修改用户子集的传出消息

时间:2015-06-30 10:38:16

标签: c# jquery asp.net signalr

是否可以修改用户子集的外发邮件?

我现在只是原型设计,但最终的计划是我们将有两个(或更多)层用户连接到相同的集线器。集线器基本上只是重新广播客户想要发送的任何消息。

更高级别的用户应该看到所有消息。较低层的用户不应该看到所有消息,并且应该看到某些消息的编辑版本。

我正在努力弄清楚如何最好地做到这一点。我以为我使用HubPipelineModule找到了答案:

using Microsoft.AspNet.SignalR.Hubs;

namespace WebApplication9
{
    public class MsgFilter : HubPipelineModule
    {
        protected override bool OnBeforeOutgoing(IHubOutgoingInvokerContext context)
        {
            if (context.Invocation.Method == "pong")
            {
                if (((string)context.Invocation.Args[0]).Equals("goodbye"))
                {
                    context.Invocation.Args[0] = "this message has been suppressed for the good of the people";
                }
            }
            return base.OnBeforeOutgoing(context);
        }
    }
}

(最终,过滤将需要确定有关已连接用户的信息,但我还没有)

Startup期间已安装的内容:

using Microsoft.AspNet.SignalR;
using Owin;

namespace WebApplication9
{
    public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            app.MapSignalR();
            GlobalHost.HubPipeline.AddModule(new MsgFilter());
        }
    }
}

中心看起来像:

using Microsoft.AspNet.SignalR;

namespace WebApplication9
{
    public class PingHub : Hub
    {
        public void Send(dynamic message)
        {
            Clients.All.pong(message);
        }
    }
}

(这最终会转移到特定群组内的广播,而不是转到所有客户端)

然后,我在MVC Controller的视图中有以下代码:

@model dynamic

@{
  ViewBag.Title = "title";
}

<h2>title</h2>

<input id="message" type="text" />
<input id="send" name="send" value="Send" type="button" />

<div id="messages"></div>

@section scripts
{
<script src="~/Scripts/jquery.signalR-2.2.0.js"></script>
<script src="~/signalr/hubs"></script>
<script>
  $(function () {
    // Reference the auto-generated proxy for the hub.  
    var ping = $.connection.pingHub;
    // Create a function that the hub can call back to display messages.
    ping.client.pong = function (message) {
      // Add the message to the page. 
      $('#messages').append('<li>' + htmlEncode(message) + '</li>');
    };
    // Start the connection.
    $.connection.hub.start().done(function () {
      $('#send').click(function () {
        // Call the Send method on the hub. 
        ping.server.send($('#message').val());
        // Clear text box and reset focus for next comment. 
        $('#message').val('').focus();
      });
    });
  });
  // This optional function html-encodes messages for display in the page.
  function htmlEncode(value) {
    var encodedValue = $('<div />').text(value).html();
    return encodedValue;
  }
</script>
}

(控制器方法本身只是Return View();

但是,当我启动两个浏览器时,请在一个浏览器中输入一条消息并按Send,我预期 OnBeforeOutgoing中的代码将被调用两次,每次连接一次。情况并非如此,它只被调用一次。

问题

因此,这似乎是实现过滤器的错误位置,该过滤器将影响一个连接而不会影响另一个。

我的理解错了吗?我应该使用不同的扩展点吗?

工具组:

VS 2012,清空ASP.NET应用程序,然后安装以下软件包:

<packages>
  <package id="Antlr" version="3.4.1.9004" targetFramework="net45" />
  <package id="bootstrap" version="3.0.0" targetFramework="net45" />
  <package id="jQuery" version="2.1.4" targetFramework="net45" />
  <package id="jQuery.Validation" version="1.13.1" targetFramework="net45" />
  <package id="Microsoft.AspNet.Mvc" version="5.0.0" targetFramework="net45" />
  <package id="Microsoft.AspNet.Razor" version="3.0.0" targetFramework="net45" />
  <package id="Microsoft.AspNet.SignalR" version="2.2.0" targetFramework="net45" />
  <package id="Microsoft.AspNet.SignalR.Core" version="2.2.0" targetFramework="net45" />
  <package id="Microsoft.AspNet.SignalR.JS" version="2.2.0" targetFramework="net45" />
  <package id="Microsoft.AspNet.SignalR.SystemWeb" version="2.2.0" targetFramework="net45" />
  <package id="Microsoft.AspNet.Web.Optimization" version="1.1.1" targetFramework="net45" />
  <package id="Microsoft.AspNet.WebPages" version="3.0.0" targetFramework="net45" />
  <package id="Microsoft.jQuery.Unobtrusive.Validation" version="3.0.0" targetFramework="net45" />
  <package id="Microsoft.Owin" version="2.1.0" targetFramework="net45" />
  <package id="Microsoft.Owin.Host.SystemWeb" version="2.1.0" targetFramework="net45" />
  <package id="Microsoft.Owin.Security" version="2.1.0" targetFramework="net45" />
  <package id="Microsoft.Web.Infrastructure" version="1.0.0.0" targetFramework="net45" />
  <package id="Modernizr" version="2.6.2" targetFramework="net45" />
  <package id="Newtonsoft.Json" version="6.0.4" targetFramework="net45" />
  <package id="Owin" version="1.0" targetFramework="net45" />
  <package id="WebGrease" version="1.5.2" targetFramework="net45" />
</packages>

当人们出席XY problems时,我总是抱怨,在重新阅读上述内容时,我意识到自己可能会自我介绍。

我们正在考虑将SignalR设置为一般的“事件通知”机制,既适用于使用各种内部应用程序的员工,也适用于供应商和客户也可以访问。

大多数活动都涉及到个别客户,因此计划是让人们访问特定客户的帐户,以加入以该客户的参考编号命名的组。然后,当有人对该客户进行更改时,他们会向该组发布事件。

但是,并非所有发生在客户账户上的活动都必须对外部各方(客户本人或我们的供应商)可见 - 这些是否需要相同的访问规则尚未确定。此外,并非所有附加的信息都必须发布(例如,在内部,我们可能需要知道“Joe Blogs”,一名员工,只是做了X,但我们可能希望将其更改为“乔(客户服务)”以便不透露员工的个人信息)

2 个答案:

答案 0 :(得分:2)

回答第一个问题:不,我不认为您可以干扰广播的消息,以便根据所寻址的用户修改其内容(说从集线器的角度来看)。

从集线器中提供的机制来看,我认为唯一的方法是跟踪连接ID,然后使用具有排除的连接ID列表(外部用户)的组呼,以仅针对特定用户。这是在不知道在特定情况下处理连接和重新连接有多困难的情况下说明的。

如果他在内部用户中,则每个连接的用户都会被添加到集合中。然后,内部用户需要调用另一个服务器方法,他需要被授权从排除列表中删除(从客户端触发的额外授权)。

str

向项目所有成员发送广播消息将导致:

[Authorize]
public void RegisterAsTeamMember()
{
      if (!IDs.Any(u => u == Context.ConnectionId))
      {
           IDs.Remove(Context.ConnectionId);
      }
}

如果是独家消息:

Clients.Group("[customer]").broadcastMessage(name, message);

我知道这不是一种优雅的方式。我甚至宁愿考虑我在评论中建议的团体名称惯例,但我很高兴与您讨论或听到您已经考虑过这一点。

答案 1 :(得分:0)

也许你应该使用membershipprovider和roleprovider,并使用'RoleProvider.IsUserInRole'根据订阅者角色修改消息。