Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Combining with Custom Model Binder #43

Open
Luke1979 opened this issue Mar 30, 2020 · 2 comments
Open

Combining with Custom Model Binder #43

Luke1979 opened this issue Mar 30, 2020 · 2 comments

Comments

@Luke1979
Copy link

Luke1979 commented Mar 30, 2020

Hi all,

Great nuget package; thanks.

Is it possible to combining HybridModelBinder with another Custom IModelBinder.

My Request class has a complex type (Company) which I'm attempting to resolve using CompanyModelBinder in the example below. If I use [FromQuery] it all works, but changing to [FromHybrid] prevents the model binder from being hit.

Any help/info would be great.

CompanyModelBinder.cs

    public class CompanyModelBinderProvider: IModelBinderProvider
    {
        public IModelBinder GetBinder(ModelBinderProviderContext context)
        {
            return context.Metadata.ModelType == typeof(Company) 
                ? new CompanyModelBinder() 
                : null;
        }
    }

    public class CompanyModelBinder : IModelBinder
    {
        public Task BindModelAsync(ModelBindingContext bindingContext)
        {
            if (bindingContext == null)
                throw new ArgumentNullException(nameof(bindingContext));

            var valueProviderResult = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
            if (valueProviderResult == ValueProviderResult.None)
                return Task.CompletedTask;

            bindingContext.ModelState.SetModelValue(bindingContext.ModelName, valueProviderResult);

            var value = valueProviderResult.FirstValue;

            if (string.IsNullOrEmpty(value)) 
                return Task.CompletedTask;
            
            var model = new Company(value);

            bindingContext.Result = ModelBindingResult.Success(model);

            return Task.CompletedTask;
        }
    }

Startup.cs....

services
                .AddMvc(config =>
                {
                    // Custom Model Binders.
                    config.ModelBinderProviders.Insert(0, new CompanyModelBinderProvider());
                 })
                .AddHybridModelBinder();

Request.cs

public class Request : IRequest<Result<Response>>
{
    public Company Company { get; set; }
}

Controller.cs

Using [FromQuery] works (The Company model binder is invoked)

public IActionResult Index([FromQuery]Request request)
{
   ...
}

...but using [FromHybrid]` doesn't.... :(

public IActionResult Index([FromHybrid]Request request)
{
   ...
}
GET /api/v1/company?company=Foo HTTP/1.1
Host: localhost:44398

Any ideas what I might be doing wrong?

Thanks.

@billbogaiv
Copy link
Owner

I suspect it's a limitation of the framework to only execute the first successful instance of IModelBinder. HybridModelBinding registers itself as the first MvcOptions.ModelBinderProviders via AddHybridModelBinder.

However, I've had an idea before to create public-facing methods for adding model binders through HybridModelBinding to continue hydrating properties of the parent-instance (currently, this is all handled internally). Need to think about implementation a bit more since ordering of events becomes more important.

@WarpSpideR
Copy link

Hi Bill,

We've been using this package for a new project we're working on and it's been super helpful, sadly we've now come across this limitation as well.

Is this something that is being actively looked at? Are you open to some help implementing this? If so please let me know as I'd be keen to get this added to the package!

Cheers

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

No branches or pull requests

3 participants