2012-09-03 43 views
14

我需要使用某种类型的自定义模型绑定器在英国的格式始终将传入的日期,我已经建立了自定义模型粘结剂和像这样注册:Asp.Net的Web API - ModelBinders

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

这只似乎为查询字符串参数工作,如果我在我的参数,像这样指定[ModelBinder的]唯一的作品,有我的方式,使所有操作用我的模型绑定:

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

而且,我怎么可以让我贴形式到我的Api控制器使用我的模型联编程序?

回答

5

我觉得你不需要一个模型粘合剂。你的方法是不正确的。日期的正确方法是使用客户端全球化库(如globalize library)来解析以任何语言格式化的日期,并将它们转换为JavaScript日期对象。然后你可以使用浏览器JSON.stringify在json中序列化你的datascript数据结构,这应该可以工作。 最好总是使用日期的标准格式,并使用格式化程序而不是模型绑定程序。如果您使用C#DateTime对象的参数指定日期时间是以本地时间还是以UTC时间表示,则可用格式化程序也可正确处理时区。

+0

在发布之前,我如何将客户端的所有日期格式化为iso格式,我是否需要在每个日期字段的每个帖子前手动执行此操作?似乎有点乏味和重复? –

+0

绝对不是!您可以通过传递一个识别日期并将其转换为适当字符串的函数来定制浏览器的JSON.stringify函数。一旦你完成了这个,你可以调用JSON.stringify来转换所有js模型在日期中使用正确的格式 –

+0

实际上,所有主浏览器JSON.stringify函数的默认行为应该是将日期转换为iso格式。所以你不必做任何事情:) –

0

您不需要自定义模型绑定器。如果这是您的网站始终在使用的内容,则您应该通过将线索文化更改为英国或为英国设置您的web.config settings

如果不是,您仍然可以将CurrentCulture的DateTimeFormatInfo更改为UK。

Scott Hanselman还有一篇关于模型粘合剂available here的好贴子。

你可以把这个Global.asax中:

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

我已经尝试在web.config中设置,它不适用于ApiControllers,如果我发布相同的窗体到一个mvc控制器,它完美的工作,但对一个ApiController它似乎并不尊重我的文化背景。 –

5

您可以通过实施ModelBinderProvider并将其插入到服务列表中来全局注册模型联编程序。在Global.asax中

实施例使用:

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

下面是示例代码演示一个ModelBinderProvider以及变换器,在培养知道地日期时间参数的ModelProvider实行(使用当前线程培养);

DateTimeModelBinderProvider实现:

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似乎与模型结合冲突。如果使用路由的属性,你可以包装global.asax配置成一个单一的GlobalConfiguration.Config呼吁避免初始化问题:

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

(这可能是固定在即将到来的ASP。NET 5如果它与bug #1165。)