[asp.net] 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) 를 허용해야합니다 .


답변

제품 웹 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에서 GetProductPeriodOrders 메서드 테스트 :

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 parameter use moment.js

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


답변

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

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


답변

sk의 대답과 유사한 대안으로 Date.prototype.toISOString()쿼리 문자열에 형식이 지정된 날짜를 전달할 수 있습니다. 이것은 표준 ISO 8601 형식이며 라우트 또는 작업의 추가 구성없이 .Net Web API 컨트롤러에서 허용됩니다.

예 :

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


답변

이것은 가능한 솔루션의 솔루션이자 모델입니다. 클라이언트에서 Moment.js를 사용하여 날짜 형식을 지정하고 유닉스 시간으로 변환하십시오.

 $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 메서드


답변

예전에는 힘든 작업 이었지만 이제는 toUTCString ()을 사용할 수 있습니다.

예:

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

Ajax 게시물 요청에 아래를 입력하십시오.

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


답변

사실, 매개 변수를 명시 적으로? date = ‘fulldatetime’으로 지정하는 것은 매력처럼 작동했습니다. 따라서 이것은 현재 해결책이 될 것입니다. 쉼표를 사용하지 말고 오래된 GET 접근 방식을 사용하십시오.