Strict mapping in web Web API (Over-Posting)

江枫思渺然 提交于 2019-12-25 07:41:51

问题


I just realized that the mapping between the JSON send from a query and my API is not strict.

I give you more explanations:

Here is my C# POCO

public partial class AddressDto
{
    public string AddrId { get; set; }
    public string Addr1 { get; set; }
    public string Addr2 { get; set; }
    public string PostalCode { get; set; }
    public string City { get; set; }
    public string Country { get; set; }
}

And the REST JSON query

PUT http://Localhost:55328/api/ClientAddr/ADD-2059-S002 HTTP/1.1
content-type: application/json

{
    "AddrID": "ADD-2059-S002",
    "addr1": "B-1/327",
    "addr2": "1ST FLOOR",
    "city": "Paris",
    "Zip_Code": "78956",
    "country": "France",
}

The web client send a PUT with Zip_Code in place of PostalCode. PostalCode is not madatory/required. But Zip_Code does not exist in my DTO.

So in my C# code testing the model state won't help.

public HttpResponseMessage Put(string id, AddressDto address)
{
     if (!ModelState.IsValid)
            return BadRequest(ModelState); // This wont help
}

How can I raise exception when the client is using something in the JSON that is not existing in my DTO (model) ?


回答1:


if you need to identify extra columns and handle that as an error you have to extend IModelBinder interface and tell json deserializer to treat extra column as an error and add that error to ModelState. By that way you can check in controller for ModelState.IsValid. Checkout the below Code

CustomModelBinder

public class CustomModelBinder : IModelBinder
{
    public bool BindModel(HttpActionContext actionContext, ModelBindingContext bindingContext)
    {
        JsonSerializerSettings settings = new JsonSerializerSettings();
        settings.MissingMemberHandling = MissingMemberHandling.Error;
        ObjToPass obj = new ObjToPass();
        ;
        try
        {
            ObjToPass s =
                JsonConvert.DeserializeObject<ObjToPass>(actionContext.Request.Content.ReadAsStringAsync().Result,
                    settings);


            bindingContext.Model = obj;
        }
        catch (Exception ex)
        {
            bindingContext.ModelState.AddModelError("extraColumn", ex.Message);
        }
        return true;
    }
}

public class CustomerOrderModelBinderProvider : ModelBinderProvider
{
    public override IModelBinder GetBinder(System.Web.Http.HttpConfiguration configuration, Type modelType)
    {
        return new CustomModelBinder();
    }
}

Object Class that is passed to webapi

 public class ObjToPass
{
    public int Id { get; set; }
    public string Name { get; set; }

}

Controller

 [HttpPost]
    public void PostValues([ModelBinder(typeof(CustomerOrderModelBinderProvider))] ObjToPass obj)
    {
        if(!ModelState.IsValid)
        { }
        else
        {

        }
    }

This sample holds good for HttpPut as well.




回答2:


"Over-Posting": A client can also send more data than you expected. For example:

Here, the JSON includes a property ("Zip_Code") that does not exist in the Address model. In this case, the JSON formatter simply ignores this value. (The XML formatter does the same.)

https://docs.microsoft.com/en-us/aspnet/web-api/overview/formats-and-model-binding/model-validation-in-aspnet-web-api



来源:https://stackoverflow.com/questions/42709122/strict-mapping-in-web-web-api-over-posting

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!