Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

176
Visualizações
MVC 5 Model Binder Override

I wrote an override of the Model Binder.

public override object BindModel(Controller context, ModelBindingContext bindingContext)
{
    var value = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);

    object returnVal = null;

    if (value == null)
        returnVal = base.BindModel(controllerContext, bindingContext);
    else
    {
        /* custom logic here that never seems to get called.
            returnVal = something();
        */
    }

    return returnVal;
}

I also have a javascript service (in Angular) that makes an AJAX request to one of my controllers.

The AJAX request attempts to post a collection of ints. I tried stepping through the model binder, and it seems like value is always null. And by some magic, the base.BindModel() is still able to bind my collection to the correct C# object.

The problem with this is that I can't use my custom binder as the else block is never invoked. Is there another way I can get the value besides using the ValueProvider?

I also believe that before this custom binder was working correctly (from memory which could be wrong). I recently updated from 4.5 to 5.2.something. Is there anything that was updated that could've changed this behavior?

over 4 years ago · Santiago Trujillo
2 Respostas
Responde à pergunta

0

I also have a javascript service (in Angular) that makes an AJAX request to one of my controllers.

...

The problem with this is that I can't use my custom binder as the else block is never invoked.

  • I am going to assume that you have properly registered your binder either globally OR on the action itself on one or more of the parameters.
  • I will also assume that your binder is being called when you expect it to.

Its null because it can't find the data based on your model name that it is trying to bind to. Whether the value can be found by this name depends on the model name and the data sent in the client request which have to align/match. But before anyone can tell you why its not matching data (including your model with the array) can be sent from the client in one of three ways:

  1. If using the URL you will reuse the same property name in the query string. Example: ?myArray=1&myArray=2&myArray=3. This means that in your model binder you will have to consider this.
  2. If using the data (body) in a POST then it might be an actual array object. Example in json: {"myArray":[1,2,3,4]}
  3. You might also be serializing the entire form and sending it over with Angular (which would allow you to better use the binding functionality in MVC)

So to better answer your question you will need to provide

  1. The format of the data is being sent from the browser and how its being sent (query string or in the data payload) (this is probably in your Angular factory,service, or controller)
  2. The model definition you are trying to bind to

So to recap: bindingContext.ModelName is the expected name and must match the data that your model binder is trying to find. If you are sending {"myArray":[1,2,3,4]} but your model property is named ProductIds then it will always be null.

I recently updated from 4.5 to 5.2.something

No, not that I am aware of.


Final thought. You could also let the default model binder execute and then do something with the returned value if the types match. If the binding happens now without a problem but you want to do some post-processing this would be a better choice. Example:

public override object BindModel(Controller context, ModelBindingContext bindingContext)
{
    var value = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);

    object returnVal = base.BindModel(controllerContext, bindingContext);

    /* check returnVal and then additional custom logic here */.
    
    return returnVal;
}
over 4 years ago · Santiago Trujillo Relatório

0

Please make sure you have done something like this:-

  1. Custom Model Binding:-

    public class HomeCustomDataBinder : DefaultModelBinder
    {
        public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
        {
            if (bindingContext.ModelType == typeof(HomePageModels))
            {
                HttpRequestBase request = controllerContext.HttpContext.Request;
    
                string title = request.Form.Get("Title");
                string day = request.Form.Get("Day");
                string month = request.Form.Get("Month");
                string year = request.Form.Get("Year");
    
                return new HomePageModels
                {
                    Title = title,
                    Date = day + "/" + month + "/" + year
                };
    
                //// call the default model binder this new binding context
                //return base.BindModel(controllerContext, newBindingContext);
            }
            else
            {
                return base.BindModel(controllerContext, bindingContext);
            }
        }
    
    } 
    
  2. Once we have completed coding our custom class we will need to register the class which I do in the Global.asax under Application_Start().

    protected void Application_Start()
    {
        AreaRegistration.RegisterAllAreas();
        WebApiConfig.Register(GlobalConfiguration.Configuration);
        FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
        RouteConfig.RegisterRoutes(RouteTable.Routes);
        BundleConfig.RegisterBundles(BundleTable.Bundles);
        AuthConfig.RegisterAuth();
        ModelBinders.Binders.Add(typeof(HomePageModels), new HomeCustomBinder());
    }
    

    3) Finally we need to inform the controller as to the binding we want it to use. This we can specify using attributes [ModelBinder(typeof(HomeCustomBinder))] as below:

    [HttpPost]
    public ActionResult Index([ModelBinder(typeof(HomeCustomBinder))] HomePageModels home)
    {
        if (ModelState.IsValid)
        {
            ViewBag.Title = home.Title;
            ViewBag.Date = home.Date;
        }
        return View();
    }
    
over 4 years ago · Santiago Trujillo Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda