2011-08-02 11 views
4

私は、JSONオブジェクトとして渡されたエンティティを永続化させる快適なWeb​​サービスを作成するために、EF 4.1に基づいてWCF Data Servicesを使用する方法を理解しようとしています。WCF DataServiceでJSONを受け入れる方法は?

私は、プリミティブデータ型のセットを引数としてGETリクエストを受け入れることができるメソッドを作成できました。私はその解決策が気に入らないので、httpリクエスト本体にJSONオブジェクトを含むPOSTリクエストを送信する方が好きです。

私はjsonをオブジェクトにシリアル化するためのフレームワークを手に入れることはできませんが、手作業でやっても問題ありません。

私の問題は、POST要求の本文を読むことができないことです。本文はJSONペイロードでなければなりません。

ここには、下の大きな亀裂があります。私はこれのいくつかの異なる反復を試してきましたし、要求本体から未処理のJSONを取得できないようです。

どのような考えですか?これを行う良い方法は? JSONデータをPOSTして処理したいだけです。

[WebInvoke(Method = "POST")] 
    public void SaveMyObj() 
    { 
     StreamReader r = new StreamReader(HttpContext.Current.Request.InputStream); 
     string jsonBody = r.ReadToEnd(); // jsonBody is empty!! 

     JavaScriptSerializer jss = new JavaScriptSerializer(); 
     MyObj o = (MyObj)jss.Deserialize(jsonBody, typeof(MyObj)); 

     // Now do validation, business logic, and persist my object 
    } 

私のDataServiceは

System.Data.Services.DataService<T> 

私はメソッドへのパラメータとして非プリミティブな値を追加しようとした場合

を拡張Entity FrameworkのDataServiceのですが、私はトレースログに以下の例外を参照してください。

System.InvalidOperationException, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 
'Void SaveMyObj(MyNamespace.MyObj)' has a parameter 'MyNamespace.MyObj o' of type 'MyNamespace.MyObj' which is not supported for service operations. Only primitive types are supported as parameters. 

答えて

8

メソッドにパラメータを追加します。また、WebInvokeにいくつかの追加属性が必要です。 (それは少しオフであるかもしれないので、メモリから)ここで

は一例です

[WebInvoke(BodyStyle = WebMessageBodyStyle.Wrapped, RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json, UriTemplate = "modifyMyPerson")] 
public void Modify(Person person) { 
    ... 
} 

このような人のクラス何かを:この

var person = {FirstName: "Anthony"}; 
var jsonString = JSON.stringify({person: person}); 
// Then send this string in post using whatever, I personally use jQuery 
のように送られた

[DataContract] 
public class Person { 

[DataMember(Order = 0)] 
public string FirstName { get; set; } 

} 

とJSON

編集:これは "ラップされた"アプローチを使用しています。ラップされたアプローチがなければ、BodyStyle = ...を取り出し、JSONをストリング化するだけです。JSON.stringify(person)。追加パラメータを追加する必要がある場合に備えて、通常はラップされた方法を使用します。完全なコードサンプル

Global.asax

using System; 
using System.ServiceModel.Activation; 
using System.Web; 
using System.Web.Routing; 

namespace MyNamespace 
{ 
    public class Global : HttpApplication 
    { 
     protected void Application_Start(object sender, EventArgs e) 
     { 
      RouteTable.Routes.Add(new ServiceRoute("myservice", new WebServiceHostFactory(), typeof(MyService))); 
     } 
    } 
} 

Service.cs

using System; 
using System.ServiceModel; 
using System.ServiceModel.Activation; 
using System.ServiceModel.Web; 

namespace MyNamespace 
{ 
    [ServiceContract] 
    [ServiceBehavior(MaxItemsInObjectGraph = int.MaxValue)] 
    [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)] 
    public class MyService 
    { 
     [OperationContract] 
     [WebInvoke(UriTemplate = "addObject", ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.WrappedRequest)] 
     public void AddObject(MyObject myObject) 
     { 
      // ... 
     } 

     [OperationContract] 
     [WebInvoke(UriTemplate = "updateObject", ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.WrappedRequest)] 
     public void UpdateObject(MyObject myObject) 
     { 
      // ... 
     } 

     [OperationContract] 
     [WebInvoke(UriTemplate = "deleteObject", ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.WrappedRequest)] 
     public void DeleteObject(Guid myObjectId) 
     { 
      // ... 
     } 
    } 
} 

そしてWeb.config

<system.serviceModel> 
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true" /> 
    </system.serviceModel> 
にこれを追加するために

EDIT

+0

私のサービスでは、非プリミティブ型をパラメータとして使用できないようです。私はEntity Framework DataService(System.Data.Services.DataServiceを拡張しています)を使用しています。引数に非プリミティブがあると、例外が発生します: 'code' ...'MyNamespace.MyObj'型のパラメータ 'MyNamespace.MyObj bv'があり、サービス操作ではサポートされていません。プリミティブ型だけがパラメータとしてサポートされています。「コード」 – codemonkey

+1

これは残念な欠点です...もし私があなただったら、他のメリットが得られない限り、 'DataService 'を削除します。私は自分の投稿を編集して、私が使っているものの完全なコードサンプルを私のためにうまく機能させるようにします。 –

+0

良い提案ですが、それがDataService の制限であるかどうかは不明でした。私が理解しているように、私はそのDataServiceで自動的にREST CRUD操作を取得します(GET reqのみ)。この場合は、永続化する前にバリデーションやビジネスロジックを実行する必要があるため、自動CRUDは必要ありません。私はあなたのアプローチを試し、後でここで更新します。 – codemonkey

関連する問題