【问题标题】:How can I send a DataContract object as parameter for a WCF RESTFUL webservice?如何发送 DataContract 对象作为 WCF RESTFUL Web 服务的参数?
【发布时间】:2013-09-10 04:56:26
【问题描述】:

我正在开发一个 WCF resful 服务,它基本上会被一些移动应用程序使用。 通过 POST 我试图发送一个 DataContract 对象 [实际上我必须发送一个对象列表] 和另一个单个 id 作为字符串。我的问题是是否可以定义我的函数来接受 DataContract 对象和单个字符串?

以下是我的代码: 接口声明:

[ServiceContract]
    public interface IService1
    {

        [OperationContract]
        [WebInvoke(Method = "POST", ResponseFormat = WebMessageFormat.Json, UriTemplate = "GetDataUsingDataContract/{id}")]
        CompositeType GetDataUsingDataContract(string id, CompositeType composite );


    }

    [DataContract]
    public class CompositeType
    {
        bool boolValue = true;
        string stringValue = "Hello ";

        [DataMember]
        public bool BoolValue
        {
            get { return boolValue; }
            set { boolValue = value; }
        }

        [DataMember]
        public string StringValue
        {
            get { return stringValue; }
            set { stringValue = value; }
        }
    }

函数的实际定义:

public CompositeType GetDataUsingDataContract(string id, CompositeType composite )
        {

            if (composite == null)
            {
                throw new ArgumentNullException("composite");
            }
            if (composite .BoolValue)
            {
                composite .StringValue += "- Suffix and the id is"+id;
            }
            return report;
        }

我试图从 Fiddler 发送的 json 对象是

{"BoolValue":true,"StringValue":"sdfsdfsf"}

以上是我正在测试服务的提琴手的快照。 经过几次谷歌搜索后,我得到了以下链接,其中客户端实际使用 Web 服务引用来获取 DataContract 类型并在作为请求正文发送之前序列化为 json。但是为什么我的 Fiddler 测试没有成功?! http://dotnetmentors.com/wcf/wcf-rest-service-to-get-or-post-json-data-and-retrieve-json-data-with-datacontract.aspx

谁能给点建议?

web.config 如下:

<?xml version="1.0"?>
<configuration>

  <system.web>
    <compilation debug="true" targetFramework="4.0" />
  </system.web>
  <system.serviceModel>
    <services>
      <service name="JSONWebService.Service1" behaviorConfiguration="JSONWebService.Service1Behavior">
        <endpoint address="../Service1.svc"
            binding="webHttpBinding"
            contract="JSONWebService.IService1"
            behaviorConfiguration="webBehaviour" />
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior name="JSONWebService.Service1Behavior">

          <!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
          <serviceMetadata httpGetEnabled="true"/>
          <!-- To receive exception details in faults for debugging purposes, set the value below to true.  Set to false before deployment to avoid disclosing exception information -->
          <serviceDebug includeExceptionDetailInFaults="true"/>
        </behavior>
      </serviceBehaviors>
      <endpointBehaviors>
        <behavior name="webBehaviour">
          <webHttp/>
        </behavior>
      </endpointBehaviors>
    </behaviors>
    <serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
  </system.serviceModel>
 <system.webServer>
    <modules runAllManagedModulesForAllRequests="true"/>
  </system.webServer>

</configuration>

