How to pass a datetime parameter?

后端 未结 10 1702
暗喜
暗喜 2020-11-29 01:56

How to pass UTC dates to Web API?

Passing 2010-01-01 works fine, but when I pass a UTC date such as 2014-12-31T22:00:00.000Z (with a time c

相关标签:
10条回答
  • 2020-11-29 02:37

    Since I have encoding ISO-8859-1 operating system the date format "dd.MM.yyyy HH:mm:sss" was not recognised what did work was to use InvariantCulture string.

    string url = "GetData?DagsPr=" + DagsProfs.ToString(CultureInfo.InvariantCulture)
    
    0 讨论(0)
  • 2020-11-29 02:39

    The problem is twofold:

    1. The . in the route

    By default, IIS treats all URI's with a dot in them as static resource, tries to return it and skip further processing (by Web API) altogether. This is configured in your Web.config in the section system.webServer.handlers: the default handler handles path="*.". You won't find much documentation regarding the strange syntax in this path attribute (regex would have made more sense), but what this apparently means is "anything that doesn't contain a dot" (and any character from point 2 below). Hence the 'Extensionless' in the name ExtensionlessUrlHandler-Integrated-4.0.

    Multiple solutions are possible, in my opinion in the order of 'correctness':

    • Add a new handler specifically for the routes that must allow a dot. Be sure to add it before the default. To do this, make sure you remove the default handler first, and add it back after yours.
    • Change the path="*." attribute to path="*". It will then catch everything. Note that from then on, your web api will no longer interpret incoming calls with dots as static resources! If you are hosting static resources on your web api, this is therefor not advised!
    • Add the following to your Web.config to unconditionally handle all requests: under <system.webserver>: <modules runAllManagedModulesForAllRequests="true">

    2. The : in the route

    After you've changed the above, by default, you'd get the following error:

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

    You can change the predefined disallowed/invalid characters in your Web.config. Under <system.web>, add the following: <httpRuntime requestPathInvalidCharacters="&lt;,&gt;,%,&amp;,*,\,?" />. I've removed the : from the standard list of invalid characters.

    Easier/safer solutions

    Although not an answer to your question, a safer and easier solution would be to change the request so that all this is not required. This can be done in two ways:

    1. Pass the date as a query string parameter, like ?date=2012-12-31T22:00:00.000Z.
    2. Strip the .000 from every request. You'd still need to allow :'s (cfr point 2).
    0 讨论(0)
  • 2020-11-29 02:39

    As a matter of fact, specifying parameters explicitly as ?date='fulldatetime' worked like a charm. So this will be a solution for now: don't use commas, but use old GET approach.

    0 讨论(0)
  • 2020-11-29 02:41

    I feel your pain ... yet another date time format... just what you needed!

    Using Web Api 2 you can use route attributes to specify parameters.

    so with attributes on your class and your method you can code up a REST URL using this utc format you are having trouble with (apparently its ISO8601, presumably arrived at using 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)
    

    .... BUT, although this works with one date (startDate), for some reason it doesnt work when the endDate is in this format ... debugged for hours, only clue is exception says it doesnt like colon ":" (even though web.config is set with :

    <system.web>
        <compilation debug="true" targetFramework="4.5.1" />
        <httpRuntime targetFramework="4.5.1" requestPathInvalidCharacters="" />
    </system.web>
    

    So, lets make another date format (taken from the polyfill for the ISO date format) and add it to the Javascript date (for brevity, only convert up to minutes):

    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';
            };
    
        }());
    }
    

    Then when you send the dates to the Web API 2 method, you can convert them from string to 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;
        }
    

    so the url would be

    http://domain/api/myrecordtype/daterange/20140302T0003Z/20140302T1603Z
    

    Hanselman gives some related info here:

    http://www.hanselman.com/blog/OnTheNightmareThatIsJSONDatesPlusJSONNETAndASPNETWebAPI.aspx

    0 讨论(0)
  • 2020-11-29 02:41

    As a similar alternative to s k's answer, I am able to pass a date formatted by Date.prototype.toISOString() in the query string. This is the standard ISO 8601 format, and it is accepted by .Net Web API controllers without any additional configuration of the route or action.

    e.g.

    var dateString = dateObject.toISOString(); // "2019-07-01T04:00:00.000Z"
    
    0 讨论(0)
  • 2020-11-29 02:43

    This is a solution and a model for possible solutions. Use Moment.js in your client to format dates, convert to unix time.

     $scope.startDate.unix()
    

    Setup your route parameters to be long.

    [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!
      }
    

    Create an extension method for Unix time. Unix DateTime Method

    0 讨论(0)
提交回复
热议问题