2013-05-30 24 views
22

私はこのURLAsp.net WEBAPIは現地時間にUTCの時刻文字列をデシリアライズ

http://example.com/api/record/getall?startdate=1994-11-05T17:15:30Z

を持っており、これは私が直面した問題は、たstartDateが非直列化された文字列を受け取ったことである

[ActionName("GetAll")] 
public object GetAll(DateTime startDate) 
    { 
    ... 
    } 

エンドポイントにWEBAPI現地時間として、 "11/5/1994 9:15:30 AM"の代わりに、私が欲しいものが "11/5/1994 5:15:30"となっています。

私はVS2012 update2、最新のJson.net nugetパッケージを使用しています。しかし、別のコンソールアプリケーションでテストするためにjson.netを使用すると、同じ文字列 "1994-11-05T17:15:30Z"は正しく "11/5/1994 5:15:30にデシリアライズできますPM "となります。

誰でも何が間違っているのか分かりますか?

+0

デシリアライズされた日付からUTC時間を取得できませんか? –

+0

解決策を見つけたhttp://stackoverflow.com/questions/12246254/asp-net-web-api-modelbinders –

答えて

24

あなたの質問にはすでにfound a solutionがありますが、私はそれが期待どおりに動作しなかった理由を説明するのに狙いを定めると思いました。

WebApiは、コンテンツタイプのネゴシエーションを使用して、データの読み取り時にどのパーサーを使用するかを決定します。これは、決定を行う要求のヘッダContent-Typeを調べることを意味します。 Content-Typeヘッダーがapplication/jsonに設定されている場合は、Json.Netを使用してコンテンツを解析し、メソッドにフィードします。

ここで作成しているようなHTTP GET要求には、コンテンツタイプが設定されていません。この場合の「コンテンツ」は実際にはURLからのクエリ文字列です。 WebApiはここでJSONデータを見つけることを期待していないので、JSONパーサを使用してそれを理解しようとはしません。たとえそれがあったとしても、GetAllメソッドに渡す文字列は有効なJSONですらありません。

ここで、POSTリクエストを受け入れるメソッドを変更し、コンテンツタイプヘッダーをapplication/jsonに設定し、その日付をJSON文字列として渡した場合は、これを有効にする必要があります。 WebApiはそれを解析するためにJson.Netを使用し、期待どおりに動作します。

[HttpPost] 
public object GetAll([FromBody]DateTime startDate) 
{ 
    try 
    { 
     return new 
     { 
      StartDate = startDate.ToString("yyyy-MM-dd HH:mm:ss"), 
      StartDateKind = startDate.Kind.ToString(), 
     }; 
    } 
    catch (Exception ex) 
    { 
     return ex.Message; 
    } 
} 

そして、あなたはこのような要求(POSTに注意)製:例えば

、あなたの方法は、このように見えたと言う

POST http://localhost:57524/api/values/GetAll HTTP/1.1 
Content-Type: application/json 
Content-Length: 22 
Host: localhost:57524 

"1994-11-05T17:15:30Z" 

応答は次のようになります。

HTTP/1.1 200 OK 
Cache-Control: no-cache 
Pragma: no-cache 
Content-Type: application/json; charset=utf-8 
Expires: -1 
Server: Microsoft-IIS/8.0 
X-AspNet-Version: 4.0.30319 
X-Powered-By: ASP.NET 
Date: Fri, 31 May 2013 01:25:48 GMT 
Content-Length: 57 

{"StartDate":"1994-11-05 17:15:30","StartDateKind":"Utc"} 

ご覧のとおり、このシナリオでは、UTCの日付が正しく認識されます。

+0

私は本当にありがとうございました。 +1し、あなたを答えとしてマークしました。 –

+0

ありがとう、私はあなたが役に立つ説明を見つけてうれしいです。 –

+0

残念ながら、これは[FromUri]属性がリクエストパラメータに添付されたGETリクエストでは機能しません。それを働かせる方法がわからない。 – SamSerious

3

あなたがAsp WEBAPIがあなたのGET要求のURIパラメータを解析する方法を変更したい場合は、カスタムIModelBinderこのように記述することができます。

public class UtcDateTimeModelBinder : IModelBinder 
{ 
    public bool BindModel(HttpActionContext actionContext, ModelBindingContext bindingContext) 
    { 
     var stringValue = bindingContext.ValueProvider.GetValue(bindingContext.ModelName)?.RawValue as string; 
     DateTime parsedDate; 
     if (!DateTime.TryParse(stringValue, null, DateTimeStyles.AdjustToUniversal, out parsedDate)) 
     { 
      return false; 
     } 

     bindingContext.Model = parsedDate; 
     return true; 
    } 
} 

をし、既定のバインダ上書き:

GlobalConfiguration.Configure(configuration => configuration.BindParameter(typeof(DateTime), new UtcDateTimeModelBinder());); 

Parameter Binding in ASP.NET Web API

+0

あなたの日付がISO形式 "1994-11-05T17:15:30Z"で既にフォーマットされている場合。 DateTime.TryParseをDateTime.TryParse(stringValue、null、DateTimeStyles.RoundtripKind、out parsedDate)として変更する必要があります。 –

関連する問題