ASP NET Web API之消息 拦截 处理

分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow

也欢迎大家转载本篇文章。分享知识,造福人民,实现我们中华民族伟大复兴!

               

标题相当难取,内容也许和您想的不一样,而且网上已经有很多这方面的资料了,我不过是在实践过程中作下记录。废话少说,直接开始。

Exception


当服务端抛出未处理异常时,most exceptions are translated into an HTTP response with status code 500, Internal Server Error.当然我们也可以抛出一个特殊的异常HttpResponseException,它将被直接写入响应流,而不会被转成500。

public Product GetProduct(int id){    Product item = repository.Get(id);    if (item == null)    {        throw new HttpResponseException(HttpStatusCode.NotFound);    }    return item;}

有时要对服务端异常做一封装,以便对客户端隐藏具体细节,或者统一格式,那么可创建一继承自System.Web.Http.Filters.ExceptionFilterAttribute的特性,如下:

public class APIExceptionFilterAttribute : ExceptionFilterAttribute{    public override void OnException(HttpActionExecutedContext context)    {        //业务异常        if (context.Exception is BusinessException)        {            context.Response = new HttpResponseMessage { StatusCode = System.Net.HttpStatusCode.ExpectationFailed };            BusinessException exception = (BusinessException)context.Exception;            context.Response.Headers.Add("BusinessExceptionCode", exception.Code);            context.Response.Headers.Add("BusinessExceptionMessage", exception.Message);        }        //其它异常        else        {            context.Response = new HttpResponseMessage { StatusCode = System.Net.HttpStatusCode.InternalServerError };        }    }}

然后将该Attribute应用到action或controller,或者GlobalConfiguration.Configuration.Filters.Add(new APIExceptionFilterAttribute());使之应用于所有action(If you use the "ASP.NET MVC 4 Web Application" project template to create your project, put your Web API configuration code inside the WebApiConfig class, which is located in the App_Start folder:config.Filters.Add(newProductStore.NotImplExceptionFilterAttribute());)。当然,在上述代码中,我们也可以在OnException方法中直接抛出HttpResponseException,效果是一样的。

Note: Something to have in mind is that the ExceptionFilterAttribute will be ignored if the ApiController action method throws a HttpResponseException;If something goes wrong in the ExceptionFilterAttribute and an exception is thrown that is not of type HttpResponseException, a formatted exception will be thrown with stack trace etc to the client.

如果要返回给客户端的不仅仅是一串字符串,比如是json对象,那么可以使用HttpError这个类。

以上知识主要来自Exception Handling in ASP.NET Web API

ActionFilterAttribute、ApiControllerActionInvoker 


有时要在action执行前后做额外处理,那么ActionFilterAttribute和ApiControllerActionInvoker就派上用场了。比如客户端请求发过来的参数为用户令牌字符串token,我们要在action执行之前先将其转为action参数列表中对应的用户编号ID,如下: 

public class TokenProjectorAttribute : ActionFilterAttribute{    private string _userid = "userid";    public string UserID    {        get { return _userid; }        set { _userid = value; }    }    public override void OnActionExecuting(HttpActionContext actionContext)    {        if (!actionContext.ActionArguments.ContainsKey(UserID))        {            //参数列表中不存在userid,写入日志            //……            var response = new HttpResponseMessage();            response.Content = new StringContent("用户信息转换异常.");            response.StatusCode = HttpStatusCode.Conflict;            //在这里为了不继续走流程,要throw出来,才会立马返回到客户端            throw new HttpResponseException(response);        }        //userid系统赋值        actionContext.ActionArguments[UserID] = actionContext.Request.Properties["shumi_userid"];        base.OnActionExecuting(actionContext);    }    public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)    {        base.OnActionExecuted(actionExecutedContext);    }}

ActionFilterAttribute如何应用到action,和前面的ExceptionFilterAttribute类似。

ApiControllerActionInvoker以上述Exception为例:

public class ServerAPIControllerActionInvoker : ApiControllerActionInvoker{    public override Task<HttpResponseMessage> InvokeActionAsync(HttpActionContext actionContext, CancellationToken cancellationToken)    {        //对actionContext做一些预处理        //……        var result = base.InvokeActionAsync(actionContext, cancellationToken);        if (result.Exception != null && result.Exception.GetBaseException() != null)        {            var baseException = result.Exception.GetBaseException();            if (baseException is BusinessException)            {                return Task.Run<HttpResponseMessage>(() =>                {                    var response = new HttpResponseMessage(HttpStatusCode.ExpectationFailed);                    BusinessException exception = (BusinessException)baseException;                    response.Headers.Add("BusinessExceptionCode", exception.Code);                    response.Headers.Add("BusinessExceptionMessage", exception.Message);                    return response;                });            }            else            {                return Task.Run<HttpResponseMessage>(() => new HttpResponseMessage(HttpStatusCode.InternalServerError));            }        }        return result;    }}

然后注册至GlobalConfiguration.Configuration.Services中。由于ApiControllerActionInvoker乃是影响全局的,所以若要对部分action进行包装处理,应该优先选择ActionFilterAttribute。 

DelegatingHandler


前面的拦截都发生在请求已被路由至对应的action后发生,有一些情况需要在路由之前就做预先处理,或是在响应流返回过程中做后续处理,这时我们就要用到DelegatingHandler。比如对请求方的身份验证,当验证未通过时直接返回错误信息,否则进行后续调用。

public class AuthorizeHandler : DelegatingHandler{    private static IAuthorizer _authorizer = null;    static AuthorizeHandler()    { }    protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)    {        if (request.Method == HttpMethod.Post)        {            var querystring = HttpUtility.ParseQueryString(request.RequestUri.Query);            var formdata = request.Content.ReadAsFormDataAsync().Result;            if (querystring.AllKeys.Intersect(formdata.AllKeys).Count() > 0)            {                return SendError("请求参数有重复.", HttpStatusCode.BadRequest);            }        }        //请求方身份验证        AuthResult result = _authorizer.AuthRequest(request);        if (!result.Flag)        {            return SendError(result.Message, HttpStatusCode.Unauthorized);        }        request.Properties.Add("shumi_userid", result.UserID);        return base.SendAsync(request, cancellationToken);    }    private Task<HttpResponseMessage> SendError(string error, HttpStatusCode code)    {        var response = new HttpResponseMessage();        response.Content = new StringContent(error);        response.StatusCode = code;        return Task<HttpResponseMessage>.Factory.StartNew(() => response);    }}

 参考资料:

转载请注明原文出处:http://www.cnblogs.com/newton/p/3238082.html


           

给我老师的人工智能教程打call!http://blog.csdn.net/jiangjunshow
这里写图片描述
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值