SignalR框架的方法返回值及异常捕获

方法返回值

Hub 的方法支持异步,方法声明为async Task<T>就可以了。如果Hub 中调用了异步的方法,那么一定要写成async。不能用TestAsync().Result 这种写法,否则Hub 方法只能调用一次就卡住了,后续调用就没反应了,不要使用WebClient 的异步,都换用HttpClient

Hub服务端

using Microsoft.AspNet.SignalR;

namespace SignalRApp
{
    public class MyResult
    {
        public int code { get; set; }
        public string msg { get; set; }
    }
    public class MyHub : Hub
    {
        public MyResult SendMsg()
        {
            var userName = Context.QueryString["userName"];
            var password = Context.QueryString["password"];

            MyResult r = null;
            if (userName == "admin" && password == "123456")
            {
                //在服务端端中,我们自定义个onSendMessage事件,这个事件就是向客户端发送一个“大家好”
                Clients.All.onSendMessage("大家好");

                r = new MyResult() { code = 200, msg = "调用成功" };
            }
            else
            {
                r = new MyResult() { code = 400, msg = "调用失败" };
            }

            return r;
        }
    }
}

浏览器客户端

<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>Index</title>
    <script src="~/Scripts/jquery-1.10.2.js"></script>
    <script src="~/Scripts/jquery.signalR-2.1.2.js"></script>
    <script src="/signalr/hubs" type="text/javascript"></script>
</head>
<body>
    <div> 
        <input type="button" value="调用方法"  id="sendMsg"/>
    </div>
    <script type="text/javascript">
        $(function () {
            //这里是监听hub服务端给我(客户端)发动的消息(即:服务端调用onSendMessage方法,或者说服务端触发onSendMessage事件)
            //当然我们也可以不监听。也可以监听。(如果不想监听这段代码可以不要)
            $.connection.myHub.client.onSendMessage = function (msg) {
                alert("消息来了:"+msg)
            }

            $.connection.hub.qs = { userName: "admin", password: "123456" };

            $.connection.hub.start().done(function () {
                alert("连接MyHub成功");
            }).fail(function () { alert("连接MyHub失败") });


            $("#sendMsg").click(function () {
                //这里是调用服务端的sendMsg方法
                $.connection.myHub.server.sendMsg().done(function (data) {
                    //在done中可以拿到服务端的方法返回值
                    //这个返回值一般是用来判断这次调用的成功或者是失败,及如果失败的话,失败的原因是什么
                    //例如你是否有权限调用这个方法,如果没有权限,服务端则会返回一个对应的调用失败代码
                    //即:这个成功或者是失败是指业务层面的成功或者失败,并不是程序常出现错误

                    alert(data.code + data.msg);
                })
            })
          
        })
        
    </script>
</body>
</html>

异常捕获

Hub 的方法中如果发生异常, 可以在fail() 回调方法中得知:hub.test().done(function(){alert(“成功”);}).fail(function(){alert(“错误);});
虽然SignalR 是在ASP.Net 项目中运行的,但是Hub 中的未处理异常是不会被MVC 的,ExceptionFilter 截获的。在服务器端可以通过自定义HubPipelineModule 来在服务器端捕获未处理异常,然后记录到日志等:

1>首先编写类继承自HubPipelineModule

public class ExceptionHubPipelineModule : HubPipelineModule
{
    protected override void OnIncomingError(ExceptionContext exceptionContext,
    IHubIncomingInvokerContext invokerContext)
    {
        //exceptionContext.Error; 就是异常对象可以记录到日志中
    }
}

2>在Global 的Application_Start() 中编写GlobalHost.HubPipeline.AddModule(new ExceptionHubPipelineModule ());

namespace SignalRApp
{
    public class MvcApplication : System.Web.HttpApplication
    {
        protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();
            RouteConfig.RegisterRoutes(RouteTable.Routes);

            //编写以下代码:
            GlobalHost.HubPipeline.AddModule(new ExceptionHubPipelineModule());
        }
    }
}

3>像上面讲的,未处理异常可以在客户端每个方法的fail 中得知,如果想统一在客户端得知异常,那么可以在浏览器端写一个function,然后在服务器端调用这个function。比如浏览器端start 之前写一个

<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>Index</title>
    <script src="~/Scripts/jquery-1.10.2.js"></script>
    <script src="~/Scripts/jquery.signalR-2.1.2.js"></script>
    <script src="/signalr/hubs" type="text/javascript"></script>
</head>
<body>
    <div> 
        <input type="button" value="调用方法"  id="sendMsg"/>
    </div>
    <script type="text/javascript">
        $(function () {
            //这里是监听hub服务端给我(客户端)发动的消息(即:服务端调用onSendMessage方法,或者说服务端触发onSendMessage事件)
            //当然我们也可以不监听。也可以监听。(如果不想监听这段代码可以不要)
            //$.connection.myHub.client.onSendMessage = function (msg) {
            //    alert("消息来了:"+msg)
            //}

            //$.connection.hub.qs = { userName: "admin", password: "123456" };

            //获取从服务端发送过来的未处理异常信息
            $.connection.myHub.client.onGlobalServerError = function (errMsg) {
                alert("这里可以得到我们在服务端自定义ExceptionHubPipelineModule类中捕获的未处理异常" + errMsg);
            }

            

            $.connection.hub.start().done(function () {
                alert("连接MyHub成功");
            }).fail(function () { alert("连接MyHub失败") });


            //$("#sendMsg").click(function () {
            //    //这里是调用服务端的sendMsg方法
            //    $.connection.myHub.server.sendMsg().done(function (data) {
            //        //在done中可以拿到服务端的方法返回值
            //        //这个返回值一般是用来判断这次调用的成功或者是失败,及如果失败的话,失败的原因是什么
            //        //例如你是否有权限调用这个方法,如果没有权限,服务端则会返回一个对应的调用失败代码
            //        //即:这个成功或者是失败是指业务层面的成功或者失败,并不是程序常出现错误

            //        alert(data.code + data.msg);
            //    })
            //})
          
        })
        
    </script>
</body>
</html>

然后ExceptionHubPipelineModule 中写

namespace SignalRApp
{
    public class ExceptionHubPipelineModule: HubPipelineModule
    {
        /// <summary>
        /// 捕获Hub的客户端
        /// </summary>
        /// <param name="exceptionContext">exceptionContext里面有异常消息</param>
        /// <param name="invokerContext"></param>
        protected override void OnIncomingError(ExceptionContext exceptionContext, IHubIncomingInvokerContext invokerContext)
        {

            //base.OnIncomingError(exceptionContext, invokerContext);
            //todo:将错误记录到Log4Net,或者分布式日记服务器

            //所有连接的客户端
            dynamic caller = invokerContext.Hub.Clients.Caller;
            //自定义一个onGlobalServerError方法,将异常信息发送到客户端(一般情况下不需要把异常消息告诉客户端,只要告诉客户端出错消息编号就好了,这里仅仅是演示)
            caller.onGlobalServerError(exceptionContext.Error.Message);
            
        }
    }
}

猜你喜欢

转载自blog.csdn.net/Fanbin168/article/details/81153277