2012-09-03 25 views
14

Ich brauche einen benutzerdefinierten Modelbinder irgendeine Art zu verwenden, um immer eingehende Daten in UK-Format zu behandeln, ich habe Setup ein Bindemittel benutzerdefiniertes Modells und registrierte wie so:Asp.Net Web Api - Modelbinder

GlobalConfiguration.Configuration.BindParameter(typeof(DateTime), new DateTimeModelBinder()); 

Dies nur scheint für Abfragezeichenfolgen-Parameter zu arbeiten, und funktioniert nur, wenn ich angeben [Modelbinder] auf meinem Parameter wie ja, gibt es i Art und Weise alle Aktionen verwenden, um meine Binder Modell zu machen:

public IList<LeadsLeadRowViewModel> Get([ModelBinder]LeadsIndexViewModel inputModel) 

auch, wie kann ich meine gepostet Formular an meinen Api-Controller, um meinen Modellbinder zu verwenden?

Antwort

5

Ich glaube, Sie brauchen nicht ein Modell Bindemittel. Deine Vorgehensweise ist falsch. Der richtige Ansatz für Datumsangaben besteht darin, eine Client-seitige Globalisierungsbibliothek wie die globalize library zu verwenden, um in einer beliebigen Sprache formatierte Datumsangaben zu analysieren und in JavaScript-Datumsobjekte umzuwandeln. Dann können Sie Ihre Datenstrukturen in json mit dem Browser JSON.stringify serialisieren, und das sollte funktionieren. Es ist besser, für Datumsangaben immer Standardformate zu verwenden und statt eines Modellbinders einen Formatierer zu verwenden. Verfügbare Formatierer verarbeiten auch Zeitzonen korrekt, wenn Sie den -Typ-Parameter Ihrer C# DateTime-Objekte verwenden, um anzugeben, ob die Datumszeit in Ortszeit oder in UTC-Zeit ausgedrückt wird.

+0

Wie formatiere ich alle meine Daten auf dem iso-Format auf der Client-Seite vor der Buchung, muss ich dies manuell vor jedem Beitrag für jedes Datenfeld tun? scheint ein wenig langweilig und wiederholend? –

+0

Absolut nicht! Sie können die JSON.stringify-Funktion des Browsers anpassen, indem Sie ihr eine Funktion übergeben, die Datumsangaben erkennt und sie in die entsprechenden Zeichenfolgen umwandelt. Sobald Sie dies getan haben, können Sie einfach JSON.stringify aufrufen, um alle Ihre js-Modell in Json mit dem richtigen Format für Termine zu konvertieren –

+0

Eigentlich sollte das Standardverhalten aller Haupt-Browser JSON.stringify Funktion sein, Daten in ISO-Format zu transformieren. .so müssen Sie nichts tun :) –

0

Sie benötigen keinen benutzerdefinierten Modellbinder dafür. Sie sollten gut sein, indem Sie die Thread-Kultur in UK ändern oder Ihre web.config settings für Großbritannien festlegen, wenn dies Ihre Website ständig verwendet.

Wenn nicht, können Sie die DateTimeFormatInfo für die CurrentCulture immer noch in UK ändern.

Es gibt auch eine gute Post über Modellbinder available here von Scott Hanselman.

Sie können dies in Global.asax setzen:

ModelBinders.Binders[typeof(DateTime)] = new DateAndTimeModelBinder() 
+4

Ich habe versucht Einstellungen in der web.config und es funktioniert nicht für ApiControllers, wenn ich das gleiche Formular auf einem MVC-Controller posten funktioniert es perfekt, aber zu einem ApiController es scheint meine Kultureinstellungen nicht zu respektieren. –

5

Sie können einen Modellbinder global registrieren, indem Sie einen ModelBinderProvider implementieren und ihn in die Liste der Dienste einfügen.

Beispiel für die Verwendung in Global.asax:

GlobalConfiguration.Configuration.Services.Insert(typeof(ModelBinderProvider), 0, new Core.Api.ModelBinders.DateTimeModelBinderProvider()); 

Unten ist ein Beispiel-Code und einen ModelBinderProvider ModelProvider Implemenation demonstriert Datumzeit Argumente in einer Kultur bewusst Weise umwandelt (die aktuelle Fäden Kultur verwendet wird);

DateTimeModelBinderProvider Umsetzung:

using System; 
using System.Web.Http; 
using System.Web.Http.ModelBinding; 

...

public class DateTimeModelBinderProvider : ModelBinderProvider 
{ 
    readonly DateTimeModelBinder binder = new DateTimeModelBinder(); 

    public override IModelBinder GetBinder(HttpConfiguration configuration, Type modelType) 
    { 
     if (DateTimeModelBinder.CanBindType(modelType)) 
     { 
      return binder; 
     } 

     return null; 
    } 
} 

DateTimeModelBinder Umsetzung:

public class DateTimeModelBinder : IModelBinder 
{ 
    public bool BindModel(HttpActionContext actionContext, ModelBindingContext bindingContext) 
    { 
     ValidateBindingContext(bindingContext); 

     if (!bindingContext.ValueProvider.ContainsPrefix(bindingContext.ModelName) || 
      !CanBindType(bindingContext.ModelType)) 
     { 
      return false; 
     } 

     bindingContext.Model = bindingContext.ValueProvider 
      .GetValue(bindingContext.ModelName) 
      .ConvertTo(bindingContext.ModelType, Thread.CurrentThread.CurrentCulture); 

     bindingContext.ValidationNode.ValidateAllProperties = true; 

     return true; 
    } 

    private static void ValidateBindingContext(ModelBindingContext bindingContext) 
    { 
     if (bindingContext == null) 
     { 
      throw new ArgumentNullException("bindingContext"); 
     } 

     if (bindingContext.ModelMetadata == null) 
     { 
      throw new ArgumentException("ModelMetadata cannot be null", "bindingContext"); 
     } 
    } 

    public static bool CanBindType(Type modelType) 
    { 
     return modelType == typeof(DateTime) || modelType == typeof(DateTime?); 
    } 
} 
2

Attribute routing scheint mit Modell-Bindung an in Konflikt geraten. Wenn Sie Routing-Attribut verwenden, können Sie die global.asax Konfiguration in einem einzigen GlobalConfiguration.Config Anruf wickeln Sie die Initialisierung Probleme zu vermeiden:

GlobalConfiguration.Configure(config => 
{ 
    config.BindParameter(typeof(DateTime), new DateTimeModelBinder()); 
    config.MapHttpAttributeRoutes(); 
} 

(Dies könnte in der kommenden ASP festgelegt werden.NET 5, wenn es sich um bug #1165 handelt.)