将AspNet.WebApi与AspNet.SignalR集成

时间:2014-11-28 14:42:21

标签: asp.net-web-api real-time signalr-hub signalr.client

我想将 Microsoft.AspNet.SignalR版本=" 2.1.2" Microsoft.AspNet.WebApi集成version =" 5.2.2" ,以便API可以实时通信。我发现一个VERY NICE SAMPLE实现/工作的方式与我想要的完全相同,但是示例使用了jquery.signalR-0.5.0.js。一些早期的实现已经改变,到目前为止,我已经做了很多努力来升级解决方案以使用最新的 signalr,asp.net web api和owin 。 我离开了Hub,因为它是

using SignalR.Hubs;
namespace NdcDemo.Hubs
{
    // This hub has no inbound APIs, since all inbound communication is done
    // via the HTTP API. It's here for clients which want to get continuous
    // notification of changes to the ToDo database.
    [HubName("todo")]
    public class ToDoHub : Hub { }
}

我也离开了ApiControllerWithHub类,因为它是

using System;
using System.Web.Http;
using SignalR;
using SignalR.Hubs;
namespace NdcDemo.Controllers
{
    public abstract class ApiControllerWithHub<THub> : ApiController
        where THub : IHub
    {
        Lazy<IHubContext> hub = new Lazy<IHubContext>(
            () => GlobalHost.ConnectionManager.GetHubContext<THub>()
        );
        protected IHubContext Hub
        {
            get { return hub.Value; }
        }
    }
}

对于ToDoController,我改变了

Hub.Clients.addItem(item), Hub.Clients.updateItem(toUpdate),
 Hub.Clients.deleteItem(id)

Hub.Clients.All.addItem(item), Hub.Clients.All.updateItem(toUpdate),
 Hub.Clients.All.deleteItem(id)

现在这是完整的ToDoController类

 using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Net;
    using System.Net.Http;
    using System.Threading;
    using System.Web.Http;
    using NdcDemo.Hubs;
    using NdcDemo.Models;

    namespace NdcDemo.Controllers
    {
        [InvalidModelStateFilter]
        public class ToDoController : ApiControllerWithHub<ToDoHub>
        {
            private static List<ToDoItem> db = new List<ToDoItem>
            {
                new ToDoItem { ID = 0, Title = "Do a silly demo on-stage at NDC" },
                new ToDoItem { ID = 1, Title = "Wash the car" },
                new ToDoItem { ID = 2, Title = "Get a haircut", Finished = true }
            };
            private static int lastId = db.Max(tdi => tdi.ID);
            public IEnumerable<ToDoItem> GetToDoItems()
            {
                lock (db)
                    return db.ToArray();
            }

            public ToDoItem GetToDoItem(int id)
            {
                lock (db)
                {
                    var item = db.SingleOrDefault(i => i.ID == id);
                    if (item == null)
                        throw new HttpResponseException(
                            Request.CreateResponse(HttpStatusCode.NotFound)
                        );

                    return item;
                }
            }

            public HttpResponseMessage PostNewToDoItem(ToDoItem item)
            {
                lock (db)
                {
                    // Add item to the "database"
                    item.ID = Interlocked.Increment(ref lastId);
                    db.Add(item);

                    // Notify the connected clients
                    Hub.Clients.addItem(item);

                    // Return the new item, inside a 201 response
                    var response = Request.CreateResponse(HttpStatusCode.Created, item);
                    string link = Url.Link("apiRoute", new { controller = "todo", id = item.ID });
                    response.Headers.Location = new Uri(link);
                    return response;
                }
            }

            public ToDoItem PutUpdatedToDoItem(int id, ToDoItem item)
            {
                lock (db)
                {
                    // Find the existing item
                    var toUpdate = db.SingleOrDefault(i => i.ID == id);
                    if (toUpdate == null)
                        throw new HttpResponseException(
                            Request.CreateResponse(HttpStatusCode.NotFound)
                        );

                    // Update the editable fields and save back to the "database"
                    toUpdate.Title = item.Title;
                    toUpdate.Finished = item.Finished;

                    // Notify the connected clients
                    Hub.Clients.updateItem(toUpdate);

                    // Return the updated item
                    return toUpdate;
                }
            }

            public HttpResponseMessage DeleteToDoItem(int id)
            {
                lock (db)
                {
                    int removeCount = db.RemoveAll(i => i.ID == id);
                    if (removeCount <= 0)
                        return Request.CreateResponse(HttpStatusCode.NotFound);

                    // Notify the connected clients
                    Hub.Clients.deleteItem(id);

                    return Request.CreateResponse(HttpStatusCode.OK);
                }
            }
        }
    }

然后我把app.MapSignalR(); 但该演示无效...... API无法与客户联系......我哪里出错了? 我仍然会感谢基于this solution的更简单的建议。

1 个答案:

答案 0 :(得分:0)

来自OP的

解决方案。

<强>答案: 喝了一杯洋甘菊茶之后,我发现客户必须在Todo.js的动态方法之前加入KEYWORD CLIENT ......所以,这就是那个需要修改,以便样本工作

hub.client.addItem = function (item) {
        alert("i just received something...");
        viewModel.add(item.ID, item.Title, item.Finished);
    };
    hub.client.deleteItem = function (id) {
        viewModel.remove(id);
    };
    hub.client.updateItem = function (item) {
        viewModel.update(item.ID, item.Title, item.Finished);
    };

它有效!