Escribí una anulación de 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; }También tengo un servicio de javascript (en Angular) que realiza una solicitud AJAX a uno de mis controladores.
La solicitud AJAX intenta publicar una colección de ints. Intenté recorrer la carpeta del modelo y parece que el value siempre es nulo. Y por un poco de magia, base.BindModel() aún puede vincular mi colección al objeto C# correcto.
El problema con esto es que no puedo usar mi carpeta personalizada ya que el bloque else nunca se invoca. ¿Hay otra forma de obtener el valor además de usar ValueProvider ?
También creo que antes este archivador personalizado funcionaba correctamente (de memoria que podría estar mal). Recientemente actualicé de 4.5 a 5.2.algo. ¿Hay algo que se actualizó que podría haber cambiado este comportamiento?
También tengo un servicio de javascript (en Angular) que realiza una solicitud AJAX a uno de mis controladores.
...
El problema con esto es que no puedo usar mi carpeta personalizada ya que el bloque else nunca se invoca.
Es nulo porque no puede encontrar los datos basados en el nombre de su modelo al que está tratando de vincularse. Si el valor se puede encontrar con este nombre depende del nombre del modelo y los datos enviados en la solicitud del cliente que deben alinearse/coincidir. Pero antes de que alguien pueda decirle por qué los datos no coinciden (incluido su modelo con la matriz) se pueden enviar desde el cliente de una de estas tres maneras:
?myArray=1&myArray=2&myArray=3 . Esto significa que en la carpeta de tu modelo tendrás que considerar esto.data (cuerpo) en un POST, entonces podría ser un objeto de matriz real. Ejemplo en json: {"myArray":[1,2,3,4]}Entonces, para responder mejor a su pregunta, deberá proporcionar
Entonces, para recapitular: bindingContext.ModelName es el nombre esperado y debe coincidir con los datos que su enlazador de modelos está tratando de encontrar. Si está enviando {"myArray":[1,2,3,4]} pero la propiedad de su modelo se llama ProductIds , entonces siempre será nulo.
Recientemente actualicé de 4.5 a 5.2.algo
No, no que yo sepa.
Pensamiento final. También puede dejar que se ejecute el enlazador de modelos predeterminado y luego hacer algo con el valor devuelto si los tipos coinciden. Si el enlace se realiza ahora sin problemas, pero desea realizar un procesamiento posterior, esta sería una mejor opción. Ejemplo:
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; }Por favor, asegúrese de haber hecho algo como esto: -
Encuadernación de modelo personalizado:-
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); } } }Una vez que hayamos completado la codificación de nuestra clase personalizada, necesitaremos registrar la clase que hago en Global.asax en 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) Finalmente, debemos informar al controlador sobre el enlace que queremos que use. Esto lo podemos especificar usando los atributos [ModelBinder(typeof(HomeCustomBinder))] como se muestra a continuación:
[HttpPost] public ActionResult Index([ModelBinder(typeof(HomeCustomBinder))] HomePageModels home) { if (ModelState.IsValid) { ViewBag.Title = home.Title; ViewBag.Date = home.Date; } return View(); }