SignalR:必须先启动连接,然后才能发送数据。 .send()之前调用.start()

时间:2012-03-22 22:31:26

标签: c# knockout.js signalr

直到最近才开始使用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组件,它接收集线器以连接相关的处理程序。很多这都是无关紧要的,但我想我会把它全部发布。我在闭包开始时开始我的连接,并创建我的knockout组件传递给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:必须先启动连接才能发送数据。在.send()之前调用.start()”。

我已经开始连接了!即使我尝试也是如此;

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

我得到Connection必须在数据发送之前启动消息。

任何想法??

先谢谢!

乔恩

1 个答案:

答案 0 :(得分:10)

start()的来电不是即时的,可能是您问题的原因。您可能希望将启动后应该发生的代码移动到start方法中的回调中,如:

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