如何在WCF数据服务中接受JSON

本文关键字:JSON 服务 数据 WCF | 更新日期: 2023-09-27 18:04:12

我正在尝试理解如何使用WCF数据服务(基于EF 4.1)来创建一个restful web服务,该服务将持久化作为JSON对象传递的实体。

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

我发现,我不能得到框架序列化json为我的对象,但我会很好与手动做它。

我的问题是我似乎无法读取POST请求的主体-主体应该是JSON有效负载。

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

任何想法吗?有更好的方法吗?我只是想POST一些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
    }

My DataService是一个扩展了

的实体框架数据服务
System.Data.Services.DataService<T>

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

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.

如何在WCF数据服务中接受JSON

为你的方法添加参数。您还需要在WebInvoke上添加一些附加属性。

这里有一个例子(从记忆中,所以它可能有点偏离)

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

与person类类似:

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

json是这样发送的

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

编辑:这是使用"包装"的方法。没有包装的方法,你会拿出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>