[英]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.