6

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?

5
  • 1
    Hi have a look on this: stackoverflow.com/questions/29925674/… Commented Feb 3, 2017 at 9:41
  • Also you can use ModelBinder instead, have a look on this: stackoverflow.com/questions/33247992/… Commented Feb 3, 2017 at 9: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 '-'. Commented Feb 3, 2017 at 9: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 Commented Feb 4, 2017 at 16:58
  • Have you solved the problem? Commented May 24, 2018 at 2:03

1 Answer 1

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; }
}
Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.