Ø  前言

目前 C# 比较流行使用 ASP.NET Web API 来承载 Web 接口,提供与客户端之间的数据交互,现在的版本已经是 2.0 了。既然是接口就少不了对输入参数的验证,所以本文主要探讨下,Web API 中实现接口参数验证的几种方式:

1.   使用 Web API 过滤器验证。

2.   继承验证基类,重写验证方法。

1.   使用 Web API 过滤器验证(Demo 演示)

1)   定义个 DataRecordValidationAttribute 类,:默认;1:成交时间由近到远;2:成交金额由高到低;3:成交可能性由高到低;4:过期未成交优先)。

/// </summary>

public int OrderBy { get; set; }

public override bool Validate(ref string message)

{

if (base.Validate(ref message))

{

if (OrderBy < 0 || OrderBy > 4)

message = "排序Key 必须介于 0 至 4 之间";

}

return string.IsNullOrEmpty(message);

}

}

3)   定义参数验证过滤器

/// <summary>

/// 参数验证。

/// </summary>

public class ParameterValidateAttribute : System.Web.Http.Filters.ActionFilterAttribute

{

/// <summary>

/// 在调用操作方法之前发生。

/// </summary>

/// <param name="actionContext">操作上下文。</param>

public override void OnActionExecuting(System.Web.Http.Controllers.HttpActionContext actionContext)

{

string validateMessage = this.GetValidateMessage(actionContext);

if (!string.IsNullOrEmpty(validateMessage))

{

//var response = new ResponseModel<object>(ResponseStatusCode.ParameterError, validateMessage, null);

//actionContext.Response = actionContext.Request.CreateResponse<ResponseModel<object>>(

//    HttpStatusCode.OK, response);

actionContext.Response = actionContext.Request.CreateResponse<string>(HttpStatusCode.BadRequest, validateMessage);

}

base.OnActionExecuting(actionContext);

}

/// <summary>

/// 根据 System.Web.Http.Controllers.HttpActionContext 对象,获取请求参数 RequestModel 派生对象的验证信息。

/// </summary>

/// <param name="actionContext">System.Net.Http.HttpRequestMessage 对象。</param>

/// <returns>验证信息。返回空表示验证成功,否则验证失败。</returns>

public string GetValidateMessage(System.Web.Http.Controllers.HttpActionContext actionContext)

{

string result = null;

try

{

Type paraBaseType = typeof(RequestModel);

var parameterList = actionContext.ActionArguments.Values.ToList();

if (parameterList == null || parameterList.Count != 2)          //参数数量不满足,则退出验证

return result;

var parameter = parameterList[1];

if(parameter == null)   //只有一个参数时,例如:(HttpRequestMessage request)

return result;

Type parameterType = parameter.GetType();

if (parameter is RequestModel)     //参数的基类型不为 RequestModel,则退出验证

{

//递归验证参数

Func<object, string, string> validate = null;

validate = (obj, mes) =>

{

var requestModel = obj as RequestModel;

if (obj != null)

{

if (requestModel.Validate(ref mes)) //为flase时,立即结束验证

{

var properties = obj.GetType().GetProperties();

foreach (var item in properties)

{

if (item.PropertyType.BaseType == paraBaseType)

{

var propObj = item.GetValue(obj, null);

mes = validate(propObj, mes);

if (!string.IsNullOrEmpty(mes))

break;

}

}

}

}

return mes;

};

result = validate(parameter, string.Empty);

}

}

catch (JsonSerializationException ex)

{

result = "参数序列化异常:{0}{1}".Fmt(

ex.InnerException != null ? ex.InnerException.Message : null, ex.Message);

}

catch (Exception ex)

{

//参数验证本身发生异常

result = "参数验证时发生异常:{0}{1}".Fmt(

ex.InnerException != null ? ex.InnerException.Message : null, ex.Message);

}

return result;

}

}

4)   注册全局验证过滤器,在 WebApiConfig.Register() 方法中加入一行代码即可。

config.Filters.Add(new ParameterValidateAttribute());

5)   添加 Action 操作方法

/// <summary>

/// 获取销售机会分页列表。

/// </summary>

/// <param name="request"></param>

/// <param name="model">分页模型。</param>

/// <returns></returns>

[Route("getSalesOpportunityPagingList")]

[System.Web.Http.HttpPost]

public HttpResponseMessage GetSalesOpportunityPagingList(HttpRequestMessage request, PagingReqModel<SalesOpportunityPagingReqModel> model)

{

return CreateHttpResponse(request, (isPaging) =>

{

return userService.GetSalesOpportunityPagingList(isPaging, base.CurrentUserId, model);

}, (data) =>

{

var response = new ResponseModel<PaginationSet<SalesOpportunityPagingResModel>>(ResponseStatusCode.OK, null, data);

var httpResponse = request.CreateResponse<ResponseModel<PaginationSet<SalesOpportunityPagingResModel>>>(HttpStatusCode.OK, response);

return httpResponse;

});

}

6)   OK,下面是调用示例

1.   调用失败(排序Key 不在范围内)

2.   调用成功

Ø  总结

1.   使用 Web API 过滤器验证

1)   优点

1.   属于 Web API 框架的一部分,应该性能较好,是一套标准化的验证机制。

2.   支持多种验证规则,例如:数据类型、邮箱、电话号码、数值范围、字符串长度、正则表达式等验证。

2)   缺点

1.   学习成本较高,比较难以控制全局(除了更进一步的封装)。

2.   有时可能不够灵活。

2.   继承验证基类,重写验证方法

1)   优点

1.   功能强大,简单易用,可自定义任意的验证规则。

