3
votes

I have a simple ASP.Net Web API controller in an otherwise unchanged MVC4 Web API project that has a POST method that takes a Values class. When I do a:

POST /api/values with a body of { name: "somename" }

the Values() constructor gets called instead of the Values(string name) one. Normally, this isn't a problem because the Name property would have a public set and Web API would call it after construction. In this case it is private, so I get a default instance of Values.

If I remove the Values(int) ctor then it does call the Values(string) ctor.

Is there a reason ModelBinding isn't choosing the ctor with the name parameter?

Here's the example code:

using System.Web.Http;

namespace WebAPIPlayground.Controllers
{
    public class ValuesController : ApiController
    {
        public void Post(Values value)
        {
            var a = value.ID; // == 0
            var b = value.Name; // == null
        }
    }

    public class Values
    {
        public int ID { get; private set; }
        public string Name { get; private set; }

        private Values() { }
        public Values(int id) { ID = id; }
        public Values(string name) { Name = name; }
    }
}

I have already looked at: Routing and Action Selection and WebAPI Parameter binding under the hood among many other sites, but I do not understand this behavior.

1
I don't know much about this, but the constructor you claim it should be calling does not have the same method signature as your POST body (you haven't provided an int parameter). - Robert Harvey
@RobertHarvey Thanks for catching that. It shouldn't have been there. That was one of the last things I tried before posting here. - Jerry

1 Answers

5
votes

You're talking about deserialization here, not model binding. Try adding this attribute to the constructor you want to have used:

[JsonConstructor]
public Values(string name)

That should do it for the Json.NET case, but it won't work in XML. Maybe that's all you care about.