【问题标题】:Using HttpClient to Send Dates in URL Using AttributeRouting使用 HttpClient 使用 AttributeRouting 在 URL 中发送日期
【发布时间】:2013-08-05 21:06:48
【问题描述】:

我在获取 WebAPI 接受的日期范围查询时遇到了一些问题。据我所知,这应该可以正常工作,但我仍然收到 400 Bad Request 回复。

我的 API 路由如下所示:

    [System.Web.Http.HttpGet]
    [GET("range/{start:datetime}/{end:datetime}")]
    public HttpResponseMessage Get(DateTime start, DateTime end)

我正在使用AttributeRouting 库,根据this page,我请求的 URL 应该没问题。

我的请求 URL 如下所示:

http://localhost:51258/plots/range/2013-07-29T21:58:39/2013-08-05T21:58:39

我在控制器 RoutePrefix("plots") 上设置了这个,这是 URL 路由的 plots 位的来源。

如果我去掉 DateTime 对象的时间,一切正常,但我需要时间过去。

【问题讨论】:

  • 这可能是因为这不是 C# 中的标准 DateTime 格式。日期部分很好,时间也很好,但是它们之间的 T 使它不标准。我会尝试用空格替换它。如果这行得通,那么您就会知道需要做什么。
  • 我添加了 T,因为它也不适用于空格或编码空格。根据 Mike Wasson(在页面链接中)的说法,添加 T 是合法的,应该可以正常工作。
  • 您是否将他提到的正则表达式(在链接中)添加到您的 DateTime 中?那么只有“yyyy-mm-dd”形式的日期才会匹配。
  • 不,在我让这个基本实现工作之前,我一直让它尽可能简单。
  • 我刚刚访问了 API 上的 routes.axd 页面并尝试执行请求 http://localhost:51258/plots/range/2013-07-29T21:58:39/2013-07-29T21:58:39 并收到此错误 A potentially dangerous Request.Path value was detected from the client (:). 所以看来 : 实际上可能是一个非法字符.. .

标签: c# datetime asp.net-web-api attributerouting


【解决方案1】:

经过大量阅读后,似乎可以做我想做的事情,但需要放松许多有用的安全措施才能做到这一点。由于有一个简单的解决方法,鉴于安全风险增加,放松这些措施是没有意义的。

我在 API 上遇到的错误是:

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

显然这是用于分隔DateTime 字符串的时间部分元素的冒号字符。所以我做了以下改动。

我的 Api 操作方法现在看起来像这样:

[System.Web.Http.HttpGet]
[GET("range?{startDate:datetime}&{endDate:datetime}")]
public HttpResponseMessage Get(DateTime startDate, DateTime endDate)

日期现在被定义为查询字符串的一部分,而不是路径本身的一部分。

为了处理查询字符串的创建,我还有以下扩展方法:

public static string ToQueryString(this NameValueCollection source, bool removeEmptyEntries)
{
    return source != null ? "?" + String.Join("&", source.AllKeys
        .Where(key => !removeEmptyEntries || source.GetValues(key).Any(value => !String.IsNullOrEmpty(value)))
        .SelectMany(key => source.GetValues(key)
            .Where(value => !removeEmptyEntries || !String.IsNullOrEmpty(value))
            .Select(value => String.Format("{0}={1}", HttpUtility.UrlEncode(key), value != null ? HttpUtility.UrlEncode(value) : string.Empty)))
        .ToArray())
        : string.Empty;
}

在我的客户端代码中使用如下:

var queryStringParams = new NameValueCollection
    {
        {"startDate", start.ToString(_dateService.DefaultDateFormatStringWithTime)},
        {"endDate", end.ToString(_dateService.DefaultDateFormatStringWithTime)}
    };

var response = httpClient.GetAsync(ApiRootUrl + "plots/range" + queryStringParams.ToQueryString(true)).Result;

我的应用程序中的日期服务仅提供默认日期格式字符串并使用此模式:

"yyyy-MM-ddTHH:mm:ss"

由此生成的完整 URI 如下所示:

http://localhost:51258/plots/range?startDate=2013-07-30T21%3A48%3A26&endDate=2013-08-06T21%3A48%3A26

希望这对将来的其他人有所帮助。

【讨论】:

    【解决方案2】:

    : 是 URL 中的保留字符,但在查询字符串中是可以接受的。因此,如果它适用于您的路由,您可以简单地使用:

    [System.Web.Http.HttpGet]
    [GET("range")]
    public HttpResponseMessage Get(DateTime start, DateTime end)
    

    您的 URL 请求可能如下所示:

    http://localhost:51258/plots/range?start=2013-07-29T21:58:39&end=2013-08-05T21:58:39
    

    【讨论】:

      猜你喜欢
      • 2012-04-30
      • 1970-01-01
      • 1970-01-01
      • 2013-06-03
      • 1970-01-01
      • 2019-08-15
      • 2019-10-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多