Skip to content
This repository has been archived by the owner on Dec 14, 2018. It is now read-only.

ModelBinder attribute attached to a class has no effect (broken in rc2-final) #4652

Closed
AlekseyMartynov opened this issue May 17, 2016 · 9 comments
Assignees
Milestone

Comments

@AlekseyMartynov
Copy link

I have a model class and a binder:

[ModelBinder(BinderType = typeof(MyModelBinder))]
public class MyModel {
    public string Foo;
}

public class MyModelBinder : IModelBinder {

    public Task BindModelAsync(ModelBindingContext bindingContext) {
        var model = new MyModel {
            Foo = "Bar"
        };

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

Usage:

public IActionResult Index(MyModel model)
{
    return View();
}

In rc2, the binder isn't invoked, but the same approach works fine with classic MVC 5 and DNX rc1-final.
Full sample: https://github.com/AlekseyMartynov/aspnetcore-rc2-modelbinding

@dougbu
Copy link
Member

dougbu commented May 17, 2016

I can reproduce this issue. The BinderTypeModelBinderProvider isn't called though the ModelBinderFactory has an instance first in its _providers -- as expected. Will see if I can reproduce this in the MVC Sandbox and debug further...

@dougbu
Copy link
Member

dougbu commented May 17, 2016

🆒 bug 😎

Well BinderTypeModelBinderProvider is called but it's checking context.BindingInfo?.BinderType instead of context.Metadata.BinderType. At the top level, the first is non-null only when binding attributes are on the parameter. Binding attributes on a parameter type are not used.

Probably best for ModelBinderFactory to initialize DefaultModelBinderProviderContext.BindingInfo using both its own ModelBinderFactoryContext.BindingInfo and ModelBinderFactoryContext.Metadata.BindingInfo. No need for any changes except when initializing for the top level model.

This issue affects at least

  • BinderTypeModelBinderProvider
  • BodyModelBinderProvider
  • HeaderModelBinderProvider
  • ServicesModelBinderProvider

@dougbu dougbu self-assigned this May 17, 2016
@Eilon Eilon added the bug label May 17, 2016
@Eilon Eilon added this to the 1.0.0 milestone May 17, 2016
@Eilon
Copy link
Member

Eilon commented May 17, 2016

Umm, and add a unit test? 😄

@dougbu
Copy link
Member

dougbu commented May 17, 2016

@Eilon well I've fixed the bug while proving to myself I understood it. So why not 😺

dougbu added a commit that referenced this issue May 24, 2016
- #4652
- previously ignored for top-level models
- `ModelBinderProviderContext.BindingInfo` is now never `null`
- similarly, use type metadata (as well as parameter info) for `ModelBindingContext.BinderModelName`
 - previously ignored when overridden in `ControllerArgumentBinder`
dougbu added a commit that referenced this issue May 27, 2016
- #4652
- previously ignored for top-level models
- `ModelBinderProviderContext.BindingInfo` is now never `null`
- similarly, use type metadata (as well as parameter info) for `ModelBindingContext.BinderModelName`
 - previously ignored when overridden in `ControllerArgumentBinder`
dougbu added a commit that referenced this issue May 28, 2016
- #4652
- previously ignored for top-level models
- `ModelBinderProviderContext.BindingInfo` is now never `null`
- similarly, use type metadata (as well as parameter info) for `ModelBindingContext.BinderModelName`
 - previously ignored when overridden in `ControllerArgumentBinder`
dougbu added a commit that referenced this issue May 28, 2016
- #4652
- previously ignored for top-level models
- `ModelBinderProviderContext.BindingInfo` is now never `null`
- similarly, use type metadata (as well as parameter info) for `ModelBindingContext.BinderModelName`
 - previously ignored when overridden in `ControllerArgumentBinder`
@dougbu
Copy link
Member

dougbu commented May 28, 2016

e63f094

@dougbu dougbu closed this as completed May 28, 2016
@jruckert
Copy link

jruckert commented Jun 5, 2016

Is there a work around for this (if we want to keep using rc2-final)??

@AlekseyMartynov
Copy link
Author

@jruckert yes, the workaround is to use the binder attribute explicitly (example)

@vaindil
Copy link

vaindil commented Jan 26, 2017

@dougbu I don't know if this is working. The attribute seems to have no effect in my code. Model binders are still called in order like normal, the attribute does nothing.

[HttpGet]
public async Task<IActionResult> Get([ModelBinder(BinderType = typeof(MyModelBinder))] int userId)
{
    // stuff
}

@dougbu
Copy link
Member

dougbu commented Jan 26, 2017

@vaindil please open a new issue describing the exact scenario where you're seeing a regression of this fix.

I assume you are using an Mvc package more recent than 1.0.0. But, please include the project.json content in the new issue.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

5 participants