ASP.NET Web API之消息[拦截]处理(转)

出处:http://www.cnblogs.com/Leo_wl/p/3238719.html

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

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);}
}
复制代码
复制代码

 参考资料:

  • ASP.NET Web API Exception Handling
  • Implementing message handlers to track your ASP.NET Web API usage
  • MVC4 WebAPI(二)——Web API工作方式
  • Asp.Net MVC及Web API框架配置会碰到的几个问题及解决方案

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

转载于:https://www.cnblogs.com/smileberry/p/7093326.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/254208.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

无人驾驶遇见人工智能 百度将推有“大脑”的汽车

在日前举行的中国云计算大会&#xff0c;百度高级副总裁、技术战略委员会主席王劲表示&#xff0c;百度将在今年下半年推出无人驾驶汽车。不过&#xff0c;百度自己并不会造车&#xff0c;它将与第三方汽车厂商合作制造。据介绍&#xff0c;百度将利用现有的大数据、地图、人工…

AdlinkMotionCardLibrary函数C++

#include "stdafx.h" #include "AdlinkMotionCardLibrary.h"extern "C" _declspec(dllexport) bool _stdcall MotionCardIni(I32& BoardId_InBits, I32 Mode) { try{//mode0&#xff1a;&#xff1a; 系统指定卡号 mode1&#xff1a;&am…

查看表的结构

describe 表名转载于:https://www.cnblogs.com/dengyg200891/p/5966565.html

定制一个网络文件系统

定制一个网络文件系统【把pc上的文件系统挂接到开发板上面】 1、修改exports文件【PC上】一定要修改&#xff0c;否则不会成功 vi /etc/exports 修改为 /空格* 并保存 2、设置开发板上的IP地址 ifconfig eth0 192.168.0.11 up 3、设置PC上的IP地址 ifconfig et…

创建Hbase Hive外部表报错: Unable to determine ZooKeeper ensemble