【问题讨论】:

    标签: json wcf rest wcf-rest


    【解决方案1】:

    您需要做几件事才能使此方案发挥作用。

    首先,在服务契约中,需要将WebInvoke属性的BodyStyle参数设置为Wrapped标记具有多个参数的方法strong> 如本例所示(改编自您在http://dotnetmentors.com/wcf/wcf-rest-service-to-get-or-post-json-data-and-retrieve-json-data-with-datacontract.aspx 链接到的示例):

    [OperationContract]
    [WebInvoke(UriTemplate = "/PlaceOrder",
        RequestFormat = WebMessageFormat.Json,
        ResponseFormat = WebMessageFormat.Json, Method = "POST",
        BodyStyle = WebMessageBodyStyle.Wrapped)]
    bool PlaceOrder(string id, OrderContract order);
    

    使用此属性参数,您必须将多个 Web 方法参数包装到客户端中的单个字符串中。以下示例显示了在 C# 中执行此操作的一种方法:

      var requestdata = new
      {
        id = order.OrderID,
        order = order
      };
      string data2 = JsonConvert.SerializeObject(requestdata);
    

    请注意,匿名方法中的字段名称与您的 Web 方法中的参数名称相匹配。

    作为参考,生成的 JSON 如下所示,您可以在 JSON 字符串中看到 idorder 对象:

    {"id":"10560","order":{"OrderID":"10560","OrderDate":"06/09/2013 12:29:04","ShippedDate":"16/09/2013 12:29:04","ShipCountry":"Uganda","OrderTotal":"781"}}

    您应该能够使用您的示例在 Fiddler 中测试这种格式的 JSON。


    扩展答案以处理其他数据类型

    使用包含 boolDateTime 属性的 DataContract

    [DataContract]
    public class OrderContract
    {
      [DataMember]
      public string OrderID { get; set; }
    
      [DataMember]
      public string OrderDate { get; set; }
    
      [DataMember]
      public string ShippedDate { get; set; }
    
      [DataMember]
      public string ShipCountry { get; set; }
    
      [DataMember]
      public string OrderTotal { get; set; }
    
      [DataMember]
      public bool Shipped { get; set; }
    
      [DataMember]
      public DateTime DeliveredDate { get; set; }
    }
    

    这里的问题是处理 DateTime 并确保 JSON 采用 WCF RESTful 服务可以反序列化的格式。为了让它工作,我在客户端上使用了这段代码:

    OrderContract order = new OrderContract
    {
      OrderID = "10560",
      OrderDate = DateTime.Now.ToString(),
      ShippedDate = DateTime.Now.AddDays(10).ToString(),
      ShipCountry = "India",
      OrderTotal = "781",
      Shipped = true,
      DeliveredDate = DateTime.Now
    };
    
    DataContractJsonSerializer ser =
            new DataContractJsonSerializer(typeof(OrderContract));
    MemoryStream mem = new MemoryStream();
    ser.WriteObject(mem, order);
    string data =
        Encoding.UTF8.GetString(mem.ToArray(), 0, (int)mem.Length);
    
    var requestdata = new
    {
      id = order.OrderID,
      order = order
    };
    JsonSerializerSettings microsoftDateFormatSettings = new JsonSerializerSettings
    {
      DateFormatHandling = DateFormatHandling.MicrosoftDateFormat
    };
    string data2 = JsonConvert.SerializeObject(requestdata, microsoftDateFormatSettings);
    WebClient webClient = new WebClient();
    webClient.Headers["Content-type"] = "application/json";
    webClient.Encoding = Encoding.UTF8;
    webClient.UploadString("http://localhost:61966/OrderService.svc/PlaceOrder", "POST", data2);
    

    注意 JSON 序列化器设置 - 这会产生以下 JSON:

    {"id":"10560","order":{"OrderID":"10560","OrderDate":"10/09/2013 16:15:30","ShippedDate":"20/09/2013 16:15:30","ShipCountry":"India","OrderTotal":"781","Shipped":true,"DeliveredDate":"\/Date(1378826130655+0100)\/"}}
    

    【讨论】:

    • 嗨@Dominic 发送多个参数是我的次要问题 - 我首先关心的是通过 POST 将 DataContract 作为 json 发送并自动反序列化到我的 DataContract。仍然没有运气!
    • 当我将 DataContract 替换为 Stream 作为 web 方法的参数时 - 它有效!添加了 web.config,因为我错过了那里的任何内容。
    • 嗨@mar​​ifrahman。您的 ServiceContract 中是否同时具有 RequestFormat 和 ResponseFormat 参数?我在您发布的代码中看不到“RequestFormat = WebMessageFormat.Json”...
    • 只需设置它,它似乎只适用于 int 和 string 类型的 DataMembers 但是当我尝试使用 bool 或 datetime 类型的 DataMembers 时,我得到了同样的错误请求错误;但是非常感谢,请就 DataContracts 中的数据成员提出建议。
    • 嗨@mar​​ifrahman - 我刚刚扩展了处理 bool 和 DateTime 数据类型的答案。
    猜你喜欢
    • 2012-07-20
    • 1970-01-01
    • 2016-12-22
    • 1970-01-01
    • 2012-01-12
    • 1970-01-01
    • 1970-01-01
    • 2023-03-05
    • 1970-01-01
    相关资源
    最近更新 更多