SignalR: соединение должно быть запущено до отправки данных.Вызовите .start () перед .send () - PullRequest
0 голосов
/ 23 марта 2012

Только недавно начал использовать SignalR, и у меня это работало несколько дней назад, и теперь я не могу определить, что пошло не так.

У меня есть концентратор:

[HubName("roleManagementHub")]
public class RoleManagementHub : GenericHub<RoleManagementRole>
{
    public RoleManagementHub(ICurrentlyViewingUserService service) : base(service)
    {
    }
}

, который расширяет общийхаб, который я создал:

public class GenericHub<TEntity> : Hub where TEntity : class, IBusinessObject<TEntity>
{
    private readonly ICurrentlyViewingUserService service;

    public GenericHub(ICurrentlyViewingUserService service)
    {
        this.service = service;
    }

    public void ImViewing(string id)
    {
        string colour;
        service.AddCurrentlyViewingUser<TEntity>(id, HttpContext.Current.User.Identity.Name, out colour);
        Clients.handleImViewingMessage(HttpContext.Current.User.Identity.Name, colour, id);
    }

    public void ImLeaving(string id)
    {
        service.RemoveCurrentlyViewingUser<TEntity>(id, HttpContext.Current.User.Identity.Name);
        Clients.handleImLeavingMessage(HttpContext.Current.User.Identity.Name, id);
    }

    public void IHaveEdited(string id, string property, string content)
    {
        string colour = service.GetCurrentlyViewingUserColour<TEntity>(id, HttpContext.Current.User.Identity.Name);

        if (string.IsNullOrEmpty(colour))
            return;

        Clients.handleIHaveEdited(id, property, content);
    }
}

Я включаю <script type="text/javascript" src="@Url.Content("~/signalr/hubs")"></script>.

Теперь к основному javascript.Я создал многократно используемый компонент Knockout JS, который использует концентратор для подключения соответствующих обработчиков.Многое из этого не имеет значения, но я думал, что выложу все это просто в случае.Я запускаю соединение в начале закрытия и создаю свой компонент выбивки, передавая его в roleManagementHub.

var user_role_edit = {};

    (function (index) {

        user_role_edit = index;

        jQuery.connection.hub.start();

        var val = ko.setupValidation([], []);
        val.createErrorCollections({Name: 0, General: 0}, index, 'rename-role-form');
        var dmp = new diff_match_patch();

        index.Id = ko.observable();
        index.Name = ko.observable();
        index.currentViewersViewModel = new ko.currentlyViewingComponent.viewModel({
            hub: jQuery.connection.roleManagementHub,
            id: index.Id,
            modalSelector: '#user-role-edit-modal'
        });

        index.rename = function (form) {
            jQuery.post('" + @Url.Action("Rename", "RoleManagement") + @"', {
                'id': index.Id(),
                'name': index.Name()
            }, function (dataReturned) {
                if (dataReturned.IsValid) {
                    jQuery(document).trigger('userRoleUpdated', index);
                    index.editModal.modal('hide');
                }
                else {
                    val.rebindValidations({Name: 0, General: 0}, index, dataReturned.Errors);   
                }
            });
        };

        index.raiseClose = function () {
            index.editModal.modal('hide');
        };

        index.raiseDetails = function () {
            jQuery(document).trigger('userRoleDetails', [index]);
            index.editModal.modal('hide');
        }

        jQuery(document).bind('userRoleEdit', function (event, id) {

            jQuery.getJSON('" + @Url.Action("GetNewsArticleForUpdateOrDelete", "RoleManagement") + @"', { id: id }, function (data) {

                index.Id(data.Role.Id);
                index.Name(data.Role.Name);

                index.currentViewersViewModel.initialiseCurrentViewers(data.CurrentlyViewingUsers);

                val.clearValidations({Name: 0, General: 0}, index);
                index.editModal.modal('show');
            });
        });

        jQuery.connection.roleManagementHub.handleIHaveEdited = function(id, property, content) {
            if (index.Id() != id)
                return;

            if (index[property] == undefined)
                return;

            dmp.Match_Distance = 1000;
            dmp.Match_Threshold = 0.5;
            dmp.Patch_DeleteThreshold = 0.5;

            var patches = dmp.patch_make(index[property](), content);
            var results = dmp.patch_apply(patches, index[property]());
            index[property](results[0]);
        };

        jQuery(function () {
            ko.applyBindings(index, jQuery('#user-role-edit-container')[0]);
            index.editModal = jQuery('#user-role-edit-modal').modal({ backdrop: true, closeOnEscape: true, modal: true, show: false });

            jQuery('#rename-role-form > fieldset > div > div > input#Name').blur(function(event) {
                jQuery.connection.roleManagementHub.iHaveEdited(index.Id(), 'Name', index.Name());
            });
        });
    } (user_role_edit));");

