在WebApi2中使用模型验证

很多时候我们在接收到客户端提交过来的请求之前,要验证一下数据合法性再执行操作。

 

数据注解Data Annotations

    WepApi中可以使用System.ComponentModel.DataAnnotations命名空间的属性,在你的model类中设置属性,来实现验证。

考虑以下场景:

using System.ComponentModel.DataAnnotations;

namespace MyApi.Models
{
   
public class Product
    {
       
public int Id { get; set; }
        [
Required]
       
public string Name { get; set; }
       
public decimal Price {get; set;}
        [
Range(0, 999)]
       
public double Weight { get; set; }
    }
}

    如果你在MVC中使用过模型验证,那么看起来很眼熟,[Required]特性表示Name不能为null[Range]特性表示Weight必须在0-999范围内。

    假设收到客户端POST过来的json数据:

{ "Id":4, "Price":2.99, "Weight":5 }

    我们可以看到数据并没有包含Name,而Name我们是标记了[Required]特性的。当WebApi将其转换为Product实体的时候,就会发生验证冲突。

    在你的Action中可以验证Model是否合法:

         public class ProductsController : ApiController
    {
       
public HttpResponseMessagePost(Product product)
        {
           
if (ModelState.IsValid)
            {
               
// Dosomething with the product (not shown).

                                      returnnew HttpResponseMessage(HttpStatusCode.OK);
            }
           
else
            {
               
return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState);
            }
        }
    }

 

   但是模型验证不能保证完全不会出现问题,所以你需要在程序的其他层中增加验证,比如在Model层增加外键关联等等(EF)。

如果你使用的是EF可以参照文章Using Web API withEntity Framework,其中介绍了很多类似的问题。

 

Under-Posting”(参数缺失)

    传过来的数据中参数缺失的情况,例如:

   

   {"Id":4, "Name":"Gizmo"} 这里没有传PirceWeight参数,此时Json Formatter会指定默认的值;

 

"Over-Posting"(参数多余)

    传过来的参数多

        {"Id":4, "Name":"Gizmo", "Color":"Blue"}

 

    可以看到传过来一个不存在Color属性,既然这样,formatter会忽略该值,XMLformatter也一样。

 

 

注意,当你打算将某个属性作为只读属性的时候可能有问题。

     例如

public class UserProfile
{
   
public string Name { get; set; }
   
public UriBlog { get; set; }
   
public bool IsAdmin { get; set;}  // uh-oh!
}

     你不希望用户可以修改IsAdmin这个值,因为这样会篡改为管理员权限!

     最好的办法就是使用DTO对象,说白了就是封装一层面向展示层的对象,将IsAdmin剔除,这样用户就不会修改该值了。

public class UserProfileDTO
{
   
public string Name { get; set; }
   
public UriBlog { get; set; }
   
// Leave out "IsAdmin"
}

 

 

 处理验证错误

 

   1.当验证错误的时候WebApi不会自动向客户端返回错误,而是有Action编写代码实现向客户端返回错误。

 

   2.你也可以自己创建一个action filter去验证模型状态(model state),如果发生错误则会想客户端返回错误信息,action也不会执行。

namespace MyApi.Filters
{
   
public class ValidateModelAttribute: ActionFilterAttribute
    {
       
public override void OnActionExecuting(HttpActionContext actionContext)
        {
           
if (actionContext.ModelState.IsValid == false)
            {
                actionContext.
Response = actionContext.Request.CreateErrorResponse(
                   
HttpStatusCode.BadRequest,actionContext.ModelState);
            }
        }
    }
}

 

HTTP/1.1 400 Bad Request

Content-Type: application/json; charset=utf-8

Date: Tue, 16 Jul 2013 21:02:29 GMT

Content-Length: 331

{

  "Message": "The request isinvalid.",

  "ModelState": {

    "product": [

      "Required property'Name' not found in JSON. Path '', line 1, position 17."

    ],

    "product.Name": [

      "The Name field isrequired."

    ],

    "product.Weight": [

      "The field Weight mustbe between 0 and 999."

    ]

  }

}

 

如何应用这个filter呢?需要在 HttpConfiguration.Filters 集合中添加刚才创建的filter

public static class WebApiConfig
    {
       
public static void Register(HttpConfiguration config)
        {
            config.
Filters.Add(new ValidateModelAttribute());
        }
}

 

3.另外一个方式就是添加特性(简便省事儿)

public class ProductsController : ApiController
{
    [
ValidateModel]
   
public HttpResponseMessagePost(Product product)
    {
       
// ...
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值