Rest Web API路由中自定义格式日期时间值的解析

Rest Web API路由中自定义格式日期时间值的解析,rest,datetime,url,asp.net-web-api,asp.net-web-api2,Rest,Datetime,Url,Asp.net Web Api,Asp.net Web Api2,我希望在我的路线中使用DateTime值,如下所示: /api/items/after/2015-08-01T08:00:00 public class TestController : ApiController { // GET api/<controller>/5 public string Get(DateTimeWrapper id) { return id.Value.ToString(CultureInfo.InvariantC

我希望在我的路线中使用
DateTime
值,如下所示:

/api/items/after/2015-08-01T08:00:00
public class TestController : ApiController
{
    // GET api/<controller>/5
    public string Get(DateTimeWrapper id)
    {
        return id.Value.ToString(CultureInfo.InvariantCulture);
    }
}
但它不起作用的原因很明显:

System.Web.HttpException:一个潜在危险的请求。从客户端(:)检测到路径值


我不想逃避
。显然,我需要不同的格式,如
2015-08-01T08-00-00
,以获得好看的URL。可以通过更改Json.NET中的默认
DateTime
序列化格式来解决此问题,但在这种情况下,它将被全局应用。或者,我可以试着写一个定制的活页夹。我想知道是否有更好(更容易)的方法。也许框架提供了一些现成的配置参数?

实现这一点的简单方法如下:

  • 实现一个具有DateTime属性的类,在该类中您将反序列化DateTime值,例如
    DateTimeWrapper
  • 将路由参数定义为此类,而不是
    DateTime
  • 创建一个类型转换器,通过继承
    TypeConverter
    ,它可以将url段字符串转换为
    DateTimeWrapper
    类。您可以称之为
    DateTimeWrapperConverter
  • 使用如下属性装饰您的
    DateTimeWrapper
    [TypeConverter(typeof(DateTimeWrapperConverter))]
完成此操作后,当收到请求时,
DateTimeWrapper
类的任何路由参数都将由转换器处理。然后,您只需读取自定义转换器创建的
DateTimeWrapper
DateTime
属性

这样可以避免修改
DateTime
值的常规行为

这是一个示例实现,但缺少解析本身:

[TypeConverter(typeof(DateTimeWrapperConverter))]
public class DateTimeWrapper
{
    public DateTime Value { get; set; }
}

public class DateTimeWrapperConverter : TypeConverter
{
    public override bool CanConvertFrom(
       ITypeDescriptorContext context, Type sourceType)
    {
        if (sourceType == typeof (string))
        {
            return true;
        }
        return base.CanConvertFrom(context, sourceType);
    }

    public override object ConvertFrom(
         ITypeDescriptorContext context, CultureInfo culture, object value)
    {
        if (value is string)
        {
            DateTimeWrapper wrapper = new DateTimeWrapper
            {
                Value = new DateTime() // parse the url segment !!
            };
            return wrapper;
        }
        return base.ConvertFrom(context, culture, value);
    }
}
您可以通过以下方式测试控制器:

/api/items/after/2015-08-01T08:00:00
public class TestController : ApiController
{
    // GET api/<controller>/5
    public string Get(DateTimeWrapper id)
    {
        return id.Value.ToString(CultureInfo.InvariantCulture);
    }
}
在此之后,只要需要
DateTime
,就可以使用此类的对象

注意:在这个实例中,更改JSON.NET序列化程序不会起任何作用。它只用于反序列化HTTP请求的有效负载,而不涉及路由参数