Подтвердить что ты не робот

Как передать параметр datetime?

Как передать даты UTC в веб-API?

Передача 2010-01-01 работает нормально, но когда я передаю дату UTC, например 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

отлично работает.

Как передать даты UTC в Web API, а затем - или, по крайней мере, указать дату и время?

4b9b3361

Ответ 1

Проблема двоякая:

1. . в пути

По умолчанию IIS рассматривает все URI с точкой в них как статический ресурс, пытается вернуть его и вообще пропустить дальнейшую обработку (через Web API). Это настраивается в вашем файле Web.config в разделе system.webServer.handlers: обработчик по умолчанию обрабатывает path="*." , Вы не найдете много документации относительно странного синтаксиса в этом атрибуте path (регулярное выражение имело бы больше смысла), но это, очевидно, означает "все, что не содержит точку" (и любой символ из пункта 2 ниже). Отсюда и "Расширение без расширения" в названии ExtensionlessUrlHandler-Integrated-4.0.

Множество решений возможно, на мой взгляд, в порядке "правильности":

  • Добавьте новый обработчик специально для маршрутов, которые должны разрешать точку. Обязательно добавьте его до значения по умолчанию. Чтобы сделать это, убедитесь, что вы сначала удалили обработчик по умолчанию, а затем добавили его обратно после своего.
  • Изменить path="*." атрибут path="*". Это тогда поймает все. Обратите внимание, что с этого момента ваш веб-интерфейс больше не будет интерпретировать входящие вызовы с точками как статические ресурсы! Если вы размещаете статические ресурсы в своем веб-интерфейсе, это не рекомендуется!
  • Добавьте следующее в ваш Web.config для безусловной обработки всех запросов: в <system.webserver>: <modules runAllManagedModulesForAllRequests="true">

2. : в маршруте

После того, как вы изменили вышеуказанное, по умолчанию вы получите следующую ошибку:

От клиента было обнаружено потенциально опасное значение Request.Path(:).

Вы можете изменить предопределенные запрещенные/недействительные символы в вашем файле Web.config. В разделе <system.web> добавьте следующее: <httpRuntime requestPathInvalidCharacters="&lt;,&gt;,%,&amp;,*,\,?"/> <httpRuntime requestPathInvalidCharacters="&lt;,&gt;,%,&amp;,*,\,?"/>. Я удалил : из стандартного списка недопустимых символов.

Более простые/безопасные решения

Хотя это и не ответ на ваш вопрос, более безопасным и простым решением было бы изменить запрос так, чтобы все это не требовалось. Это можно сделать двумя способами:

  1. Передайте дату в качестве параметра строки запроса, например ?date=2012-12-31T22:00:00.000Z.
  2. .000 с каждого запроса. Вам все еще нужно разрешить : (см. Пункт 2).

Ответ 2

Я чувствую вашу боль... еще один формат даты... просто то, что вам нужно!

С помощью Web Api 2 вы можете использовать атрибуты маршрута для указания параметров.

поэтому с атрибутами вашего класса и вашего метода вы можете закодировать URL-адрес REST, используя этот формат utc, с которым вы столкнулись (по-видимому, его 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)

.... НО, хотя это работает с одной датой (startDate), по какой-то причине он не работает, когда endDate находится в этом формате... отлаживается в течение нескольких часов, только ключ исключений говорит, что он не любит двоеточие ":" (хотя web.config устанавливается с помощью:

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

Итак, давайте создадим другой формат даты (взятый из polyfill для формата даты ISO) и добавим его к дате Javascript (для краткости, только конвертировать до нескольких минут):

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

    }());
}

Затем, когда вы отправляете даты в метод Web API 2, вы можете преобразовать их из строки в дату:

[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

Ответ 3

в вашем API-интерфейсе 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();
        }
    }
}

test Метод GetProductPeriodOrders в Fiddler - Композитор:

http://localhost:46017/api/product/orders?productCode=100&dateStart=2016-12-01T00:00:00&dateEnd=2016-12-31T23:59:59

Формат DateTime:

yyyy-MM-ddTHH:mm:ss

Использовать параметр javascript pass use moment.js

const dateStart = moment(startDate).format('YYYY-MM-DDTHH:mm:ss');
const dateEnd = moment(endDate).format('YYYY-MM-DDTHH:mm:ss');

Ответ 4

Это решение и модель возможных решений. Используйте Moment.js в своем клиенте, чтобы форматировать даты, конвертировать в 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-времени. Unix DateTime Method

Ответ 5

Фактически, задание параметров явно как? date = 'fulldatetime' работало как шарм. Таким образом, это будет решением на данный момент: не используйте запятые, но используйте старый подход GET.

Ответ 6

Раньше это была болезненная задача, но теперь мы можем использовать toUTCString():

Пример:

[HttpPost]
public ActionResult Query(DateTime Start, DateTime End)

Поместите нижеприведенный запрос на отправку Ajax

data: {
    Start: new Date().toUTCString(),
    End: new Date().toUTCString()
},

Ответ 7

В качестве Date.prototype.toISOString() альтернативы sk answer, я могу передать дату, отформатированную Date.prototype.toISOString() в строке запроса. Это стандартный формат ISO 8601, и он принят контроллерами .Net Web API без какой-либо дополнительной настройки маршрута или действия.

например

var dateString = dateObject.toISOString(); // "2019-07-01T04:00:00.000Z"