Custom Model Binder & TryUpdateModelAsync not working as expected

482 Views Asked by At

I think I might be misunderstanding how the TryUpdateModelAsync method works, I have a process where multipart form data is passed into mt controller in a PUT.

I have a requirement to trigger the model binding, use a custom model binder to pull the form data out and manipulate it as required and make it available for further processing.

I have tried to simplify the process for the purpose of this example and this is the simplest I can get :

public class HomeController : Controller
    {
        public IActionResult Index()
        {
           return View();
        }

        [HttpPut]
        public async Task<IActionResult> Upload()
        {
            var mod = new TestModel();

            await base.TryUpdateModelAsync(mod, "Model");
            
            return new OkResult();
        }
    }

    [ModelBinder(BinderType = typeof(TestModelBinder))]
    public class TestModel
    {
        public string Name;
    }

    public class TestModelBinder : IModelBinder
    {
        public Task BindModelAsync(ModelBindingContext bindingContext)
        {
            bindingContext.Result = ModelBindingResult.Success(new TestModel()
            {
                Name = "Some Value"
            });

            return Task.CompletedTask;
        }
    }

So the process is

  • Client does a PUT to the Upload action.
  • upload action creates a new instance of a class (in this example the "TestModel")
  • we call TryUpdateModelAsync passing in the new (empty) model.

What I expected was for the name on the mod variable to be set to "Some Value" as that's what I have hard-coded the model binder to do, but it doesn't seem to work.

What am I doing wrong?

1

There are 1 best solutions below

1
On

As far as I know, the TryUpdateModelAsync method is used for Manual model binding, it will not trigger custom model binder. Since the custom model binder has happened before you called TryUpdateModelAsync method. The TryUpdateModelAsync method will not recalled the custom model binder BindModelAsync method.

In my opinion, if you want to use Manual model binding, you could directly set the binder value to Some Value.