I have a WCF service that returnsa simple DTO that looks almost like this:
[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,
}
This service does a lot of complicated stuff behind the scenes but returns the a little DTO with the corresponding properties mentioned in its definition.
I consume this service using the following key=>value in the header: accept:application/json but the irony is that I get an XML response when the service creates a new schedule. That is the first time a schedule is created, it returns an XML response. Wheras if the same schedule is attempted to be created again, then I get a JSON response, i.e. if the schedule already existed in the database. We do not manually serialize in different response formats. We solely rely on WCF's serialization/deserialization.
I have tried answers like REST WCF service returns XML response but not JSON response to trace the problem, but haven't got any useful information out of it. I have wasted two days entirely trying different combinations like:
- Adding
KnownTypes(typeof(ScheduleType))to theTriggerCreateResultDTO just in case this was a serialization problem. But if it was a serialization problem, wouldn't it have thrown an exception? - Because it always returned a json when the schedule already existed in the database, I tried setting
AlreadyExistedtotrue, but that didn't help at all. - I can mask the problem and always force a
jsonresponse by using theRequestFormat = WebMessageFormat.Json,ResponseFormat = WebMessageFormat.Jsonin theWebInvokeof the operationcontract declaration. And also by making sure that all the enumeration types used in the DTO,ScheduleTypeis decorated with aDataContractattribute and has its members declared asEnumMember. But then again, even though the response is a JSON as expected the response header contains,Content-Type: application/xml.
But I want to know what is causing this automatic XML serialization when JSON format is requested even when no serialization exception is encountered. I know this because we tried logging and tracing as mentioned in one of the other questions. It just silently gives a response with HTTP 200 but return XML data instead of JSON data when what is expected is JSON.
What makes this weird is that, this service had always returned a JSON response whenever it was requested to return so, but a recent change introduced the enum property ScheduleType which is being initialized to a particular type inside the constructor of the corresponding DTO, example inside TimeTriggerCreateResult it is initialized ot TimeTrigger. Ever since, it has been behaving weird. The response of the service thereafter has been in an XML format, when it created a new schedule that never existed in the DB and when this happens, the bool AlreadyExisted would have the value of false. But if the same request was done again, then it returns a JSON response, but with AlreadyExisted, now being true.
A sample xml response:
I'm not an expert in all things WCF. SO I'd like to know what can cause the WCF serialization to silently return an XML when a JSON is requested for.
I have wasted considerable time (about 5-6 hours) trying to understand what is going on by testing various different settings. I wouldn't want to make a web.config change for this as this is the only service affected by this magical behaviour. But I have failed miserably to understand this rather unnatural phenomenon. Please help if you have any ideas.
