我有一个WCF服务,它返回一个看起来像这样的简单DTO:
[DataContract]
[KnownType(typeof(TimeTriggerCreateResult))]
[KnownType(typeof(ScheduleCreateResult))]
public class TriggerCreateResult
{
[DataMember(Order = 1)] public bool AlreadyExisted;
[DataMember(Order = 2)] public int SchedulerId; // TODO: rename to ScheduleId
[DataMember(Order = 3, EmitDefaultValue = false)] public int TriggerId;
[DataMember(Order = 4)] public ScheduleType ScheduleType;
public NewSchedule Schedule;
}
[DataContract]
public class TimeTriggerCreateResult : TriggerCreateResult
{
public TimeTriggerCreateResult()
{
ScheduleType = ScheduleType.TimeTrigger;
}
public TimeTriggerDto TimeTrigger;
[DataMember] public List<DateTuple> NextRun;
public List<DateTuple> OlderRuns;
}
[Description("Create Schedule")]
[OperationContract]
[WebInvoke(Method = "POST", UriTemplate = "schedules/create")]
TriggerCreateResult CreateNewSchedule(ScheduleDto scheduleDto);
[DataContract]
public enum ScheduleType
{
[EnumMember] NoTrigger = 0,
[EnumMember] TimeTrigger = 1,
}
此服务在幕后执行了许多复杂的操作,但返回了一个带有其定义中提到的相应属性的DTO。
我使用标题中的以下key =&gt;值来使用此服务:accept:application/json
但具有讽刺意味的是,当服务创建新计划时,我会收到 XML响应。这是第一次创建计划时,它返回XML响应。如果尝试再次创建相同的计划,那么我得到 JSON响应,即如果计划已经存在于数据库中。我们不会以不同的响应格式手动序列化。我们完全依赖于WCF的序列化/反序列化。
我尝试过像REST WCF service returns XML response but not JSON response这样的答案来追踪问题,但没有得到任何有用的信息。我浪费了两天完全尝试不同的组合,如:
KnownTypes(typeof(ScheduleType))
添加到TriggerCreateResult
DTO,以防这是序列化问题。但如果是序列化问题,它不会抛出异常吗?AlreadyExisted
设置为true
,但这根本没有帮助。json
中的RequestFormat = WebMessageFormat.Json,ResponseFormat = WebMessageFormat.Json
强制WebInvoke
响应。此外,通过确保DTO中使用的所有枚举类型ScheduleType
都使用DataContract
属性进行修饰,并将其成员声明为EnumMember
。但话说回来,即使响应是JSON 符合预期响应标头包含,Content-Type: application/xml
。 但是我想知道在请求JSON格式时导致这种自动XML序列化的原因,即使没有遇到序列化异常。我知道这是因为我们尝试了其他问题中提到的日志记录和跟踪。它只是静默地给出了HTTP 200的响应,但当预期的是JSON时,返回XML数据而不是JSON数据。
这使得这个奇怪的是,这个服务总是在请求返回时返回JSON
响应,但最近的更改引入了枚举属性ScheduleType,它被初始化为构造函数内的特定类型对应的DTO,TimeTriggerCreateResult
内的示例,它被初始化为TimeTrigger
。从那以后,它一直表现得很奇怪。此后服务的响应采用XML格式,当它创建了一个从未存在于DB中的新计划时,当发生这种情况时,bool AlreadyExisted将具有值false
。但是如果再次执行相同的请求,那么它会返回一个JSON响应,但是AlreadyExisted,现在是true
。
示例xml响应:
我不是所有WCF的专家。所以,我想知道在请求JSON时,什么可能导致WCF序列化以静默方式返回XML。
我浪费了相当多的时间(约5-6小时),试图通过测试各种不同的设置来了解正在发生的事情。我不想为此进行web.config更改,因为这是受此魔法行为影响的唯一服务。但我无法理解这种相当不自然的现象。如果您有任何想法,请提供帮助。
答案 0 :(得分:1)
我认为你需要添加
<endpointBehaviors>
<behavior name="endpointBehavior">
<enableWebScript />
<webHttp defaultBodyStyle="Wrapped" defaultOutgoingResponseFormat="Json" />
</behavior>
</endpointBehaviors>
至<system.serviceModel> <behaviors>
部分
答案 1 :(得分:1)
如果您希望响应的格式基于请求的accept标头,则需要设置WebHttpEndpoint或WebHttpBehaviour的AutomaticFormatSelectionEnabled属性。
<system.serviceModel>
<behaviors>
<endpointBehaviors>
<behavior>
<webHttp automaticFormatSelectionEnabled="true" />
</behavior>
</endpointBehaviors>
</behaviors>
<standardEndpoints>
<webHttpEndpoint>
<!-- the "" standard endpoint is used by WebServiceHost for auto creating a web endpoint. -->
<standardEndpoint name="" helpEnabled="true" />
</webHttpEndpoint>
</standardEndpoints>
</system.serviceModel>
有关详细信息,请参阅MSDN。要使用的最佳格式是通过按顺序检查以下内容来确定