4

I'm bound by agreements between my party and the client to use json parameters containing dashes. Since it's not possible to use that in property names in C#, I need to map to the desired property.

What I do now:

The below code is simplified for convenience.

Model

public class MyRequest
{
    [JsonProperty("request-number")]
    public string RequestNumber { get; set; }

    [JsonProperty("name")]
    public string Name { get; set; }
}

Controller

[HttpGet]
[Route("api/load-stuff")]
public Stuff LoadStuff([FromUri]MyRequest request)
{
    return BackEnd.LoadStuff(request);
}

Call to the API from client

The above controller is targeted using this uri:

http://localhost:12345/api/load-stuff?request-number=X123&name=requestName

My question

If I put a breakpoint at the BackEnd.LoadStuff line I can see the call arrives, but the request isn't mapped correctly.

Name contains what I expect: requestName, but RequestNumber is null, so the mapping didn't work.

What's going wrong?

Spikee
  • 3,967
  • 7
  • 35
  • 68
  • 1
    Hi have a look on this: http://stackoverflow.com/questions/29925674/webapi-datamember-name-not-used-when-de-serializing-via-application-x-www-form-u – xszaboj Feb 03 '17 at 09:41
  • Also you can use ModelBinder instead, have a look on this: http://stackoverflow.com/questions/33247992/querystring-model-binding-asp-net-webapi – xszaboj Feb 03 '17 at 09:46
  • Thanks, but I don't think it's a related issue because my model-instance does arrive, it's just that (one of) the mappings failed. Everything's fine if I omit the '-'. – Spikee Feb 03 '17 at 09:59
  • 1
    of course that it will arrive correctly if you ommit '-' because it will be the same name as you have on your model. Default ModelBinder is not case sensitive – xszaboj Feb 04 '17 at 16:58
  • Have you solved the problem? – Mohammed Noureldin May 24 '18 at 02:03

1 Answers1

2

ASP.NET's default model binder doesn't take the JsonPropertyAttribute into account when attempting to bind request parameters to a model (it can't, since it doesn't know about JsonPropertyAttribute and the rest of NewtonSoft.Json). Given your scenario (property names that aren't legal identifiers in C#), the only way to achieve what you want is via a custom model binder that does read JsonPropertyAttribute.

If you did have property names that were legal identifiers (for example request_number) then you could create a request model with those named properties, then map it to a separate model with the correctly-named properties, e.g.:

public class MyController : ApiController
{
    [HttpGet]
    [Route("api/load-stuff")]
    public Stuff LoadStuff([FromUri]MyRequest request)
    {
        return BackEnd.LoadStuff(request.ToMyPrettyRequest());
    }
}

public class MyRequest
{
    public string request_number { get; set; }

    public string name { get; set; }

    MyPrettyRequest ToMyPrettyRequest()
    {
        return new MyPrettyRequest
        {
            RequestNumber = request_number,
            Name = name,
        };
    }
}

public class MyPrettyRequest
{
    public string RequestNumber { get; set; }

    public string Name { get; set; }
}
Ian Kemp
  • 28,293
  • 19
  • 112
  • 138