Интеграция AspNet.WebApi с AspNet.SignalR

Я хочу интегрировать Microsoft.AspNet.SignalR version="2.1.2" с Microsoft.AspNet.WebApi version="5.2.2", чтобы API мог взаимодействовать в РЕАЛЬНОМ ВРЕМЕНИ. Я нашел один ОЧЕНЬ КРАСИВЫЙ ОБРАЗЕЦ, который реализует / работает точно так же, как я хочу, но в примере используется jquery.signalR-0.5.0.js. Некоторые из ранних реализаций изменились, и до сих пор я сделал то, что я предпринял, пытаясь обновить решение для использования новейших сигнализаторов, asp.net web api и owin. Я покинул Хаб как есть

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 не связывается с клиентами... Где я иду не так?Я был бы признателен за более простые рекомендации, основанные на этом решении.

1 ответ

Решение от ОП.

Ответ: выпив чашку ромашкового чая, я обнаружил, что клиенты должны были включить КЛИЕНТ KEYWORD перед динамическими методами в Todo.js... Итак, вот что нужно изменить, чтобы пример работал

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);
    };

И это работает!

Другие вопросы по тегам