Program Club

datetime 매개 변수를 전달하는 방법은 무엇입니까?

proclub 2020. 11. 5. 19:48
반응형

datetime 매개 변수를 전달하는 방법은 무엇입니까?


웹 API에 UTC 날짜를 전달하는 방법은 무엇입니까?

전달 2010-01-01은 정상적으로 작동하지만 2014-12-31T22:00:00.000Z(시간 구성 요소 포함)과 같은 UTC 날짜를 전달 하면 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에 전달하는 방법-또는 적어도 날짜 시간을 지정하는 방법은 무엇입니까?


문제는 두 가지입니다.

1. .경로에서

기본적으로 IIS는 점이있는 모든 URI를 정적 리소스로 취급하고이를 반환하고 추가 처리 (웹 API에 의한)를 모두 건너 뜁니다. 이것은 섹션의 Web.config에서 구성됩니다 . system.webServer.handlers기본 처리기가 처리합니다 path="*.". path속성 에서 이상한 구문에 관한 문서를 많이 찾을 수는 없지만 (정규식이 더 의미가 있었을 것입니다), 이것이 분명히 의미하는 것은 "점을 포함하지 않는 모든 것"(그리고 아래 2 번 지점의 문자)입니다. 따라서 이름의 'Extensionless' ExtensionlessUrlHandler-Integrated-4.0.

제 생각에는 '정확성'의 순서로 여러 가지 해결책이 가능합니다.

  • 점을 허용해야하는 경로에 대해 특별히 새 핸들러를 추가하십시오. 기본값 앞에 추가 해야 합니다. 이렇게하려면 먼저 기본 처리기 제거 하고 나중에 다시 추가해야합니다.
  • path="*."속성을로 변경하십시오 path="*". 그런 다음 모든 것을 잡을 것입니다. 그때부터 웹 API는 더 이상 점이있는 수신 호출을 정적 리소스로 해석하지 않습니다. 웹 API에서 정적 리소스를 호스팅하는 경우 권장되지 않습니다!
  • Web.config에 다음을 추가하여 모든 요청을 무조건 처리합니다. under <system.webserver>:<modules runAllManagedModulesForAllRequests="true">

2. :경로에서

위의 내용을 변경하면 기본적으로 다음과 같은 오류가 발생합니다.

클라이언트 (:)에서 잠재적으로 위험한 Request.Path 값이 감지되었습니다.

Web.config에서 미리 정의 된 허용되지 않는 / 잘못된 문자를 변경할 수 있습니다. 아래 <system.web>에 다음을 추가합니다 <httpRuntime requestPathInvalidCharacters="&lt;,&gt;,%,&amp;,*,\,?" />.. :유효하지 않은 문자의 표준 목록에서를 제거했습니다 .

더 쉽고 안전한 솔루션

귀하의 질문에 대한 답변은 아니지만 더 안전하고 쉬운 해결책은이 모든 것이 필요하지 않도록 요청을 변경하는 것입니다. 이는 두 가지 방법으로 수행 할 수 있습니다.

  1. 날짜를와 같은 쿼리 문자열 매개 변수로 전달합니다 ?date=2012-12-31T22:00:00.000Z.
  2. 을 벗겨 .000모든 요청에서. 여전히 :'s (cfr point 2) 를 허용해야합니다 .

나는 당신의 고통을 느낍니다 ... 또 다른 날짜 시간 형식 ... 당신이 필요로하는 것!

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)

....하지만 이것은 하나의 날짜 (startDate)로 작동하지만 어떤 이유로 endDate가이 형식이면 작동하지 않습니다. 몇 시간 동안 디버깅되었지만 단서 만 예외는 콜론 ":"을 좋아하지 않는다고 말합니다. web.config가 다음으로 설정되어 있지만

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

따라서 다른 날짜 형식 (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


in your Product Web API controller:

[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 method in Fiddler - Composer:

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

DateTime format:

yyyy-MM-ddTHH:mm:ss

javascript pass parameter use moment.js

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

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


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.


It used to be a painful task, but now we can use toUTCString():

Example:

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

Put the below into Ajax post request

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

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"

참고URL : https://stackoverflow.com/questions/14359566/how-to-pass-a-datetime-parameter

반응형