Is it possible to override the default WCF DataContractSerializer behaviour when Serialize/DeSerialize entities and use JSON.NET instead?
在Serialize / DeSerialize实体并使用JSON.NET时,是否可以覆盖默认的WCF DataContractSerializer行为?
I have the following service contract for handling the City entity. For design reasons the City entity has IsReference=true, and therefore the default DataContractSerializer raise errors.
我有以下服务合同来处理City实体。出于设计原因,City实体具有IsReference = true,因此默认的DataContractSerializer会引发错误。
For the "GET" methods I can handle the situation with JsonConvert.DeserializeObject, but with "PUT,POST,DELETE" methods DataContractSerializer takes precedence and fails complaining for the IsReference entities cannot be serialized.
对于“GET”方法,我可以使用JsonConvert.DeserializeObject来处理这种情况,但是使用“PUT,POST,DELETE”方法DataContractSerializer优先,并且失败抱怨IsReference实体无法序列化。
I have find this Post to implement IOperationBehavior and provide my own Serializer but I do not know how to integrate Json.NET with this. and I believe there should be more straight forward approach for this.
我发现这个Post实现IOperationBehavior并提供我自己的Serializer但我不知道如何将Json.NET与此集成。我相信应该有更直接的方法。
I’d appreciate any help or guidance regarding this scenario, or advice to other approaches.
我很感激有关此方案的任何帮助或指导,或对其他方法的建议。
[ServiceContract]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
public class CityService
{
[Description("Get all Cities")]
[WebGet(UriTemplate = "")]
public Message Cities()
{
}
[Description("Allows the details of a single City to be updated.")]
[WebInvoke(UriTemplate = "{code}", Method = "PUT")]
public Message UpdateCity(string code, City city)
{
}
}
Many thanks
非常感谢
Hossam
霍山
3 个解决方案
#1
21
The usage of Extending Encoders and Serializers (see http://msdn.microsoft.com/en-us/library/ms733092.aspx) or other methods of Extending WCF like usage of DataContractSerializerOperationBehavior
is very interesting, but for your special problem there are easier solution ways.
使用扩展编码器和序列化器(请参阅http://msdn.microsoft.com/en-us/library/ms733092.aspx)或扩展WCF的其他方法(如使用DataContractSerializerOperationBehavior)非常有趣,但对于您的特殊问题,有更容易解决方法。
If you already use Message
type to return the results an use WCF4 you can do something like following:
如果您已使用消息类型返回结果,请使用WCF4,您可以执行以下操作:
public Message UpdateCity(string code, City city)
{
MyResponseDataClass message = CreateMyResponse();
// use JSON.NET to serialize the response data
string myResponseBody = JsonConvert.Serialize(message);
return WebOperationContext.Current.CreateTextResponse (myResponseBody,
"application/json; charset=utf-8",
Encoding.UTF8);
}
In case of errors (like HttpStatusCode.Unauthorized
or HttpStatusCode.Conflict
) or in other situations when you need to set a HTTP status code (like HttpStatusCode.Created
) you can continue to use WebOperationContext.Current.OutgoingResponse.StatusCode
.
如果出现错误(如HttpStatusCode.Unauthorized或HttpStatusCode.Conflict),或者在需要设置HTTP状态代码(如HttpStatusCode.Created)的其他情况下,您可以继续使用WebOperationContext.Current.OutgoingResponse.StatusCode。
As an alternative you can also return a Stream
(see http://blogs.msdn.com/b/carlosfigueira/archive/2008/04/17/wcf-raw-programming-model-web.aspx and http://msdn.microsoft.com/en-us/library/ms732038.aspx) instead of Message
to return any data without additional default processing by Microsoft JSON serializer. In case of WCF4 you can use CreateStreamResponse
(see http://msdn.microsoft.com/en-us/library/dd782273.aspx) instead of CreateTextResponse
. Don't forget to set stream position to 0 after writing in the stream if you will use this technique to produce the response.
作为替代方案,您还可以返回一个Stream(请参阅http://blogs.msdn.com/b/carlosfigueira/archive/2008/04/17/wcf-raw-programming-model-web.aspx和http:// msdn .microsoft.com / zh-cn / library / ms732038.aspx)而不是Message,无需Microsoft JSON序列化程序的其他默认处理即可返回任何数据。对于WCF4,您可以使用CreateStreamResponse(请参阅http://msdn.microsoft.com/en-us/library/dd782273.aspx)而不是CreateTextResponse。如果您将使用此技术生成响应,请不要忘记在流中写入后将流位置设置为0。
#2
1
Is there some reason why you want to use the Json.NET library specifically. If you want to return JSON, why not just use the ResponseFormat property from the WebGet and WebInvoke attributes?
您是否有理由特别要使用Json.NET库?如果要返回JSON,为什么不直接使用WebGet和WebInvoke属性中的ResponseFormat属性?
[WebGet(UriTemplate = "", ResponseFormat = WebMessageFormat.Json)]
That should for most cases. What version of WCF are you running? Any reason you're returning a Message type rather than the actual type?
这应该适用于大多数情况。你在运行什么版本的WCF?您是否返回Message类型而不是实际类型?
#3
0
Define it in your service web config on service behaviors:
在服务Web配置中定义服务行为:
<endpointBehaviors>
<behavior name="restfulBehavior">
<webHttp defaultOutgoingResponseFormat="Json" defaultBodyStyle="Wrapped" automaticFormatSelectionEnabled="False" />
<!--<enableWebScript />-->
</behavior>
</endpointBehaviors>
or in your operation contract of your Interface
或者在您的界面的操作合同中
[OperationContract]
[WebInvoke(Method = "GET",
UriTemplate = "/advertisements/{app_id}/{access_token}/{genero}/{age}",
ResponseFormat = WebMessageFormat.Json,
RequestFormat = WebMessageFormat.Json,
BodyStyle = WebMessageBodyStyle.Wrapped)]
#1
21
The usage of Extending Encoders and Serializers (see http://msdn.microsoft.com/en-us/library/ms733092.aspx) or other methods of Extending WCF like usage of DataContractSerializerOperationBehavior
is very interesting, but for your special problem there are easier solution ways.
使用扩展编码器和序列化器(请参阅http://msdn.microsoft.com/en-us/library/ms733092.aspx)或扩展WCF的其他方法(如使用DataContractSerializerOperationBehavior)非常有趣,但对于您的特殊问题,有更容易解决方法。
If you already use Message
type to return the results an use WCF4 you can do something like following:
如果您已使用消息类型返回结果,请使用WCF4,您可以执行以下操作:
public Message UpdateCity(string code, City city)
{
MyResponseDataClass message = CreateMyResponse();
// use JSON.NET to serialize the response data
string myResponseBody = JsonConvert.Serialize(message);
return WebOperationContext.Current.CreateTextResponse (myResponseBody,
"application/json; charset=utf-8",
Encoding.UTF8);
}
In case of errors (like HttpStatusCode.Unauthorized
or HttpStatusCode.Conflict
) or in other situations when you need to set a HTTP status code (like HttpStatusCode.Created
) you can continue to use WebOperationContext.Current.OutgoingResponse.StatusCode
.
如果出现错误(如HttpStatusCode.Unauthorized或HttpStatusCode.Conflict),或者在需要设置HTTP状态代码(如HttpStatusCode.Created)的其他情况下,您可以继续使用WebOperationContext.Current.OutgoingResponse.StatusCode。
As an alternative you can also return a Stream
(see http://blogs.msdn.com/b/carlosfigueira/archive/2008/04/17/wcf-raw-programming-model-web.aspx and http://msdn.microsoft.com/en-us/library/ms732038.aspx) instead of Message
to return any data without additional default processing by Microsoft JSON serializer. In case of WCF4 you can use CreateStreamResponse
(see http://msdn.microsoft.com/en-us/library/dd782273.aspx) instead of CreateTextResponse
. Don't forget to set stream position to 0 after writing in the stream if you will use this technique to produce the response.
作为替代方案,您还可以返回一个Stream(请参阅http://blogs.msdn.com/b/carlosfigueira/archive/2008/04/17/wcf-raw-programming-model-web.aspx和http:// msdn .microsoft.com / zh-cn / library / ms732038.aspx)而不是Message,无需Microsoft JSON序列化程序的其他默认处理即可返回任何数据。对于WCF4,您可以使用CreateStreamResponse(请参阅http://msdn.microsoft.com/en-us/library/dd782273.aspx)而不是CreateTextResponse。如果您将使用此技术生成响应,请不要忘记在流中写入后将流位置设置为0。
#2
1
Is there some reason why you want to use the Json.NET library specifically. If you want to return JSON, why not just use the ResponseFormat property from the WebGet and WebInvoke attributes?
您是否有理由特别要使用Json.NET库?如果要返回JSON,为什么不直接使用WebGet和WebInvoke属性中的ResponseFormat属性?
[WebGet(UriTemplate = "", ResponseFormat = WebMessageFormat.Json)]
That should for most cases. What version of WCF are you running? Any reason you're returning a Message type rather than the actual type?
这应该适用于大多数情况。你在运行什么版本的WCF?您是否返回Message类型而不是实际类型?
#3
0
Define it in your service web config on service behaviors:
在服务Web配置中定义服务行为:
<endpointBehaviors>
<behavior name="restfulBehavior">
<webHttp defaultOutgoingResponseFormat="Json" defaultBodyStyle="Wrapped" automaticFormatSelectionEnabled="False" />
<!--<enableWebScript />-->
</behavior>
</endpointBehaviors>
or in your operation contract of your Interface
或者在您的界面的操作合同中
[OperationContract]
[WebInvoke(Method = "GET",
UriTemplate = "/advertisements/{app_id}/{access_token}/{genero}/{age}",
ResponseFormat = WebMessageFormat.Json,
RequestFormat = WebMessageFormat.Json,
BodyStyle = WebMessageBodyStyle.Wrapped)]