0

I have an ASP.NET Core API that takes in a DTO parameter called DetParameterCreateDto which looks like this

DTO

public class DetParameterCreateDto
{
    public int Project_Id { get; set; }
    public string Username { get; set; }
    public string Instrument { get; set; }
    public short Instrument_Complete { get; set; }
}

The problem I am having is that the parameter passed in from the client has a property named Instrument_Complete; which is dynamic.

The name is actually [instrument]_complete where [instrument] is the name of the instrument. So if the name of the instrument is my_first_project then the parameter's property name will actually be my_first_instrument_complete, which will not properly map to my API's input parameter; so it always shows a value of 0

API Method

    [HttpPost("create")]
    public IActionResult CreateDetEntry(DetParameterCreateDto detParameters)
    {
       // some stuff in here
    }

Update (8/2)

Using bradley's suggestion it seems like I can do this with custom model binding. However, I have to set each model property instead of just the one I want to set instrument_complete (and convert some from string). This does not seem like an optimal solution.

    public Task BindModelAsync(ModelBindingContext bindingContext)
    {
        if (bindingContext == null)
        {
            throw new ArgumentNullException(nameof(bindingContext));
        }

        var instrumentValue = bindingContext.ValueProvider.GetValue("instrument").FirstValue;

        var model = new DetParameterCreateDto()
        {
            Project_Id = Convert.ToInt32(bindingContext.ValueProvider.GetValue("project_id").FirstValue),
            Username = bindingContext.ValueProvider.GetValue("username").FirstValue,
            Instrument = instrumentValue,
            Instrument_Complete = Convert.ToInt16(bindingContext.ValueProvider.GetValue($"{instrumentValue}_complete").FirstValue),

        bindingContext.Result = ModelBindingResult.Success(model);
        return Task.CompletedTask;

    }
2
  • You could probably use an ActionFilter to locate the parameter and alter its name before CreateDetEntry gets called. Commented Jul 31, 2017 at 17:55
  • 1
    Actually, a custom ModelBinder would probably be more appropriate for changing the way the data gets mapped. Commented Jul 31, 2017 at 17:57

1 Answer 1

1

DTO params in Web API are limiting especially when the properties are dynamic. I solved a similar issue before by using JObject. Yours could be something like:

[HttpPost("create")]
public IActionResult CreateDetEntry(JObject detParameters)
{
    //DO something with detParameters
    ...
    //Optionally convert it to your DTO
    var data = detParameters.ToObject<DetParameterCreateDto>();
   // or use it as is
}
Sign up to request clarification or add additional context in comments.

1 Comment

Will this still work if the data is not passed in JSON notation? I don't think that the API is using JSON because when I had [FromBody] in the params it didn't work. Also, Is it best practice to accept all parameters? I like having it strongly validated

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.