如何在WCF DataService中接受JSON?

cod*_*key 4 c# json wcf-data-services ef4-code-only

我试图了解如何使用WCF数据服务(基于EF 4.1)来创建一个宁静的Web服务,该服务将持久化作为JSON对象传递的实体.

我已经能够创建一个方法,可以接受带有一组原始数据类型作为参数的GET请求.我不喜欢这个解决方案,我更喜欢在http请求体中发送带有JSON对象的POST请求.

我发现我无法让框架将json序列化为一个对象,但是我可以手动完成它.

我的问题是我似乎无法读取POST请求的正文 - 正文应该是JSON有效负载.

下面是一个粗略的裂缝.我已经尝试了几次不同的迭代,似乎无法从请求体中获取原始JSON.

有什么想法吗?更好的方法吗?我只想发布一些JSON数据并进行处理.

    [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
    }
Run Code Online (Sandbox Code Playgroud)

我的DataService是一个扩展的实体框架DataService

System.Data.Services.DataService<T>
Run Code Online (Sandbox Code Playgroud)

如果我尝试将非原始值作为参数添加到方法中,我会在跟踪日志中看到以下异常:

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.
Run Code Online (Sandbox Code Playgroud)

Ant*_*ile 7

向您的方法添加参数.您还需要WebInvoke上的一些其他属性.

这是一个例子(从内存中可能有点偏离)

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

有人类这样的东西:

[DataContract]
public class Person {

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

}
Run Code Online (Sandbox Code Playgroud)

而json这样发了

var person = {FirstName: "Anthony"};
var jsonString = JSON.stringify({person: person});
// Then send this string in post using whatever, I personally use jQuery
Run Code Online (Sandbox Code Playgroud)

编辑:这是使用"包裹"的方法.如果没有包装方法,你可以取出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)));
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

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)
        {
            // ...
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

并添加此 Web.config

  <system.serviceModel>
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true" />
  </system.serviceModel>
Run Code Online (Sandbox Code Playgroud)

  • @codemonkey这实际上是OData标准的限制,而不是WCF数据服务本身.您可以破解WCF数据服务以获取发布数据.在Glenn Gailey的这篇相关博客文章中简要提到了"将数据上传到服务运营":http://blogs.msdn.com/b/writingdata_services/archive/2011/07/05/uploading-data-to-a -service-operation.aspx话虽如此,不推荐这样的hack,因此应该序列化复杂的类型(在博客文章中也提到过). (2认同)