2012-09-03 47 views
14

que necesito utilizar un modelbinder costumbre de algún tipo para tratar siempre las fechas de entrada en formato Reino Unido, He fijado un ligante modelo personalizado y registrado como tal:Asp.Net Web Api - ModelBinders

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

Esto sólo parece funcionar para querystring parámetros, y sólo funciona si especifica [ModelBinder] en mi parámetro como tal, está allí i manera de hacer todas las acciones que utilizan mi modelo ligante:

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

Además, ¿cómo puedo hacer que mi publicado forma a mi controlador Api para usar mi carpeta modelo?

Respuesta

5

Creo que usted no necesita un ligante modelo. Tu enfoque es incorrecto El enfoque correcto para las fechas es utilizar una biblioteca de globalización del lado del cliente como globalize library para analizar las fechas formateadas en cualquier idioma y transformarlas en objetos de fecha de JavaScript. Luego puede serializar sus estructuras de datos de datos en json con el navegador JSON.stringify, y esto debería funcionar. Es mejor usar siempre formatos estándar para las fechas y utilizar un formateador en lugar de un archivador modelo. Los formateadores disponibles también manejan TimeZones correctamente, si usa el parámetro tipo de sus objetos C# DateTime para especificar si la fecha y hora se expresa en hora local o en hora UTC.

+0

¿cómo formatearé todas mis fechas en el formato iso en el lado del cliente antes de publicar, ¿debo hacerlo manualmente antes de cada publicación para cada campo de fecha? parece un poco tedioso y repetitivo? –

+0

¡Absolutamente no! Puede personalizar la función JSON.stringify del navegador pasandole una función que reconozca las fechas y las transforme en las cadenas adecuadas. Una vez que haya hecho esto, puede simplemente llamar a JSON.stringify para transmitir su modelo js en json con el formato correcto para las fechas –

+0

En realidad, el comportamiento predeterminado de todas las funciones principales del navegador JSON.stringify debe ser transformar las fechas en formato iso ... .so que no tienes que hacer nada :) –

0

No necesita un archivador de modelo personalizado para eso. Debería ser bueno cambiando la cultura del hilo a Reino Unido o configurar su web.config settings para el Reino Unido, si esto es lo que su sitio está usando todo el tiempo.

Si no, aún puede cambiar DateTimeFormatInfo para CurrentCulture a UK.

También hay una buena publicación sobre carpetas modelo available here de Scott Hanselman.

Usted puede poner esto en Global.asax:

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

He intentado configurar esto en el web.config y no funciona para ApiControllers, si publico el mismo formulario en un controlador mvc funciona perfectamente, pero para un ApiController no parece respetar mi configuración de cultura –

5

Puede registrar un archivador de modelo globalmente implementando un ModelBinderProvider e insertándolo en la lista de servicios.

Ejemplo uso en Global.asax:

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

continuación se ejemplo de código que demuestra una ModelBinderProvider y una implemenation ModelProvider que convierte argumentos DateTime de una manera consciente de cultivo (usando la cultura hilos actual);

aplicación DateTimeModelBinderProvider: aplicación

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:

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 parece estar en conflicto con la unión modelo. Si utiliza atributo de direccionamiento, se puede envolver la configuración global.asax en una sola llamada GlobalConfiguration.Config para evitar los problemas de inicialización:

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

(esto podría fijarse en la próxima ASP.NET 5 si está relacionado con bug #1165.)