如何传递date时间参数?
如何将UTCdate传递给Web API?
通过2010年1月1日工作正常,但是当我通过UTCdate,如2014-12-31T22:00:00.000Z
(与时间组件),我得到一个HTTP 404响应。 所以
http://domain/api/controller/action/2012-12-31T22:00:00.000Z
产生404错误响应,而
http://domain/api/controller/action/2012-12-31
工作正常。
如何将UTCdate传递给Web API – 或者至less指定date和时间?
我感觉到你的痛苦……又一个date时间格式…正是你需要的!
使用Web Api 2,您可以使用路由属性来指定参数。
所以对于你的类和你的方法的属性,你可以使用这种utc格式编码一个REST URL(显然它的ISO8601,大概是使用了startDate.toISOString())
[Route(@"daterange/{startDate:regex(^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.\d{3}Z$)}/{endDate:regex(^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.\d{3}Z$)}")] [HttpGet] public IEnumerable<MyRecordType> GetByDateRange(DateTime startDate, DateTime endDate)
….但是,虽然这与一个date(startDate)工作,由于某种原因,它不工作,当endDate是在这种格式…debugging了几个小时,只有线索是exception说,它不像冒号“:”(偶虽然web.config设置为:
<system.web> <compilation debug="true" targetFramework="4.5.1" /> <httpRuntime targetFramework="4.5.1" requestPathInvalidCharacters="" /> </system.web>
因此,让我们制作另一种date格式(从ISOdate格式的polyfill中获取)并将其添加到Javascriptdate(为简洁起见,只能转换成分钟):
if (!Date.prototype.toUTCDateTimeDigits) { (function () { function pad(number) { if (number < 10) { return '0' + number; } return number; } Date.prototype.toUTCDateTimeDigits = function () { return this.getUTCFullYear() + pad(this.getUTCMonth() + 1) + pad(this.getUTCDate()) + 'T' + pad(this.getUTCHours()) + pad(this.getUTCMinutes()) + 'Z'; }; }()); }
然后,当您将date发送到Web API 2方法时,可以将它们从string转换为date:
[RoutePrefix("api/myrecordtype")] public class MyRecordTypeController : ApiController { [Route(@"daterange/{startDateString}/{endDateString}")] [HttpGet] public IEnumerable<MyRecordType> GetByDateRange([FromUri]string startDateString, [FromUri]string endDateString) { var startDate = BuildDateTimeFromYAFormat(startDateString); var endDate = BuildDateTimeFromYAFormat(endDateString); ... } /// <summary> /// Convert a UTC Date String of format yyyyMMddThhmmZ into a Local Date /// </summary> /// <param name="dateString"></param> /// <returns></returns> private DateTime BuildDateTimeFromYAFormat(string dateString) { Regex r = new Regex(@"^\d{4}\d{2}\d{2}T\d{2}\d{2}Z$"); if (!r.IsMatch(dateString)) { throw new FormatException( string.Format("{0} is not the correct format. Should be yyyyMMddThhmmZ", dateString)); } DateTime dt = DateTime.ParseExact(dateString, "yyyyMMddThhmmZ", CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal); return dt; }
所以url会
http://domain/api/myrecordtype/daterange/20140302T0003Z/20140302T1603Z
Hanselman在这里提供一些相关信息:
http://www.hanselman.com/blog/OnTheNightmareThatIsJSONDatesPlusJSONNETAndASPNETWebAPI.aspx
问题是双重的:
1 .
在路线
默认情况下,IIS将所有的URI都以点作为静态资源,尝试将其返回并完全跳过进一步处理(通过Web API)。 这在system.webServer.handlers
部分的Web.config中configuration:默认处理程序处理path="*."
。 你不会在这个path
属性中find很多关于这个奇怪语法的文档(正则expression式会更有意义),但是这显然意味着什么是“不包含任何点的东西”(以及下面第二点的任何字符)。 因此名为ExtensionlessUrlHandler-Integrated-4.0
的“Extensionless”。
我认为按照“正确性”的顺序,可能有多种解决scheme:
- 为必须允许点的路由添加一个新的处理程序。 一定要在默认之前添加它。 要做到这一点,请确保先删除默认处理程序,然后将其添加回去。
- 更改
path="*."
属性为path="*"
。 它会抓住一切。 请注意,从那时起,您的web api将不再将带有点的来电解释为静态资源! 如果你在你的web api上托pipe静态资源,这是不build议的! - 将以下内容添加到Web.config中,以无条件处理所有请求:在
<system.webserver>
:<modules runAllManagedModulesForAllRequests="true">
2.在路线上
在你改变了上面的内容之后,默认情况下会出现以下错误:
从客户端(:)中检测到有潜在危险的Request.Path值。
您可以更改Web.config中预定义的不允许/无效字符。 在<system.web>
,添加以下内容: <httpRuntime requestPathInvalidCharacters="<,>,%,&,*,\,?" />
<httpRuntime requestPathInvalidCharacters="<,>,%,&,*,\,?" />
。 我从无效字符的标准列表中删除了:
更简单/更安全的解决scheme
虽然不是您的问题的答案,但更安全和更简单的解决scheme将是更改请求,以便所有这些不是必需的:
- 将date作为查询stringparameter passing,如
?date=2012-12-31T22:00:00.000Z
。 - 从每个请求中剥离
.000
。 你仍然需要允许:
(cfr第二点)。
这是可能的解决scheme的解决scheme和模型。 在客户端使用Moment.js格式化date,转换为unix时间。
$scope.startDate.unix()
设置你的路由参数很长。
[Route("{startDate:long?}")] public async Task<object[]> Get(long? startDate) { DateTime? sDate = new DateTime(); if (startDate != null) { sDate = new DateTime().FromUnixTime(startDate.Value); } else { sDate = null; } ... your code here! }
为Unix时间创build一个扩展方法。 Unix DateTime方法
在您的产品Web API控制器中:
[RoutePrefix("api/product")] public class ProductController : ApiController { private readonly IProductRepository _repository; public ProductController(IProductRepository repository) { this._repository = repository; } [HttpGet, Route("orders")] public async Task<IHttpActionResult> GetProductPeriodOrders(string productCode, DateTime dateStart, DateTime dateEnd) { try { IList<Order> orders = await _repository.GetPeriodOrdersAsync(productCode, dateStart.ToUniversalTime(), dateEnd.ToUniversalTime()); return Ok(orders); } catch(Exception ex) { return NotFound(); } } }
在Fiddler – Composer中testingGetProductPeriodOrders方法:
http://localhost:46017/api/product/orders?productCode=100&dateStart=2016-12-01T00:00:00&dateEnd=2016-12-31T23:59:59
date时间格式:
yyyy-MM-ddTHH:mm:ss
javascript传递参数使用了moment.js
const dateStart = moment(startDate).format('YYYY-MM-DDTHH:mm:ss'); const dateEnd = moment(endDate).format('YYYY-MM-DDTHH:mm:ss');
事实上,将参数明确地指定为?date ='fulldatetime'就像魅力一样工作。 所以现在这将是一个解决scheme:不要使用逗号,而是使用旧的GET方法。
它曾经是一个痛苦的任务,但现在我们可以使用toUTCString():
例:
[HttpPost] public ActionResult Query(DateTime Start, DateTime End)
把下面的Ajax post请求
data: { Start: new Date().toUTCString(), End: new Date().toUTCString() },