Вот компонент выбивки:

(function () {

function currentUserViewModel(username, colour) {
    this.Username = username;
    this.Colour = colour;
}

ko.currentlyViewingComponent = {
    // Defines a view model class you can use to populate a grid
    viewModel: function (configuration) {

        this.currentViewers = ko.observableArray([]);

        var index = this;

        this.initialiseCurrentViewers = function (currentUsers) {

            index.currentViewers.removeAll();

            ko.utils.arrayForEach(currentUsers, function (item) {
                index.currentViewers.push(new currentUserViewModel(item.Username, item.Colour));
            });
        };

        configuration.hub.handleImViewingMessage = function (username, colour, id) {
            if (configuration.id() != id)
                return;

            var findResult = ko.utils.arrayFirst(index.currentViewers(), function (item) {
                return item.Username == username;
            });

            if (findResult == null)
                index.currentViewers.push(new currentUserViewModel(username, colour));

            jQuery('a[rel=tooltip]').tooltip();
        };

        configuration.hub.handleImLeavingMessage = function (username, id) {
            if (configuration.id() != id)
                return;

            index.currentViewers.remove(function (item) {
                return item.Username == username;
            });
        };

        jQuery(configuration.modalSelector).bind('show', function () {
            configuration.hub.imViewing(configuration.id());
        });

        jQuery(configuration.modalSelector).bind('hide', function () {
            configuration.hub.imLeaving(configuration.id());
        });
    }
};

// Templates used to render the grid
var templateEngine = new ko.nativeTemplateEngine();

templateEngine.addTemplate = function (templateName, templateMarkup) {
    document.write("<script type='text/html' id='" + templateName + "'>" + templateMarkup + "<" + "/script>");
};

templateEngine.addTemplate("ko_currentlyViewing", "<div data-bind=\"foreach: currentViewers\" class=\"pull-left\"><a data-bind=\"attr: { title: Username, 'class': Colour }\" rel='tooltip'>&nbsp;</a></div>");

ko.bindingHandlers.currentlyViewingComponent = {
    init: function () {
        return { 'controlsDescendantBindings': true };
    },
    // This method is called to initialize the node, and will also be called again if you change what the grid is bound to
    update: function (element, viewModelAccessor, allBindingsAccessor) {
        var viewModel = viewModelAccessor(), allBindings = allBindingsAccessor();

        // Empty the element
        while (element.firstChild)
            ko.removeNode(element.firstChild);

        // Allow the default templates to be overridden
        var currentlyViewingTemplateName = allBindings.currentlyViewingTemplate || "ko_currentlyViewing";

        // Render the main grid
        var currentlyViewingContainer = element.appendChild(document.createElement("DIV"));
        ko.renderTemplate(currentlyViewingTemplateName, viewModel, { templateEngine: templateEngine }, currentlyViewingContainer, "replaceNode");
    }
};

}) ();

Как вы можете видеть на модальном шоу, он отправляет сообщение с помощью концентратора, чтобы сообщить другим подключенным пользователям, что пользователи начали просматривать этот элемент.

Однако меня сейчас приветствует "SignalR".: Соединение должно быть установлено перед отправкой данных. Вызовите .start () перед .send () ".

Я уже установил соединение!Также, даже если я попытаюсь;

jQuery(function() {
        jQuery.connection.hub.start();
        jQuery.connection.userManagementHub.imViewing("1");
    });

Я получаю Соединение должно быть запущено, прежде чем данные могут быть отправлены сообщения.

Любые идеи ??

Спасибо заранее!

Джон

1 Ответ

10 голосов
/ 23 марта 2012

Звонок на start() не мгновенный и может быть причиной вашей проблемы. Возможно, вы захотите переместить код, который должен произойти после запуска, в обратный вызов метода start, например:

jQuery(function(){
    jQuery.connection.hub.start(function(){
         jQuery.connection.userManagementHub.imViewing("1");
    });
});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...