rest - 解析 Web API 路由中的自定义格式 DateTime 值

标签 rest datetime url asp.net-web-api asp.net-web-api2

我想在我的 route 使用 DateTime 值,如下所示:

/api/items/after/2015-08-01T08:00:00

但由于明显的原因它不起作用:

System.Web.HttpException: A potentially dangerous Request.Path value was detected from the client (:).

我不想转义:。显然,我需要不同的格式,例如 2015-08-01T08-00-00 以获得美观​​的网址。可以通过更改 Json.NET 中默认的 DateTime 序列化格式来解决,但在这种情况下它将全局应用。或者,我可以尝试编写自定义 Binder 。我想知道是否有更好(更简单)的方法。也许框架提供了一些开箱即用的配置参数?

最佳答案

执行此操作的简单方法如下:

  • 实现一个具有 DateTime 属性的类,您将在其中反序列化 DateTime 值,例如 DateTimeWrapper
  • 将路由参数定义为此类,而不是 DateTime
  • 创建一个类型转换器,通过继承 TypeConverter,将 url 段字符串转换为 DateTimeWrapper 类。您可以将其称为DateTimeWrapperConverter
  • 使用如下属性装饰您的 DateTimeWrapper[TypeConverter(typeof(DateTimeWrapperConverter))]

完成此操作后,当您收到请求时,DateTimeWrapper 类的任何路由参数都将由您的转换器处理。然后,您只需读取自定义转换器创建的 DateTimeWrapperDateTime 属性即可。

通过这种方式,您可以避免修改 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);
    }
}

您可以使用这样的 Controller 进行测试:

public class TestController : ApiController
{
    // GET api/<controller>/5
    public string Get(DateTimeWrapper id)
    {
        return id.Value.ToString(CultureInfo.InvariantCulture);
    }
}

由于 id 的类型为 DateTimeWrapper,因此它是使用自定义转换器进行转换的。

如果您愿意,可以更改 DateTimeWrapper,使其隐式转换为 DateTime,这样您就不需要读取 Value 属性。将其添加到 DateTimeWrapper 类中:

public static implicit operator DateTime(DateTimeWrapper wrapper)
{
    return wrapper.Value;
}

此后,只要需要 DateTime,您就可以使用此类的对象。

注意:在此实例中更改 JSON.NET 序列化程序不会执行任何操作。它仅用于反序列化 HTTP 请求的负载,但对路由参数不执行任何操作。

关于rest - 解析 Web API 路由中的自定义格式 DateTime 值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30048812/

相关文章:

C# 如何将 HttpClient Keep-Alive 设置为 false

python - 有没有办法在 Pandas 中显示 24 小时以上的时间数据?

html - 在 h1 标签旁边获取背景 url 图片,不起作用

python - 在列表中查找离今天最近的日期

datetime - Apache Pig:将当前日期和时间作为常数添加到每个生成的记录中

javascript - AngularJS 全局可选哈希参数

regex - 我如何检测哪些是 Imgur 图片链接,哪些不是?

http - if-match HTTP header 是否需要两阶段提交?

javascript - 使用 dd-mm-yyyy 格式的 SharePoint 列表过滤器

spring - Jersey REST API 作为一个单独的网络应用程序