使用单一OperationContract方法支持WCF XML和JSON?
我花了好几天的时间努力满足以下要求。我希望我的WCFAPI使用单个方法处理XML和JSON请求/响应。我还知道.NET4支持自动格式选择,但它的工作方式与我希望的XML和JSON结构不同。以下是我的结构: JSON: XML: 以下是数据合同:使用单一OperationContract方法支持WCF XML和JSON?,wcf,Wcf,我花了好几天的时间努力满足以下要求。我希望我的WCFAPI使用单个方法处理XML和JSON请求/响应。我还知道.NET4支持自动格式选择,但它的工作方式与我希望的XML和JSON结构不同。以下是我的结构: JSON: XML: 以下是数据合同: [DataContract] public class Test: ITest { responsePushNotify = new ResponsePushNotify(); ResponsePushNotify
[DataContract]
public class Test: ITest
{
responsePushNotify = new ResponsePushNotify();
ResponsePushNotify PushNotify(RequestPushNotifiy pushnotify)
{
if (Content-Type == "application/json; charset=utf-8")
{
OperationContext.Current.OutgoingMessageProperties.Add(WebBodyFormatMessageProperty.Name, new WebBodyFormatMessageProperty(WebContentFormat.Json));
}
responsePushNotify.id = "1";
responsePushNotify.value = "Hello World";
return responsePushNotify ;
}
以下是建议的代码:
public class MyWebHttpBehavior : WebHttpBehavior
{
protected override IDispatchMessageFormatter GetReplyDispatchFormatter(OperationDescription operationDescription, ServiceEndpoint endpoint)
{
WebGetAttribute webGet = operationDescription.Behaviors.Find<WebGetAttribute>();
IDispatchMessageFormatter json = null, xml = null;
WebMessageFormat originalFormat = webGet.ResponseFormat;
webGet.ResponseFormat = WebMessageFormat.Json;
json = base.GetReplyDispatchFormatter(operationDescription, endpoint);
webGet.ResponseFormat = WebMessageFormat.Xml;
xml = base.GetReplyDispatchFormatter(operationDescription, endpoint);
webGet.ResponseFormat = originalFormat;
return new MyReplyDispatchMessageFormatter(json, xml);
}
}
public class MyReplyDispatchMessageFormatter : IDispatchMessageFormatter
{
IDispatchMessageFormatter jsonFormatter;
IDispatchMessageFormatter xmlFormatter;
public MyReplyDispatchMessageFormatter(IDispatchMessageFormatter jsonFormatter, IDispatchMessageFormatter xmlFormatter)
{
this.jsonFormatter = jsonFormatter;
this.xmlFormatter = xmlFormatter;
}
public void DeserializeRequest(Message message, object[] parameters)
{
throw new NotSupportedException("Used for replies only");
}
public Message SerializeReply(MessageVersion messageVersion, object[] parameters, object result)
{
IDispatchMessageFormatter formatter = this.xmlFormatter;
if (OperationContext.Current.OutgoingMessageProperties.ContainsKey(WebBodyFormatMessageProperty.Name))
{
WebBodyFormatMessageProperty webBody = (WebBodyFormatMessageProperty)OperationContext.Current.OutgoingMessageProperties[WebBodyFormatMessageProperty.Name];
if (webBody != null && webBody.Format == WebContentFormat.Json)
{
formatter = this.jsonFormatter;
}
}
return formatter.SerializeReply(messageVersion, parameters, result);
}
}
这是我的网络配置:
<?xml version="1.0"?>
<configuration>
<system.serviceModel>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true"/>
<services>
<service behaviorConfiguration="CustomBehavior" name="Service.Test">
<endpoint address="" behaviorConfiguration="web" binding="webHttpBinding" contract="Services.ITest" bindingConfiguration="general"/>
</service>
</services>
<bindings>
<webHttpBinding>
<binding name="general" closeTimeout="00:10:00" openTimeout="00:10:00" sendTimeout="00:10:00"
receiveTimeout="00:10:00" maxReceivedMessageSize="2147483647" maxBufferPoolSize="4194304"
maxBufferSize="2147483647" />
</webHttpBinding>
</bindings>
<behaviors>
<endpointBehaviors>
<behavior name="web">
<webHttp automaticFormatSelectionEnabled="true" />
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="CustomBehavior">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
现在我的问题是,如何在代码中定义自定义行为并将其添加到webconfig?我需要做哪些更改?另外,如果我要设置BodyStyle=WebMessageBodyStyle.Wrapped,我该怎么做?在哪里做?我看到这个问题很久以前就发布了,但可能对某些人有用。我在overcoder.net上找到了解决方案。您只需为所需的输出格式生成相应的字符串,并为结果类型使用流
[OperationContract]
[WebGet(UriTemplate = "test?format={format}")]
System.IO.Stream test(string format);
您可能需要编写自己的customdispatcher。参考下面的链接:太棒了,拉杰什:但是我需要设置WebMessageBodyStyle.Wrapped。拉杰什:我已经完成了你在帖子中提到的工作,并添加了如下完全相同的类:公共类MyWebHttpBehavior:WebHttpBehavior公共类MyReplyDispatchMessageFormatter:IDispatchMessageFormatter公共无效反序列化请求消息,object[]参数public Message SerializeReplyMessageVersion messageVersion,object[]参数,object resultSorry这不允许我一次发布所有代码。下面是我的操作合同:[OperationContract][WebInvokeMethod=POST,UriTemplate=Push]响应PushRequest pushnotifi;这是我的数据约定:Response PushRequest pushnotifi{if requestHeader.ContentType==application/json;charset=utf-8{OperationContext.Current.OutgoingMessageProperties.AddWebBodyFormatMessageProperty.Name,new WebBodyFormatMessageProperty yWebContentFormat.json;}返回响应;}@carlosfigueira:我不允许在这里发布代码,因为它太长,而且非常令人沮丧,除非我回答我自己的问题。有什么办法可以联系你吗?电子邮件什么的?因为这里有很多东西要放,而且我是新来的。
public class MyWebHttpBehavior : WebHttpBehavior
{
protected override IDispatchMessageFormatter GetReplyDispatchFormatter(OperationDescription operationDescription, ServiceEndpoint endpoint)
{
WebGetAttribute webGet = operationDescription.Behaviors.Find<WebGetAttribute>();
IDispatchMessageFormatter json = null, xml = null;
WebMessageFormat originalFormat = webGet.ResponseFormat;
webGet.ResponseFormat = WebMessageFormat.Json;
json = base.GetReplyDispatchFormatter(operationDescription, endpoint);
webGet.ResponseFormat = WebMessageFormat.Xml;
xml = base.GetReplyDispatchFormatter(operationDescription, endpoint);
webGet.ResponseFormat = originalFormat;
return new MyReplyDispatchMessageFormatter(json, xml);
}
}
public class MyReplyDispatchMessageFormatter : IDispatchMessageFormatter
{
IDispatchMessageFormatter jsonFormatter;
IDispatchMessageFormatter xmlFormatter;
public MyReplyDispatchMessageFormatter(IDispatchMessageFormatter jsonFormatter, IDispatchMessageFormatter xmlFormatter)
{
this.jsonFormatter = jsonFormatter;
this.xmlFormatter = xmlFormatter;
}
public void DeserializeRequest(Message message, object[] parameters)
{
throw new NotSupportedException("Used for replies only");
}
public Message SerializeReply(MessageVersion messageVersion, object[] parameters, object result)
{
IDispatchMessageFormatter formatter = this.xmlFormatter;
if (OperationContext.Current.OutgoingMessageProperties.ContainsKey(WebBodyFormatMessageProperty.Name))
{
WebBodyFormatMessageProperty webBody = (WebBodyFormatMessageProperty)OperationContext.Current.OutgoingMessageProperties[WebBodyFormatMessageProperty.Name];
if (webBody != null && webBody.Format == WebContentFormat.Json)
{
formatter = this.jsonFormatter;
}
}
return formatter.SerializeReply(messageVersion, parameters, result);
}
}
<?xml version="1.0"?>
<configuration>
<system.serviceModel>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true"/>
<services>
<service behaviorConfiguration="CustomBehavior" name="Service.Test">
<endpoint address="" behaviorConfiguration="web" binding="webHttpBinding" contract="Services.ITest" bindingConfiguration="general"/>
</service>
</services>
<bindings>
<webHttpBinding>
<binding name="general" closeTimeout="00:10:00" openTimeout="00:10:00" sendTimeout="00:10:00"
receiveTimeout="00:10:00" maxReceivedMessageSize="2147483647" maxBufferPoolSize="4194304"
maxBufferSize="2147483647" />
</webHttpBinding>
</bindings>
<behaviors>
<endpointBehaviors>
<behavior name="web">
<webHttp automaticFormatSelectionEnabled="true" />
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="CustomBehavior">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
[OperationContract]
[WebGet(UriTemplate = "test?format={format}")]
System.IO.Stream test(string format);
public System.IO.Stream test(string format)
{
ArrayList ar = new ArrayList() { 1, 2, 3 };
if (format == "text")
result = String.Join(",", ar.ToArray());
if (format == "xml")
{
result = @"<soapenv:Envelope>
<soapenv:Header/>
<soapenv:Body>
<result>";
foreach (int i in ar)
result += String.Format("\r\n <item>{0}</item>", i);
result += @"
</result>
</soapenv:Body>
</soapenv:Envelope>";
}
if (format == "json")
result = JsonConvert.SerializeObject(ar, Newtonsoft.Json.Formatting.Indented);
OutgoingWebResponseContext context = WebOperationContext.Current.OutgoingResponse;
context.ContentType = "text/plain";
return new System.IO.MemoryStream(ASCIIEncoding.Default.GetBytes(result));
}