繁体   English   中英

如何在WCF Rest Service中创建JSON以匹配/序列化为DataContract

[英]How to create JSON to match/serialize to DataContract in WCF Rest Service

接口:

namespace SQRT_WCF
    {
    [DataContract]
    public class PlaceOrder
    {
        [DataMember]
        public string claimID { get; set; }
        [DataMember]
        public string rederenceDate { get; set; }
    }
}

调用C#方法:

public SQ_jsonModel.Response placeOrder(PlaceOrder argPlaceOrderJSON)
{
   ...
}

我已将我的web服务附加到工作进程,并跟踪代码。 到目前为止,我尝试过的所有内容,变量argPlaceOrderJSON都为null。

我尝试过至少三种变化:

变化#1

{
         "claimID" : "value",
         "rederenceDate" : "value"
}

变化#2:

{
    "PlaceOrder" : {
         "claimID" : "value",
         "rederenceDate" : "value"
}

变化#3:

{
    "ns0:PlaceOrder" : {
        "@xmlns:ns0" : "SQRT_WCF",
         "claimID" : "value",
        "rederenceDate" : "value"
}

我写了一个快速的C#控制台程序来构建和序列化一个对象,它匹配上面的Variation 1。 所以现在我认为问题不是JSON,而是SOAP-UI和Web服务之间的握手。 我将在旁边写一个C#测试客户端,看看那里发生了什么。

SQRT_WCF.PlaceOrder order = new SQRT_WCF.PlaceOrder();
order.ClaimID = "claim1"; 
string strJson = new JavaScriptSerializer().Serialize(order);

有人在webservice中询问了属性,假设这是他的意思:

public interface ISQRTREST {[OperationContract] void DoWork();

    [OperationContract]
    [WebInvoke(Method="GET",
        ResponseFormat = WebMessageFormat.Json ,
        BodyStyle = WebMessageBodyStyle.Wrapped ,
        UriTemplate ="json/{id}"
        )]
    string JSONData(String id);


    [OperationContract]
    [WebInvoke(Method = "POST",
        ResponseFormat = WebMessageFormat.Json,
        BodyStyle = WebMessageBodyStyle.Wrapped,
        UriTemplate = "placeOrder/"
        )]
    SQ_jsonModel.Response placeOrder(PlaceOrder order);

}

Web.Config中

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

  <system.web>
    <compilation debug="true" targetFramework="4.0" />
  </system.web>
  <system.serviceModel>
    <services>
      <service name="SQRT_WCF.SQRTREST" behaviorConfiguration="ServiceBehaviour">
        <endpoint address="" binding="webHttpBinding" bindingConfiguration="longTimeoutBinding" contract="SQRT_WCF.ISQRTREST" behaviorConfiguration="web">
        </endpoint>
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior name="ServiceBehaviour">
          <!-- 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="false"/>
        </behavior>
      </serviceBehaviors>
      <endpointBehaviors>
        <behavior name="web">
          <webHttp/>
        </behavior>
      </endpointBehaviors>
    </behaviors>
    <bindings>
      <webHttpBinding>
        <binding name="longTimeoutBinding"
        receiveTimeout="00:10:00" sendTimeout="00:10:00">
          <security mode="None"/>
        </binding>
      </webHttpBinding>
    </bindings>
    <serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
  </system.serviceModel>
 <system.webServer>
    <modules runAllManagedModulesForAllRequests="true"/>
  </system.webServer>

</configuration>

更新:似乎更改BodyStyle = WebMessageBodyStyle.Bare使用变体1。

但现在,问题是我需要能够使用WebMessageBodyStyle.Wrapped。

这是它正在生产的现有Web服务。 编写该程序的人早已不复存在,现在B2B / BizTalk团队正在接管该项目。 我们正在使用尚未安装REST的BT2010,我们正在尝试为客户提供相同的界面,因此他们不必更改URL以外的任何内容。

RESTful Web服务正文格式似乎解释得相当好,我即将在C#中使用.wrapped选项尝试Variation 2。

更新2:使用BodyWrapped尝试变体2仍然获得一个null对象:

这是我包装它的方式。 在Update1中使用了什么

string strPostBodyWrapped = "{\"PlaceOrder\" : " + strPostBody + "}";

午饭后会做更多的调试。

更新3:仍然没有运气。 基于上面的StackOverflow引用,看起来包装器应该是“实体”,我尝试了几种方法:

来自SOAP-UI:

{
    "entity" : { 
        "claimID" : "value",
}

我也试过“实体”而不是“实体”,只是确定。

我的DataContract中的所有字段都是字符串,因此应该没有问题序列化日期或数字。

来自C#Client测试程序:

            strPostBody = replaceSingleWithDoubleQuotes("{'ClaimID':'testvalue'}"); 

            string strPostBodyWrapped = replaceSingleWithDoubleQuotes("{'entity': ") + strPostBody + "}";

public static string replaceSingleWithDoubleQuotes(string argText)
    {
        return argText.Replace("'", "\"");
    }

如果我在SOAP_UI中尝试一些不好的东西,像这样:

{
    "entity" : {  xxx 
        "claimID" : "value",
}

然后我意识到实体不是关键词,而是他班级的名字......哎呀。 所以我尝试了“Placeorder”和“placeorder”作为我案例的包装器。

我得到一个很好的错误:

The server encountered an error processing the request. The exception message is 'The formatter threw an exception while trying to deserialize the message: Error in deserializing body of request message for operation 'placeOrderSQRT'. Encountered unexpected character 'x'.'...

所以我不明白为什么在这种情况下解析器失败,但在其他情况下它不会失败,但它也不会设置任何字段值。

如果我尝试无效的字段名称,但语法正确,解析器似乎不会给出任何错误,例如“claimIDxxxxxxxx”:“value”

我想你可能需要对你的对象进行字符串化。

var obj = {
     "claimID" : "value",
     "rederenceDate" : "value"
 }

.......

data: '{ "argPlaceOrderJSON": ' + JSON.stringify(obj) + ' }'

我有一个类似的问题,结果我必须定义我的请求格式和正文。 尝试这个:

[OperationContract]
[WebInvoke(Method = "POST", BodyStyle = WebMessageBodyStyle.WrappedRequest, RequestFormat = WebMessageFormat.Json)]
YourResultType placeOrder(PlaceOrder argPlaceOrderJSON);

答案被埋在这里:

WCF BodyStyle WrappedRequest对传入的JSON参数不起作用?

包装器的名称不是参数类型,而是参数名称。

所以在我的例子中,包装名称是“order”,因为我的parm名称是“order”:

SQ_jsonModel.Response placeOrderSQRT(PlaceOrder order);

以下是SOAP-UI的工作原理:

{
    "order" : {
         "claimID" : "value",
         "rederenceDate" : "value"
}

对我而言,这非常令人震惊; 通常我们可以更改变量名称和参数名称(只是不是类名称),绝对不会影响用户界面。 参考文章显示了如何使用属性“MessageParameter”来设置外部名称,并且仍然允许在需要时更改内部名称。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM