web-dev-qa-db-ja.com

日時パラメータを渡す方法は?

UTC日付をWeb APIに渡す方法は?

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

67
Nickolodeon

問題は2つあります。

1.ルートの.

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

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

  • ドットを許可する必要があるルート専用の新しいハンドラーを追加します。必ず追加してくださいbeforeデフォルト。これを行うには、最初にremoveを確認してから、自分の後に追加してください。
  • path="*."属性をpath="*"に変更します。その後、すべてをキャッチします。それ以降、Web APIはドット付きの着信呼び出しを静的リソースとして解釈しなくなることに注意してください! Web APIで静的リソースをホストしている場合、これはお勧めしません!
  • 以下をWeb.configに追加して、すべての要求を無条件に処理します。under <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を取り除きます。 : 's(cfrポイント2)を許可する必要があります。
25
Vincent Sels

私はあなたの痛みを感じます...さらに別の日付時刻形式...まさにあなたが必要なもの!

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

Hanselmanが関連情報をここに提供します。

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

16

product Web 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でGetProductPeriodOrdersメソッドをテストします-作曲者:

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

日時形式:

yyyy-MM-ddTHH:mm:ss

javascriptパスパラメータはmoment.jsを使用します

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

これは解決策であり、可能な解決策のモデルです。クライアントで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時間の拡張メソッドを作成します。 nix DateTimeメソッド

6
Kentonbmax

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

3
Nickolodeon

かつては骨の折れる作業でしたが、今ではtoUTCString()を使用できます。

例:

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

以下をAjaxのポストリクエストに入れます

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

S kの答えの代替として、クエリ文字列で Date.prototype.toISOString() でフォーマットされた日付を渡すことができます。これは標準のISO 8601形式であり、ルートまたはアクションの追加構成なしで.Net Web APIコントローラーで受け入れられます。

例えば.

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