15

Given the ASP.NET Web API route:

example/{Id}

Which maps to the following ApiController action method:

public void Example(Model m)
{
    ...
}

With the model class defined as:

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

When I post JSON { "Name": "Testing" } to the URL /example/123 then Id property of the Model object is not bound. It remains as 0 instead of 123.

How can I make the model binding also include values from the route data? I'd prefer not having to write custom model binders for what seems like a common use case. Any ideas would be greatly appreciated. Thanks!

abatishchev
  • 98,240
  • 88
  • 296
  • 433
Andrew Davey
  • 5,441
  • 3
  • 43
  • 57

4 Answers4

11

The easiest way to accomplish what you're looking for is just to add another parameter to your method, and specify which parameter comes from which part of the request.

Example:

[HttpPost]
public void Example([FromUri]int id, [FromBody]Model m) {
    // ...
}

Now your route of /examples/{id} will successfully be able to bind - because the Example method has a parameter called id which it is looking for in the URI. To populate your model, you can either pass the ID in there as well, or do something like the following:

[HttpPost]
public void Example([FromUri]int id, [FromBody]Model m) {
    m.Id = id; // Make sure the model gets the ID as well.
}

Then simply post in { "Name": "Testing" } to /example/123 as you mentioned above.

Troy Alford
  • 26,660
  • 10
  • 64
  • 82
5

Our built-in ModelBinding infrastructure doesn't support partial binding of object from both URI and body. You can, however, implement a custom IActionValueBinder to accomplish this task. For example, please refer to the blog post http://blogs.msdn.com/b/jmstall/archive/2012/04/18/mvc-style-parameter-binding-for-webapi.aspx.

Bhavesh Chauhan
  • 1,048
  • 8
  • 5
3

The suggested process for this is normally to post to /example instead of /example/{id}. (though with Web API they normally use /api/{controller})

Check out the table half way down this page: http://www.asp.net/web-api/overview/web-api-routing-and-actions/routing-in-aspnet-web-api

Also check this link on "Inserting a record with ASP.NET Web API" - http://stephenwalther.com/archive/2012/03/05/introduction-to-the-asp-net-web-api.aspx

dkarzon
  • 7,868
  • 9
  • 48
  • 61
  • What if I'm PUTing a resource? In that case I don't want to remove the ID from the URL. – Andrew Davey Aug 08 '12 at 10:51
  • 2
    In that case you need to have it as a separate parameter on your action `(int id, Model, model)` Not the best solution I know. – dkarzon Aug 08 '12 at 10:59
0

I don't think the default binder can associate your Id route value to your Model Id property, so whatever d1k_is answer is as good as it gets I'm afraid; either that or writing your own binder (you might be able to write a more generic binder maybe? -if you have like a DomainEntity super class or something like that...)

nieve
  • 4,601
  • 3
  • 20
  • 26