2.   具有全局性,可提高一定的开发效率。

2)   缺点

1.   性能方面可能有所降低,因为会不停的反射成员属性,有时还有可能递归调用(这是无法避免的)。

3.   共同点:

1)   都是基于模型验证,且都采用了 System.Web.Http.Filters.ActionFilterAttribute 动作过滤器。

2)   非模型参数时,两者都不能实现验证。

Ø  提示:如果有同学有其他的验证方案,或更高见解,欢迎随时讨论~。

ASP.NET Web API 2 之参数验证的更多相关文章

  1. 让ASP.NET Web API支持$format参数的方法

    在不使用OData的情况下,也可以让ASP.NET Web API支持$format参数,只要在WebApiConfig里添加如下三行红色粗体代码即可: using System; using Sys ...

  2. [转]让ASP.NET Web API支持$format参数的方法

    本文转自:http://www.cnblogs.com/liuzhendong/p/4228592.html 在不使用OData的情况下,也可以让ASP.NET Web API支持$format参数, ...

  3. ASP.NET Web API中的参数绑定总结

    ASP.NET Web API中的action参数类型可以分为简单类型和复杂类型. HttpResponseMessage Put(int id, Product item) id是int类型,是简单 ...

  4. ASP.NET Web API 安全筛选器

    原文:https://msdn.microsoft.com/zh-cn/magazine/dn781361.aspx 身份验证和授权是应用程序安全的基础.身份验证通过验证提供的凭据来确定用户身份,而授 ...

  5. 【ASP.NET Web API教程】2.1 创建支持CRUD操作的Web API

    原文 [ASP.NET Web API教程]2.1 创建支持CRUD操作的Web API 2.1 Creating a Web API that Supports CRUD Operations2.1 ...

  6. 【ASP.NET Web API教程】4.3 ASP.NET Web API中的异常处理

    原文:[ASP.NET Web API教程]4.3 ASP.NET Web API中的异常处理 注:本文是[ASP.NET Web API系列教程]的一部分,如果您是第一次看本系列教程,请先看前面的内 ...

  7. ASP.NET Web API与Owin OAuth:使用Access Toke调用受保护的API

    在前一篇博文中,我们使用OAuth的Client Credential Grant授权方式,在服务端通过CNBlogsAuthorizationServerProvider(Authorization ...

  8. 【转】ASP.NET WEB API系列教程

    from: 西瓜小强 http://www.cnblogs.com/risk/category/406988.html ASP.NET Web API教程(六) 安全与身份认证 摘要: 在实际的项目应 ...

  9. 【ASP.NET Web API教程】6 格式化与模型绑定

    原文:[ASP.NET Web API教程]6 格式化与模型绑定 6 Formats and Model Binding 6 格式化与模型绑定 本文引自:http://www.asp.net/web- ...

随机推荐

  1. AWS免费EC2

    终于弄到这个EC2了.回想下过程大概如下 1.注册账号 https://amazonaws-china.com/cn/free/ 可以这地址点击"创建免费账户" 2.注册填写信息, ...

  2. luogu4159 迷路 (矩阵加速)

    考虑如果只有距离为1的边,那我用在时间i到达某个点的状态数矩阵 乘上转移矩阵(就是边的邻接矩阵),就能得到i+1时间的 然后又考虑到边权只有1~9,那可以把边拆成只有距离为1的 具体做法是一个点拆成9 ...

  3. CF739E Gosha is hunting

    法一: 匹配问题,网络流! 最大费用最大流,S到A,B流a/b费0,A,B到i流1费p[i]/u[i],同时选择再减p[i]*u[i]? 连二次!所以i到T流1费0流1费-p[i]*u[i] 最大流由 ...

  4. 上pixiv解决法(保存)

    C:\Windows\System32\drivers\etc\hosts 127.0.0.1 localhost 127.0.0.1 advstat.xunlei.com 127.0.0.1 cl. ...

  5. (转)你应该知道的RPC原理

    背景:对于项目中的RPC框架,仅仅停留在使用层面,对于其底层的实现原理不是很清楚.这样的后果是很危险的,对于面试官来说,跟不知道这个东西一样. 转载自:https://www.cnblogs.com/ ...

  6. Let's Encrypt:初次使用免费的ssl证书,并生成java用的 jks(keystore) 文件

    现在都流行 https,今天晚上花了二个小时,学习了一下,这里做个学习总结: 因为刚开始接触,就使用免费的:Let's Encrypt Let's Encrypt证书特点: 1. 现在主流的浏览器(c ...

  7. Educational Codeforces Round 53 (Rated for Div. 2) A Diverse Substring

    传送门 https://www.cnblogs.com/violet-acmer/p/10163375.html 题意: 给出串是多态的定义“长度为 n 的串 s ,当串 s 中所有字母出现的次数严格 ...

  8. TestNg-数据驱动-dataProvider

    参考https://blog.csdn.net/hjianhui24/article/details/50554828 之前的用例自己一笔一划写出来的,知道了数据驱动的概念之后,修改了一下用例. @D ...

  9. JS学习笔记Day2

    一.程序的三大结构 顺序结构:从上到下,从左到右依次执行每一条语句 选择结构:根据条件判断选择要执行的语句,出口只有一个 循环结构:满足一定条件,重复执行一段代码 二.选择结构 1.三元运算符:? : ...

  10. Luogu P3239 [HNOI2015]亚瑟王

    题目链接 \(Click\) \(Here\) 期望神题.最开始一直尝试推朴素一点的,逻辑上的\(DP\)式子,后来发现一直出锅,可能是我的式子没容斥对... 题解中给出的想法是这样的: 首先,如果直 ...