E不小心

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

扩展Webapi中的RouteConstraint中,让DateTime类型,支持时间格式化(DateTimeFormat)

一、背景

大家在使用WebApi时,会用到DateTime为参数,类似于这样:

//url: xxx/2016-09-08
[HttpGet("{date:datetime}")]
public string Get(DateTime date)
{
    return date.ToString("yyyyMMdd");
}

但是":datetime" 支持这样的格式:

12/25/2009
11:45:00 PM
11:45:00
11:45
Apr 5 2009 11:45:00 PM
April 5 2009 11:45:00 PM
12/25/2009 11:45:00 PM
11:45:00 PM
2009-05-12T11:45:00Z

但我们有的时候想要的是类似这样的格式:

20091225
091225
12252009

或是各种自定义的时间格式。

二、目的

用简单的办法来自定义这个时间格式。比如正则":regex"是支持参数的,我们让默认的":datetime"来支持一个参数。 比如":datetime(yyyyMMdd)"

三、实现

要做一个自定义的 RouteConstraint ,我们要实现一个接口 IRouteConstraint


但我们可以偷个懒,我们找到DateTimeRouteConstraint的源码,做一些修改。

Routing 源码地址 :https://github.com/aspnet/Routing

找到 Routing/src/Microsoft.AspNetCore.Routing/Constraints/DateTimeRouteConstraint.cs

源码:

public class DateTimeRouteConstraint : IRouteConstraint
{
    /// <inheritdoc />
    public bool Match(
        HttpContext httpContext,
        IRouter route,
        string routeKey,
        RouteValueDictionary values,
        RouteDirection routeDirection)
    {
        if (httpContext == null)
        {
            throw new ArgumentNullException(nameof(httpContext));
        }
        if (route == null)
        {
            throw new ArgumentNullException(nameof(route));
        }
        if (routeKey == null)
        {
            throw new ArgumentNullException(nameof(routeKey));
        }
        if (values == null)
        {
            throw new ArgumentNullException(nameof(values));
        }
        object value;
        if (values.TryGetValue(routeKey, out value) && value != null)
        {
            if (value is DateTime)
            {
                return true;
            }
            DateTime result;
            var valueString = Convert.ToString(value, CultureInfo.InvariantCulture);
            return DateTime.TryParse(valueString, CultureInfo.InvariantCulture, DateTimeStyles.None, out result);
        }
        return false;
    }
}

我们来对这个做一点修改。给他增加两个构造函数。

一个有一个string参数,用来接受DateTimeFormat。
一个无参数的,用来兼容默认无参的情况。

别的不多说了,直接上代码。

DateTimeExRouteConstraint.cs

public class DateTimeExRouteConstraint : IRouteConstraint
{
    private readonly string _dateTimeformat;
    public DateTimeExRouteConstraint(string p_dateTimeformat)
    {
        _dateTimeformat = p_dateTimeformat;
    }
    public DateTimeExRouteConstraint()
    {
    }
    public bool Match(HttpContext httpContext, IRouter route, string routeKey, RouteValueDictionary values, RouteDirection routeDirection)
    {
        if (httpContext == null)
        {
            throw new ArgumentNullException(nameof(httpContext));
        }
        if (route == null)
        {
            throw new ArgumentNullException(nameof(route));
        }
        if (routeKey == null)
        {
            throw new ArgumentNullException(nameof(routeKey));
        }
        if (values == null)
        {
            throw new ArgumentNullException(nameof(values));
        }
        object value;
        if (values.TryGetValue(routeKey, out value) && value != null)
        {
            if (value is DateTime)
            {
                return true;
            }
            DateTime result;
            var valueString = Convert.ToString(value, CultureInfo.InvariantCulture);
            if (!string.IsNullOrEmpty(_dateTimeformat))
            {
                var success = DateTime.TryParseExact(valueString, _dateTimeformat, CultureInfo.InvariantCulture, DateTimeStyles.None, out result);
                if (success)
                {
                    values[routeKey] = result;
                }
                return success;
            }
            return DateTime.TryParse(valueString, CultureInfo.InvariantCulture, DateTimeStyles.None, out result);
        }
        return false;
    }
}

然后我们用这个新的 DateTimeExRouteConstraint 来替换默认的 RouteConstraint

找到 Startup.csConfigureServices 方法,添加

services.Configure<RouteOptions>(options => options.ConstraintMap["datetime"] = typeof(DateTimeExRouteConstraint));

四、使用

实现以后,我们就可以愉快的使用的DateTimeFormat 的方式了。


比如这样

//url: xxx/20160908
[HttpGet("{date:datetime(yyyyMMdd)}")]
public string Get(DateTime date)
{
    return date.ToString();
}

或者这样

//url: xxx/160908
[HttpGet("{date:datetime(yyMMdd)}")]
public string Get(DateTime date)
{
    return date.ToString();
}

再或者这样

//url: xxx/09082016
[HttpGet("{date:datetime(MMddyyyy)}")]
public string Get(DateTime date)
{
    return date.ToString();
}

全看你喜欢了。

本文地址:
http://www.cnblogs.com/gaoshang212/p/5855931.html

posted on 2016-09-09 11:39  E不小心  阅读(1718)  评论(1编辑  收藏  举报