3

I'm trying to figure out model binding in current mvc6 (visual studio 2015 release candidate). This is what my code looks like so far:

public class MyObjectModelBinder : IModelBinder
{
    public Task<ModelBindingResult> BindModelAsync(ModelBindingContext bindingContext)
    {

        if (bindingContext.ModelType == typeof(MyObject))
        {
            var model = new MyObject();
            return Task.FromResult(new ModelBindingResult(model, bindingContext.ModelName, true));
        }
        return Task.FromResult<ModelBindingResult>(null);

    }
}

The registration in startup.cs

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc().Configure<MvcOptions>(options =>
    {
        options.ModelBinders.Add(typeof( MyObjectModelBinder));
    });
}

My Controller:

[HttpPost]
public void ReceiveMyObject([FromBody] MyObject x)
{

}

I don't care yet about actually creating the object from the input, what troubles me is that when I debug, I see the controller firing (with x being null), but the binder function is not being called. Any ideas of what's wrong here?

[EDIT: This has already been updated]Also note, I have already seen What is the correct way to create custom model binders in MVC6? but the answer in that post is either wrong or outdated, since the example provided doesn't implement the current IModelBinder.

Thanks

EDIT: This is the javascript code used to fire the controller:

function sendMessage(i) {
    $.ajax({
        type: 'POST',
        url: 'myurl',
        data: data,
        contentType: 'application/x-www-form-urlencoded',
        dataType: 'json',
        success: function (data) { console.log(data) }
    });
}
Community
  • 1
  • 1
Plaga
  • 83
  • 1
  • 7

3 Answers3

2

Add

public void ReceiveMyObject([ModelBinder(BinderType = typeof(MyObjectModelBinder))] MyObject x)

to method or u can set default binder for type

Horosho
  • 647
  • 1
  • 8
  • 22
1

Remove the [FromBody] decoration on the action's parameter.

FromBody is indicated that an InputFormatter is to be used to populate this parameter. If you remove it model binders run.

Yishai Galatzer
  • 8,791
  • 2
  • 32
  • 41
Kiran
  • 56,921
  • 15
  • 176
  • 161
  • If I remove it, the controller no longer fires. It does if there is no parameter, though. I've attached the javascript I use for testing, but in the real case the call is being made by an external software, so I can't change it. – Plaga May 06 '15 at 08:22
1

Try to add it as the first model binder into the list. When an IModelBinder successfully sets a model, other IModelBinder won't be fired.

So if you want to give a chance to your own IModelBinder you have to make it being fired before others do the job.

This works for me:

services.Configure<MvcOptions>(options =>
{
    options.ModelBinders.Insert(0, new MyObjectModelBinder());
});

But index 0 is not the best place to put it. Just determine which ModelBinder sets the model and prevents your ModelBinder to be fired and put your ModelBinder before it.

Yves
  • 3,752
  • 4
  • 29
  • 43