是否可以对查询参数使用Web API模型验证?

时间:2016-02-24 00:55:01

标签: c# asp.net asp.net-mvc model-binding model-validation

我目前正在尝试编写一个Web API应用程序,其中我要验证的参数之一是查询参数(也就是说,我希望以val accum1:Accumulable[a] val accum2: Accumulable[b] val accum3: Accumulable[c] data.foreach{ u => accum1+=u accum2 += u accum3 += u } 的形式传递它):

/route?offset=0&limit=100

特别是,我想确保"偏移"大于0,因为负数会导致数据库抛出异常。

我直接采用了附加[HttpGet] public async Task<HttpResponseMessage> GetItems( int offset = 0, int limit = 100) { if (!ModelState.IsValid) { // Handle error } // Handle request } 的逻辑方法:

ValidationAttribute

这根本不会导致任何错误。

经过对ASP.NET的大量痛苦调试后,在我看来,这可能根本不可能。特别是,因为[HttpGet] public async Task<HttpResponseMessage> GetItems( [Range(0, int.MaxValue)] int offset = 0, int limit = 100) { if (!ModelState.IsValid) { // Handle error } // Handle request } 参数是方法参数而不是字段,offset是使用ModelMetadata而不是GetMetadataForType创建的,这意味着GetMetadataForProperty将是PropertyName。反过来,这意味着null调用AssociatedValidatorProvider,它使用一个空的属性列表,即使参数上有属性。

我甚至没有看到以这样的方式编写自定义GetValidatorsForType的方法来获取该信息,因为这是一个函数参数的信息似乎早已丢失。一种方法可能是从ModelValidatorProvider类派生并使用自定义ModelMetadata,但基本上没有任何此代码的文档,因此它将是一个crapshoot它实际上工作正常,我必须复制所有ModelMetadataProvider逻辑。

有人能证明我错了吗?有人可以告诉我如何获得验证来处理参数,类似于DataAnnotationsModelValidatorProvider在MVC中的工作方式吗?或者是否有另一种绑定查询参数的方法可以使验证正常工作?

3 个答案:

答案 0 :(得分:3)

您可以使用这两个属性创建 视图 请求模型类,并在属性上应用验证属性。

public class Req
{
    [Range(1, Int32.MaxValue, ErrorMessage = "Enter number greater than 1 ")]
    public int Offset { set; get; }

    public int Limit { set; get; }
}

在您的方法中,将其用作参数

public HttpResponseMessage Post(Req model)
{
    if (!ModelState.IsValid)
    {
       // to do  :return something. May be the validation errors?
        var errors = new List<string>();
        foreach (var modelStateVal in ModelState.Values.Select(d => d.Errors))
        {
            errors.AddRange(modelStateVal.Select(error => error.ErrorMessage));
        }
        return Request.CreateResponse(HttpStatusCode.OK, new { Status = "Error", 
                                                                       Errors = errors });
    }
    // Model validation passed. Use model.Offset and Model.Limit as needed
    return Request.CreateResponse(HttpStatusCode.OK);
}

当请求到来时,默认模型绑定器会将请求参数(limitoffset(假设它们是请求的一部分)映射到Req类的对象并且您将能够调用ModelState.IsValid方法。

答案 1 :(得分:1)

对于 .Net 5.0 和验证查询参数

using System.ComponentModel.DataAnnotations;

namespace XXApi.Models
{
    public class LoginModel
    {
        [Required]
        public string username { get; set; }
        public string password { get; set; }
    }
}
namespace XXApi.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class LoginController : ControllerBase
    {
        [HttpGet]
        public ActionResult login([FromQuery] LoginModel model)
        {
             //.Net automatically validates model from the URL string
             //and gets here after validation succeeded
        }
    }
}

答案 2 :(得分:0)

  if (Offset < 1)
        ModelState.AddModelError(string.Empty, "Enter number greater than 1");
    if (ModelState.IsValid)
    {
    }