2012-03-28 5 views
24

Ho bisogno di sapere come creare un IModelBinder personalizzato in MVC 4 ed è stato modificato.MVC 4 ModelBinder

Il nuovo metodo che deve essere implementato è:

bool BindModel(HttpActionContext actionContext, ModelBindingContext bindingContext); 

risposta

27

Ci sono 2 interfacce IModelBinder:

  1. System.Web.Mvc.IModelBinder che è la stessa come nelle versioni precedenti e non è cambiato
  2. System.Web.Http.ModelBinding.IModelBinder che viene utilizzato dall'API Web e dall'ApiController. Quindi in pratica all'interno di questo metodo devi impostare lo actionContext.ActionArguments sui valori corrispondenti. Non si restituisce più un'istanza di modello.
+0

Sì, grazie Darin. –

+3

È inoltre necessario registrare un raccoglitore modello personalizzato. L'API Web ASP.Net non ha lo stesso metodo di MVC3. Controlla [questo post] (http://forums.asp.net/t/1773706.aspx/1) per vedere come farlo in MVC4 Beta. La parte inferiore della risposta è difficile da capire, ma si noti che è stata impostata in 'global.asax.cs' con' GlobalConfiguration.Configuration.ServiceResolver.GetServices ... ' – Steve

24

This link, fornito da Steve, fornisce una risposta completa. Lo sto aggiungendo qui per riferimento. Il merito va a dravva nei forum di asp.net.

Innanzitutto, creare una classe derivata da IModelBinder. Come dice Darin, assicurati di utilizzare lo spazio dei nomi System.Web.Http.ModelBinding e non l'equivalente MVC familiare.

public class CustomModelBinder : IModelBinder 
{ 
    public CustomModelBinder() 
    { 
     //Console.WriteLine("In CustomModelBinder ctr"); 
    } 

    public bool BindModel(
     HttpActionContext actionContext, 
     ModelBindingContext bindingContext) 
    { 
     //Console.WriteLine("In BindModel"); 
     bindingContext.Model = new User() { Id = 2, Name = "foo" }; 
     return true; 
    } 
} 

successivo, fornire un fornitore, che agisce come una fabbrica per il nuovo legante, ed eventuali altri leganti è possibile aggiungere in futuro.

public class CustomModelBinderProvider : ModelBinderProvider 
{ 
    CustomModelBinder cmb = new CustomModelBinder(); 
    public CustomModelBinderProvider() 
    { 
     //Console.WriteLine("In CustomModelBinderProvider ctr"); 
    } 

    public override IModelBinder GetBinder(
     HttpActionContext actionContext, 
     ModelBindingContext bindingContext) 
    { 
     if (bindingContext.ModelType == typeof(User)) 
     { 
      return cmb; 
     } 

     return null; 
    } 
} 

Infine, includono quanto segue nel Global.asax.cs (ad esempio, Application Start).

var configuration = GlobalConfiguration.Configuration; 

IEnumerable<object> modelBinderProviderServices = configuration.ServiceResolver.GetServices(typeof(ModelBinderProvider)); 
List<Object> services = new List<object>(modelBinderProviderServices); 
services.Add(new CustomModelBinderProvider()); 
configuration.ServiceResolver.SetServices(typeof(ModelBinderProvider), services.ToArray()); 

Ora, è possibile delare il nuovo tipo come parametro per i metodi di azione.

public HttpResponseMessage<Contact> Get([ModelBinder(typeof(CustomModelBinderProvider))] User user) 

o anche

public HttpResponseMessage<Contact> Get(User user) 
+0

Credo, purché si utilizzi esplicitamente [ModelBinder (typeof (CustomModelBinderProvider))] nella tua azione, non hai bisogno del ModelBinderProvider. –

3

Un aggiornamento messaggio RC al post di Todd:

Aggiungere il vostro fornitore binder modello è stato semplificato:

var configuration = GlobalConfiguration.Configuration; 

configuration.Services.Add(typeof(ModelBinderProvider), new YourModelBinderProvider()); 
+1

Questo ha funzionato per me. C'è un modo per farlo a livello globale, cioè impostare il modello predefinito di raccoglitore? –

8

Un anche modo semplice per aggiungere un modelbinder senza ModelBinderProvider è questo:

GlobalConfiguration.Configuration.BindParameter(typeof(User), new CustomModelBinder()); 
+0

Questo ha funzionato perfettamente! Per qualche ragione non sono riuscito a far funzionare nessuno degli altri esempi su questa pagina con MVC4. L'interfaccia per ModelBinderProvider sembra essere cambiata. Ma rimuovere ModelBinderProvider e aggiungere questo codice a Application_Start ha funzionato alla grande! –