【问题标题】:Parsing of custom format DateTime values in Web API routes解析 Web API 路由中的自定义格式 DateTime 值
【发布时间】:2015-05-05 09:15:56
【问题描述】:

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

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

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

System.Web.HttpException:检测到来自客户端 (:) 的潜在危险 Request.Path 值。

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

【问题讨论】:

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


    【解决方案1】:

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

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

    完成此操作后,当您收到请求时,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);
        }
    }
    

    你可以用这样的控制器来测试:

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

    由于idDateTimeWrapper 类型,它使用自定义转换器进行转换。

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

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

    在此之后,您可以在需要 DateTime 时使用此类的对象。

    注意:在这种情况下,更改 JSON.NET 序列化程序不会有任何作用。它仅用于反序列化 HTTP 请求的负载,但对路由参数没有任何作用。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-10-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-12-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多