Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ModelBinder and sub models

I use in some models a sub model class (UserInfo) which should contain some user related info. This sub model can be used in various models, For example

public class Model
{
     int string Value { get; set; }
     public UserInfo User { get; set; }
}

I've created a model binder and registered it in WebApiConfig

config.BindParameter(typeof(UserInfo), new UserModelBinder());

The thing is the UserModelBinder isn't called by the WebApi processing pipeline. It seems that these modelbinders aren't called for the sub models. Am I missing something ?

like image 249
user49126 Avatar asked Feb 04 '13 15:02

user49126


People also ask

What is a model in Web API?

A model is an object that represents the data in your application. ASP.NET Web API can automatically serialize your model to JSON, XML, or some other format, and then write the serialized data into the body of the HTTP response message.

How do I pass model to Web API POST method?

Answers. You can serialize the model into a json string and transfer it, and then deserialize the json string in the get method of WebAPI to get the model.

What is FromBody in Web API?

Using [FromBody] When a parameter has [FromBody], Web API uses the Content-Type header to select a formatter. In this example, the content type is "application/json" and the request body is a raw JSON string (not a JSON object).

What is custom model binder in MVC?

In the MVC pattern, Model binding maps the HTTP request data to the parameters of a Controllers action method. The parameter can be of a simple type like integers, strings, double etc. or they may be complex types. MVC then binds the request data to the action parameter by using the parameter name.


2 Answers

Take a look at this question What is the equivalent of MVC's DefaultModelBinder in ASP.net Web API? for some detail on where your bindings are going to be happening.

I suspect though that your Model is being passed in the message body?

If it is then WebApi will use a formatter to deserialise your types and process the model, the defaults being XmlMediaTypeFormatter, JsonMediaTypeFormatter or FormUrlEncodedMediaTypeFormatter.

If you are posting the model in the body then depending on your requested or accepted content-type is (application/xml, application/json etc) you may need to customise the serialiser settings or wrap or implement your own MediaTypeFormatter.

If you are using application/json then you can use JsonConverters to customise the serialisation of your UserInfo class. There is an example of this here Web API ModelBinders - how to bind one property of your object differently and here WebApi Json.NET custom date handling

internal class UserInfoConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return objectType == typeOf(UserInfo);
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue,
                                JsonSerializer serializer)
    {
        //
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        //
    }
}
like image 156
Mark Jones Avatar answered Oct 20 '22 20:10

Mark Jones


HttpConfigurationExtensions.BindParameter method register that the given parameter type on an Action is to be bound using the model binder.

so what you did is similar to:

void Action([ModelBinder(UserModelBinder)] UserInfo info)

It works only if action parameter is of specified type (UserInfo).

Try putting model binder declaration on UserInfo class itself, so that it's global:

[ModelBinder(UserModelBinder)] public class UserInfo { }

However, there are some differences in the way how WebAPI and MVC bind parameters. Here is Mike Stall's detailed explanation.

like image 42
Nenad Avatar answered Oct 20 '22 21:10

Nenad