创建HBase的Hive外部表1: create external table ttt(rowkey string,info map<string,string>)STORED BY org.apache.hadoop.hive.hbase.HBaseStorageHandler WITH SERDEPROPERTIES ("hbase.columns.mapping" ":key,info:") TBLPROPERTIES ("h…

死磕算法之快速排序

版权声明&#xff1a;本文为博主原创文章&#xff0c;未经博主允许不得转载。博客源地址为zhixiang.org.cn https://blog.csdn.net/myFirstCN/article/details/80851021 学习更多算法系列请参考文章&#xff1a;死磕算法之汇总篇 快速排序是一个运用了分治法和递归算法的排序方…

九点标定进行仿射变换halcon仿真代码

筛选出来的点得坐标已经显示在PxRow、PxColunm里边 * Image Acquisition 01: Code generated by Image Acquisition 01 read_image (Image, C:/Users/Administrator/Desktop/标定板图片.png) dev_close_window () dev_open_window_fit_image (Image, 0, 0, -1, -1, WindowHand…

用SQL语句添加删除修改字段_常用SQL

1.增加字段 alter table docdsp add dspcodechar(200)2.删除字段 ALTER TABLE table_NAME DROP COLUMNcolumn_NAME3.修改字段类型 ALTER TABLE table_name ALTER COLUMNcolumn_name new_data_type4.sp_rename 改名 EXEC sp_rename [dbo].[Table_1].[fi…

DAVINCI开发原理之三----达芬奇编解码引擎Codec Engine(CE)

DaVinci是DSP和ARM 双核架构的SOC芯片。对芯片与外界的交互通过ARM端的Montavista Linux和相关驱动与应用程序来管理&#xff0c; DSP端只处理编解码相关的算法。DSP和ARM之间的通讯和交互是通过引擎(Engine)和服务器(Server)来完成的。1. 编解码引擎(Codec Engine) a. 核心引…

Windows操作系统安全加固

本文档旨在指导系统管理人员或安全检查人员进行Windows操作系统的安全合规性检查和配置。 1. 账户管理和认证授权 1.1 账户 默认账户安全 禁用Guest账户。禁用或删除其他无用账户&#xff08;建议先禁用账户三个月&#xff0c;待确认没有问题后删除。&#xff09;操作步骤 打开…

ios修改了coredata数据结构后,更新安装会闪退

如果iOS App 使用到CoreData&#xff0c;并且在上一个版本上有数据库更新&#xff08;新增表、字段等操作&#xff09;&#xff0c;那在覆盖安装程序时就要进行CoreData数据库的迁移&#xff0c;具体操作如下&#xff1a; 1.选中你的mydata.xcdatamodeld文件&#xff0c;选择菜…

TI DAVINCI开发原理(总共5部分)

2011-06-03 11:14:17| 分类&#xff1a; TI 达芬奇视频处 | 标签&#xff1a; |字号大中小订阅 DAVINCI开发原理之一----ARM端开发环境的建立(DVEVM) 1. 对DAVINCI平台&#xff0c;TI在硬件上给予双核架构强有力的支撑&#xff0c;在DSP端用DSP/BIOS来支持音视频算法的运行…

数据库代码写法

1.创建数据库create database test2; 2.删除数据库drop database test2; 3.创建表 create table ceshi (ids int auto_increment primary key,uid varchar(20),name varchar(20),class varchar(20),foreign key (class) references class(code) ); create table class (code …

random库的使用

有关Python中random标准库的使用 Python中关于随机值的部分&#xff0c;借助的是根据当前的随机种子&#xff0c;通过梅森旋转算法&#xff0c;生成一段随机序列。 基本随机函数 random.seed(aNone)初始化给定的随机种子&#xff0c;默认值为当前的系统时间。 random.random()生…

ThinkPHP--栏目增删改查ADSF

<?php /*** 栏目发布*/ //V层&#xff0c;action/name值 action " :U( Admin/Cat/Cateadd )";/*** 添加栏目数据* C层&#xff0c;写相应的方法进行数据添加*/ public function add(){if(!IS_POST){$this->display();}else{//var_dump($_POST);$catModelD…

模拟查找晶元的位置

通过模板匹配找到所有模板位置&#xff0c;并且当单击某个模板时&#xff0c;选中某个模板 read_image (Image, C:/Users/22967/Desktop/晶圆找位置/0.bmp) dev_close_window () dev_open_window_fit_image (Image, 0, 0, -1, -1, WindowHandle) dev_display (Image)* draw_cir…

JavaScript常用函数之Eval()使用

eval() 功能&#xff1a;首先解释Javascript代码 然后执行它 用法&#xff1a;Eval&#xff08;codeString&#xff09; codeString是包含有javascript语句的字符串&#xff0c;在eval之后使用Javascript引擎编译。即&#xff1a;eval函数可以把一个字符串当作一个javascript表…

初探数位dp

前言&#xff1a;这是蒟蒻第一次写算法系列&#xff0c;请诸位大佬原谅文笔与排版。 一、导入 在刷题的时候&#xff0c;我们有时会见到这样一类问题&#xff1a;在区间$[l,r]$内&#xff0c;共有多少个整数满足某种条件。如果$l$和$r$间的差很小&#xff0c;我们可以考虑暴力枚…

Java演示手机发送短信验证码功能实现

我们这里采用阿里大于的短信API 第一步&#xff1a;登陆阿里大于&#xff0c;下载阿里大于的SDK a、在阿里大于上创建自己的应用 b、点击配置管理中的验证码&#xff0c;先添加签名&#xff0c;再配置短信模板 第二步&#xff1a;解压相关SDK&#xff0c;第一个为jar包&#xf…

使用标定板对相机位姿进行估计

使用标定板几个特定的点&#xff0c;来对相机相对标定板平面进行位姿估计。 首先进行相机的畸变校正&#xff0c;之后同个各个标定板间的圆点距离进行位姿估计。 gen_caltab (7, 7, 0.002, 0.5, C:/Users/22967/Desktop/新建文件夹/111.descr, C:/Users/22967/Desktop/新建文件…