问题
看下下边的代码,[Range(10, 20)]
这个验证在这里永远不会生效,本文的目的就是让他生效。
public class ValuesController : ApiController
{
[HttpGet]
[ValidateModel]
public string novalid([Range(10, 20)] int id)
{
return "value";
}
}
接下来详细说明一下这种情况:
在.net下Webapi项目中如果使用到了任何ValidationAttribute
(包括StringLengthAttribute,RangeAttribute,Required等等)作为URL参数验证,则不会有效果,无论是原有的还是自己继承后的都不生效;这个验证只有在封装好的Model中才会生效,先看如下代码:
ValuesController
using System.ComponentModel.DataAnnotations;
using System.Web.Http;
namespace validation_test.Controllers
{
public class Model
{
[Range(10, 20)]
public int id { get; set; }
}
public class Model_1
{
public int id { get; set; }
}
[RoutePrefix("values")]
public class ValuesController : ApiController
{
/// <summary>
/// 方法一
/// 结果:验证不起作用
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
[Route("novalid/{id}")]
[HttpGet]
[ValidateModel]
public string novalid([Range(10, 20)] int id)
{
return "value";
}
/// <summary>
/// 方法二
/// 结果:验证起作用
/// </summary>
/// <param name="test"></param>
/// <returns></returns>
[Route("valid_model")]
[HttpPost]
[ValidateModel]
public string valid_model(Model test)
{
return "value";
}
/// <summary>
/// 方法三
/// 结果:验证不起作用
/// </summary>
/// <param name="test"></param>
/// <returns></returns>
[Route("valid_model_1")]
[HttpPost]
[ValidateModel]
public string valid_model_1([Required]Model_1 test)
{
return "value";
}
}
}
ValidateModel
using System.Net;
using System.Net.Http;
using System.Web.Http.Controllers;
using System.Web.Http.Filters;
namespace validation_test
{
public class ValidateModelAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(HttpActionContext actionContext)
{
if (actionContext.ModelState.IsValid == false)
{
actionContext.Response = actionContext.Request.CreateErrorResponse(
HttpStatusCode.BadRequest, actionContext.ModelState);
}
}
}
}
方法一返回结果:
方法二返回结果:
方法三返回结果:
在这里虽然一个方法是GET,另一个是POST,但是经过测试请求类型不改变测试结果。
从结果上看,只有方法二是触发了ValidationAttribute,但是ValidationAttribute特性是可以用于方法参数的(如下图);
也就是说:在.Net WebApi底层的架构里并没有触发Parameter的验证特性,只触发了Property的验证特性(可能也包含Field,未验证)
(MVC与WebApi是同样的情况)
不知.Net此种做法的目的是什么,还是接着看如何修复吧。
解决方案
在原来的ValuesController里新加如下:
[Route("valid/{id}")]
[HttpGet]
[ValidateParameter]
public string valid([Range(10, 20)] int id)
{
return "value";
}
ValidateParameter
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http.Controllers;
using System.Web.Http.Filters;
using System.Web.Http.ModelBinding;
namespace validation_test
{
public class ValidateParameterAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(HttpActionContext context)
{
var descriptor = context.ActionDescriptor as HttpActionDescriptor;
if (descriptor != null)
{
//取得所有参数描述集合
var parameters = descriptor.GetParameters();
foreach (HttpParameterDescriptor parameter in parameters)
{
//从请求中提取参数的值
var argument = context.ActionArguments[parameter.ParameterName];
EvaluateValidationAttributes(parameter, argument, context.ModelState);
}
}
//判断验证是否通过
if (!context.ModelState.IsValid)
{
//返回自定义信息
var result = string.Join("; ", context.ModelState.Values.SelectMany(x => x.Errors).Select(x => x.ErrorMessage));
context.Response = context.Request.CreateResponse(HttpStatusCode.OK, result);
}
base.OnActionExecuting(context);
}
private void EvaluateValidationAttributes(HttpParameterDescriptor parameter, object argument, ModelStateDictionary modelState)
{
//从当前参数中提取它所有的ValidationAttribute特性
IList<ValidationAttribute> validationAttributes = parameter.GetCustomAttributes<ValidationAttribute>();
foreach (var attributeData in validationAttributes)
{
if (attributeData != null)
{
//使用特性对参数值验证
var isValid = attributeData.IsValid(argument);
if (!isValid)
{
//验证失败后将错误信息写入ModelState
modelState.AddModelError(parameter.ParameterName, attributeData.FormatErrorMessage(parameter.ParameterName));
}
}
}
}
}
}
返回结果:
解决思路就是在方法执行前主动获取请求的参数,并取得参数中有关ValidationAttribute特性的集合,并手动验证,最后将错误信息添加至HttpActionContext.ModelState,这样即可解决WebApi或者Asp.Net MVC中ValidationAttribute无法在参数上生效的问题。
感谢:https://blog.markvincze.com/how-to-validate-action-parameters-with-dataannotation-attributes/
.
.
.
.
.
.
.
.
.
>>转载请注明原文链接地址:WebApi或Asp.Net MVC中参数验证无效