【AspNetCore】【WebApi】擴展Webapi中的RouteConstraint中,讓DateTime類型,支持時間格式化(DateTimeFormat)

擴展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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章