108

UTC日付をWeb 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に渡す方法、または少なくとも日付時刻を指定する方法は?

4

11 に答える 11

41

問題は 2 つあります。

1..ルート中

既定では、IIS はドットを含むすべての URI を静的リソースとして扱い、それを返そうと試み、それ以降の処理 (Web API による) を完全にスキップします。これは、セクションの Web.config で構成されますsystem.webServer.handlers: デフォルト ハンドラー ハンドルpath="*."。この属性の奇妙な構文に関するドキュメントはあまり見つかりませんがpath(正規表現の方が理にかなっています)、これが意味するのは明らかに「ドットを含まないもの」(および以下のポイント 2 の任意の文字) です。したがって、名前の「拡張なし」ExtensionlessUrlHandler-Integrated-4.0

私の意見では、「正確さ」の順序で複数の解決策が可能です。

  • ドットを許可する必要があるルート専用の新しいハンドラーを追加します。デフォルトの前に必ず追加してください。これを行うには、最初にデフォルトのハンドラーを削除してから、自分のハンドラーの後に再度追加してください。
  • path="*."属性を に変更しますpath="*"。その後、すべてをキャッチします。それ以降、Web API はドットを含む着信呼び出しを静的リソースとして解釈しなくなることに注意してください。Web API で静的リソースをホストしている場合、これはお勧めできません。
  • 以下を Web.config に追加して、すべてのリクエストを無条件に処理します<system.webserver><modules runAllManagedModulesForAllRequests="true">

2.:ルート中

上記を変更すると、デフォルトで次のエラーが発生します。

潜在的に危険な Request.Path 値がクライアント (:) から検出されました。

Web.config で定義済みの許可されていない/無効な文字を変更できます。の下<system.web>に、次を追加します<httpRuntime requestPathInvalidCharacters="&lt;,&gt;,%,&amp;,*,\,?" />:無効な文字の標準リストからを削除しました。

より簡単で安全なソリューション

あなたの質問への回答ではありませんが、より安全で簡単な解決策は、リクエストを変更して、これがすべて不要になるようにすることです。これには、次の 2 つの方法があります。

  1. のように、日付をクエリ文字列パラメーターとして渡します?date=2012-12-31T22:00:00.000Z
  2. .000すべてのリクエストから を取り除きます。を許可する必要があります:(ポイント 2 を参照)。
于 2015-10-26T12:04:03.630 に答える
19

私はあなたの痛みを感じます...さらに別の日時形式...まさにあなたが必要としていたものです!

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)

....しかし、これは1つの日付(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

ハンセルマンは、ここでいくつかの関連情報を提供します:

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

于 2014-03-01T05:22:54.870 に答える
7

これは解決策であり、可能な解決策のモデルです。クライアントで 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 メソッド

于 2016-02-19T20:18:38.807 に答える
4

以前は骨の折れる作業でしたが、toUTCString() を使用できるようになりました。

例:

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

以下をAjax投稿リクエストに入れます

data: {
    Start: new Date().toUTCString(),
    End: new Date().toUTCString()
},
于 2016-09-17T08:01:37.707 に答える
3

実際のところ、パラメーターを?date ='fulldatetime'として明示的に指定することは、魅力のように機能しました。したがって、これは今のところ解決策になります。コンマは使用せず、古いGETアプローチを使用してください。

于 2013-01-16T15:30:48.043 に答える
0

あなたのコードを見ると、DateTime オブジェクトの「時間」について心配していないと思います。その場合、日付、月、年を整数パラメータとして渡すことができます。次のコードを参照してください。これは私の現在のプロジェクトの実例です。

利点は次のとおりです。この方法は、DateTime 形式の問題とカルチャの非互換性を回避するのに役立ちます。

    /// <summary>
    /// Get Arrivals Report Seven Day Forecast
    /// </summary>
    /// <param name="day"></param>
    /// <param name="month"></param>
    /// <param name="year"></param>
    /// <returns></returns>
    [HttpGet("arrivalreportsevendayforecast/{day:int}/{month:int}/{year:int}")]
    public async Task<ActionResult<List<ArrivalsReportSevenDayForecastModel>>> GetArrivalsReportSevenDayForecast(int day, int month, int year)
    {
        DateTime selectedDate = new DateTime(year, month, day);
        IList<ArrivalsReportSevenDayForecastModel> arrivingStudents = await _applicationService.Value.GetArrivalsReportSevenDayForecast(selectedDate);
        return Ok(arrivingStudents);
    }

フロントエンドも見たい場合は、以下のコードを自由に読んでください。残念ながら、それは Angular で書かれています。これは、通常、Angular GET リクエストでクエリ パラメータとして DateTime を渡す方法です。

public getArrivalsReportSevenDayForecast(selectedDate1 : Date): Observable<ArrivalsReportSevenDayForecastModel[]> {
const params = new HttpParams();
const day = selectedDate1.getDate();
const month = selectedDate1.getMonth() + 1
const year = selectedDate1.getFullYear();

const data = this.svcHttp.get<ArrivalsReportSevenDayForecastModel[]>(this.routePrefix +
  `/arrivalreportsevendayforecast/${day}/${month}/${year}`, { params: params }).pipe(
  map<ArrivalsReportSevenDayForecastModel[], ArrivalsReportSevenDayForecastModel[]>(arrivingList => {
    // do mapping here if needed       
    return arrivingList;
  }),
  catchError((err) => this.svcError.handleError(err)));

return data;
}
于 2020-05-12T01:39:27.667 に答える