0

Currently I've got this ModelBinder that works just fine:

public class FooModelBinder : IModelBinder
    {
        public bool BindModel(HttpActionContext actionContext, ModelBindingContext bindingContext)
        {
            var body = JObject.Parse(actionContext.Request.Content.ReadAsStringAsync().Result);
            IEnumerable<Foo1> media = new List<Foo1>();
            var transaction = body.ToObject<Foo2>();

            media = body["Media"].ToObject<List<Foo3>>();


            transaction.Media = media;
            bindingContext.Model = transaction;

            return true;
        }
    }

As you can see I'm mapping the whole bindingContext.Model, but what I really want to do is to map just the Media field of the Model and all of the other fields to map as default.

This is my controller:

public HttpResponseMessage Post([ModelBinder(typeof(FooModelBinder))] Foo request)
        {
            //do something
        }

Is this achievable?

Marcelo
  • 784
  • 3
  • 9
  • 30
  • meaning what? Are you expecting the web request to be fully populated, and from the web request utilize only the 'Media' value in your controller action? – barrypicker Aug 29 '18 at 20:11
  • @barrypicker No, I just want to map the Media field in a custom way before entering the controller, but all of the other fields being mapped by default. – Marcelo Aug 29 '18 at 20:19
  • I believe this is do-able. If I understand correctly this model binder will apply to all controller actions so data type mismatches can occur if a controller action parameter is not of type Foo2. – barrypicker Aug 29 '18 at 21:36
  • You could use logic in the controller action to copy input parameter fields into a new object and utilize the default model binder too. – barrypicker Aug 29 '18 at 21:36
  • @barrypicker I think you are talking about MVC ModelBinder which differs from webapi – Marcelo Aug 30 '18 at 13:17

1 Answers1

0

Here's how all of our model binders are defined:

public class FooBinder : IModelBinder {

public bool BindModel(HttpActionContext actionContext, ModelBindingContext bindingContext)
{
    if (bindingContext.ModelType == typeof(Foo))
    {
        return FooParameter(actionContext, bindingContext);
    }

    return false;
}

If you want to make multiple parameters from your input you can just specify your desired binder in the your controller method.

    public async Task<HttpResponseMessage> GetFoo(
        [ModelBinder] Foo1 foo1 = null, [ModelBinder] Foo2 foo2 = null)
    {
       ... 
    }

I may have misunderstood your question but this is an example of real code in our system.

No Refunds No Returns
  • 8,092
  • 4
  • 32
  • 43
  • I think you did misunderstood, but that's my fault, I may have omitted my controller, now I've edited with the controller code attached. My intention is simple...inside BindModel I just want to map model.Media, and all of the other properties to be mapped by default. – Marcelo Aug 30 '18 at 13:22
  • Also...this is not MVC ModelBinder, this is ASP .NET Web API ModelBinder – Marcelo Aug 30 '18 at 13:33
  • My example is a WebAPI controller from our service. My point is that I think you may have to parse the body yourself and provide the appropriate parameter(s) from it via the model binding feature of the pipeline. Unless you have a single simple object type I think you're going to be writing a few more lines of code. – No Refunds No Returns Aug 30 '18 at 13:59
  • I'm actually parsing the body, that is what I don't want to do. My POST receives a base object, and I have 2 other objects that inherites from it, but differs on a property, that is why I want to map that property by myself using ModelBinder. – Marcelo Aug 30 '18 at 14:25
  • Do you have an interface `IFoo` that you can create objects of type `FooA` and `FooB`? If so you can create the define IFoo as the type returned in your model binder and in your factory method create FooA/FooB based on the input. – No Refunds No Returns Aug 30 '18 at 17:22
  • For example...My ModelBinder receives this `FooRequest = { "Id": "#", "Country": "###", Media[//different properties by country]}`. Then what I want to do is to change this Media property to a certain FooMedia depending on the country. – Marcelo Aug 30 '18 at 17:31