웹 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="<,>,%,&,*,\,?" />
.. :
유효하지 않은 문자의 표준 목록에서를 제거했습니다 .
더 쉽고 안전한 솔루션
귀하의 질문에 대한 답변은 아니지만 더 안전하고 쉬운 해결책은이 모든 것이 필요하지 않도록 요청을 변경하는 것입니다. 이는 두 가지 방법으로 수행 할 수 있습니다.
- 날짜를와 같은 쿼리 문자열 매개 변수로 전달합니다
?date=2012-12-31T22:00:00.000Z
. - 을 벗겨
.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 접근 방식을 사용하십시오.