2012-03-28 11 views
24

Potrzebuję wiedzieć, jak utworzyć niestandardową IModelBinder w MVC 4 i została zmieniona.MVC 4 ModelBinder

Nowa metoda, która ma być realizowane to:

bool BindModel(HttpActionContext actionContext, ModelBindingContext bindingContext); 

Odpowiedz

27

Istnieją 2 interfejsy IModelBinder:

  1. System.Web.Mvc.IModelBinder która jest taka sama jak w poprzednich wersjach, a nie zmieniła
  2. System.Web.Http.ModelBinding.IModelBinder, który jest używany przez Web API i ApiController. Więc w zasadzie w tej metodzie musisz ustawić actionContext.ActionArguments na odpowiednie wartości. Nie zwrócisz już egzemplarza modelu.
+0

Yesss, dzięki Darin. –

+3

Należy również zarejestrować niestandardowy segregator modelu. ASP.Net Web API nie działa tak samo jak MVC3. Sprawdź [ten post] (http://forums.asp.net/t/1773706.aspx/1), aby zobaczyć, jak to zrobić w wersji Beta MVC4. Odpowiedź jest trudna do ustalenia, ale pamiętaj, aby ustawić ją w pliku 'global.asax.cs' przy użyciu opcji' GlobalConfiguration.Configuration.ServiceResolver.GetServices ... ' – Steve

24

This link, dostarczone przez Steve, zapewnia kompletną odpowiedź. Dodaję go tutaj w celach informacyjnych. Kredyt trafia do dravva na forach asp.net.

Najpierw utwórz klasę pochodną od IModelBinder. Jak mówi Darin, pamiętaj, aby używać przestrzeni nazw System.Web.Http.ModelBinding, a nie znanego odpowiednika MVC.

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; 
    } 
} 

Następnie podaj dostawcę, który działa jak fabryka nowego segregatora, oraz wszelkie inne segregatory, które możesz dodać w przyszłości.

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; 
    } 
} 

Na koniec dołącz następujące elementy do pliku Global.asax.cs (np. 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()); 

Teraz można po prostu dodać nowy typ jako parametr do metod działania.

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

lub nawet

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

Uważam, pod warunkiem, że wyraźnie użyłeś [ModelBinder (typeof (CustomModelBinderProvider))] w twoim działaniu, nie potrzebujesz ModelBinderProvider. –

3

Aktualizacja postu RC do postu Todda:

Dodawanie dostawca spoiwo model został uproszczony:

var configuration = GlobalConfiguration.Configuration; 

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

To zadziałało dla mnie. Czy istnieje sposób, aby to zrobić globalnie, tj. Ustawić domyślny segregator modelu? –

8

parzystą prosty sposób dodać modelbinder bez ModelBinderProvider jest następujący:

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

To działało idealnie! Z jakiegokolwiek powodu nie mogłem uzyskać żadnego z innych przykładów na tej stronie do pracy z MVC4. Wygląda na to, że interfejs dla ModelBinderProvider się zmienił. Ale usunięcie ModelBinderProvider i dodanie tego kodu do Application_Start działało świetnie! –