问题
I'm trying to understand how to use WCF Data Services (based on EF 4.1) to create a restful web service that will persist entities passed as JSON objects.
I've been able to create a method that can accept a GET request with a set of primitive data types as arguments. I don't like that solution, I would prefer to send a POST request with a JSON object in the http request body.
I've found that I can't get the framework to serialize the json into an object for me, but i would be fine with doing it manually.
My problem is that I can't seem to read the body of the POST request - the body should be the JSON payload.
Here's a rough crack at it below. I've tried a few different iterations of this and can't seem to get the raw JSON out of the request body.
Any thoughts? A better way to do this? I just want to POST some JSON data and process it.
[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
}
My DataService is an Entity Framework DataService that extends
System.Data.Services.DataService<T>
If I try adding non-primitive values as parameters to the method, i see the following exception in the trace log:
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.
回答1:
Add parameters to your method. You'll also want some additional attributes on your WebInvoke.
Here's an example (from memory so it might be a little off)
[WebInvoke(BodyStyle = WebMessageBodyStyle.Wrapped, RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json, UriTemplate = "modifyMyPerson")]
public void Modify(Person person) {
...
}
With person class something like this:
[DataContract]
public class Person {
[DataMember(Order = 0)]
public string FirstName { get; set; }
}
And json sent like this
var person = {FirstName: "Anthony"};
var jsonString = JSON.stringify({person: person});
// Then send this string in post using whatever, I personally use jQuery
EDIT: This is using "wrapped" approach. Without wrapped approach you would take out the BodyStyle = ...
and to stringify the JSON you would just do JSON.stringify(person)
. I just usually use the wrapped methodology in case I ever need to add additional parameters.
EDIT For full code sample
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)
{
// ...
}
}
}
And add this to Web.config
<system.serviceModel>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" />
</system.serviceModel>
来源:https://stackoverflow.com/questions/6917380/how-to-accept-json-in-a-wcf-dataservice