WCF DataContractSerialzer xml to object incomplete results - wcf

I'm creating a wcf wrapper service that returns xml from another web service.
What I'm noticing is that not all the xml from the source is being serialized to my object.
Here's the source xml:
<?xml version="1.0" standalone="yes"?>
<methodResponse>
<requestId>234843080</requestId>
<errorCode>0</errorCode>
<errorText></errorText>
<processingTime>00:00:00.234</processingTime>
<results>
<resultCode>0</resultCode>
<resultText></resultText>
<resultCount>1</resultCount>
<totalResultCount>1</totalResultCount>
<result>
<contactId>123</contactId>
<sourceFolderId>3443</sourceFolderId>
<contactState>4</contactState>
<contactStateSortOrder>3</contactStateSortOrder>
<contactType>person</contactType>
<displayName>Bond, James</displayName>
<office>unknown</office>
<department></department>
<changeDate></changeDate>
<firstName>James</firstName>
<middleName></middleName>
<lastName>Bond</lastName>
<jobTitle>Spy</jobTitle>
<ape>
<address type='Street' typeId='1' relationship='Business' relationshipId='1'>
<addressLine></addressLine>
<city></city>
<state></state>
<postalCode></postalCode>
</address>
<phone type='Phone' typeId='1' relationship='Business' relationshipId='1'>
<phoneNumber></phoneNumber>
<description/>
<formattedPhone></formattedPhone>
</phone>
</ape>
</result>
</results>
</methodResponse>
The wcf wrapper service:
[DataContract(Name="methodResponse", Namespace = "")]
public partial class methodResponse {
[DataMember]
public int errorCode {
get;
set;
}
[DataMember]
public string errorText {
get;
set;
}
[DataMember]
public string requestId
{
get;
set;
}
[DataMember]
public methodResponseResults[] results
{
get;
set;
}
}
[DataContract(Namespace = "")]
public partial class methodResponseResults
{
[DataMember]
public string resultCode {
get;
set;
}
[DataMember]
public string resultText {
get;
set;
}
[DataMember]
public string resultCount {
get;
set;
}
[DataMember]
public string totalResultCount {
get;
set;
}
[DataMember]
public methodResponseResultsResult[] result {
get;
set;
}
}
[DataContract(Namespace="")]
public partial class methodResponseResultsResult {
public string contactId
{
get;
set;
}
public string displayName
{
get;
set;
}
}
[ServiceContract]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
public class WcfWrapperService
{
public Response GetXml()
{
string uri = ""; // uri to source web service
var dataContractSerializer = new DataContractSerializer(typeof(methodResponse));
using (XmlReader reader = XmlReader.Create(uri))
{
var result = (methodResponse)dataContractSerializer.ReadObject(reader);
//result object looks like:
//result.errorCode = 0;
//result.errorText = null;
//result.requestId = 234843080;
//result.results = methodResponseResults[0];
}
// return Response object
}
}
The errorCode, errorText, requestId values are there but no results.

The first thing that jumps out is that you are trying to de/serialize a contract which contains attributes. DataContractSerializer has a few restrictions, one of which is that it can only serialize/deserialize elements. In order to properly handle this Schema, you will need to use an XmlSerializer.

Your not setting any values for the Order property on your DataMember attributes. This means that the elements will be processed in alphabetical order which is most likely NOT what you want. You must explicitly set Order to ensure it matches the schema of the documents you will process. You may also need to set IsRequired = false if there are any elements that may or not be in the instance document.

Related

Not able to pass List<FilterData> using WCF with wsHttpBinging

I am not able to pass List using WCF with wsHttpBinging. List is a property of FilterResponse class.
Getting the following error.
-Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host.
//Following is the code.
[DataContract(Namespace = "Abc.Wao.Entity.Response")]
[CollectionDataContract]`
public class FilterResponse : Alcoa.Wao.Entity.Response.Response
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1002:DoNotExposeGenericLists"), DataMember]
public List<FilterData> FilterData { get; set; }
}
[KnownType(typeof(FilterResponse))]
[CollectionDataContract]
[DataContract(Namespace = "Abc.Wao.Entity.Response")]
public class Response
{
public Response()
{ }
[DataMember]
public string AuthToken { get; set; }
[DataMember]
public string Fault { get; set; }
[DataMember]
public Exception Exception { get; set; }
[DataMember]
public string SessionContext { get; set; }
}
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall, ConcurrencyMode = ConcurrencyMode.Multiple)]
public class WaoService : IWaoService
{
public FilterResponse GetFilterDetails()
{
FilterResponse res = null;
//Call factory
res = Abc.Wao.Factory.CommonFactory.GetFilterDetails();
return res;
}
}
//------------------------------------------------------
[ServiceContract]
[ServiceKnownType(typeof(FilterResponse))]
[ServiceKnownType(typeof(Response))]
public interface IWaoService
{
[OperationContract]
FilterResponse GetFilterDetails();
}
Your property in the DataContract is missing a DataMember attribute:
[DataMember]
public List<FilterData> FilterData { get; set; }

How to setup a DataContract to match the complex XML input in WCF 4.0 REST Service

I have a XML structure like this:
<Message>
<Messagehead>
<OSType>Android</OSType>
<RouteDest>SiteServerName</RouteDest>
<ActionType>Enroll</ActionType>
</Messagehead>
<MessageBody>
<Raw>
<![CDATA[OrienginalMessageContent]]>
</Raw>
</MessageBody>
</Message>
and I want upload this XML to WCF 4.0 my rest service:
public string Enroll(Message instance)
{
// TODO: Add the new instance of SampleItem to the collection
return "success";
}
the Message is a DataContract type, I setup it like below:
[DataContract(Namespace = "")]
public class Message
{
[DataMember]
public MessageHead MessageHead { get; set; }
[DataMember]
public MessageBody MessageBody { get; set; }
}
public class MessageHead
{
public OSType OSType { get; set; }
public string RouteDest { get; set; }
public Action Action { get; set; }
}
public class MessageBody
{
public string RawRequestContent { get; set; }
}
but when I get the Message instance from the server side, all the property is null, except the OSType, can anybody tell me why? How could I solve this problem?
Besides being a really bad name for a class (since it's already used in the WCF runtime), your Message class also has some flaws:
<Message>
<Messagehead>
....
</Messagehead>
Your <Messagehead> has a lower-case h in the middle - yet your class defines it to be upper case:
[DataContract(Namespace = "")]
public class Message
{
[DataMember]
public MessageHead MessageHead { get; set; }
This will not work - case is important and relevant in a WCF message! If your XML has a lower-case h, so must your DataContract class!
Your XML also requires a <Raw> tag inside your <MessageBody>
<MessageBody>
<Raw>
<![CDATA[OriginalMessageContent]]>
</Raw>
</MessageBody>
yet your data contract doesn't respect that:
public class MessageBody
{
public string RawRequestContent { get; set; }
}
Again - those don't line up! Names are important - and they must match between your XML representation of the message, and the C# class representing that message.....

How to get json response of a custom object using wcf REST services?

How can I serialize an object to return a custom type?
//The response is null.
http://localhost:50604/GameService/Getbyid?id=1
[WebGet(ResponseFormat = WebMessageFormat.Json)]
public MyClass GetById(int id)
[DataContract]
[KnownType(typeof(User))]
public partial class MyClass
{
[DataMember]
public int Id { get; set; }
[DataMember]
public string Name { get; set; }
[DataMember]
public int? CreatedBy { get; set; }
[DataMember]
public virtual User CreatedByUser { get; set; } //How will I serialize this?
}
You are missing UriTemplate for your operation so your Id is probably never passed in and your method works with default value = 0.
Try this:
[WebGet(UriTemplate="Getbyid?id={id}", ResponseFormat = WebMessageFormat.Json)]
public MyClass GetById(int id)
CreatedByUser will be serialized automatically if filled and if User is data contract as well.

WCF datacontractserialization - unexpected elements <a:anyType>

The current xml output looks like:
<response xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<totalResultCount>10</totalResultCount>
<results xmlns:a="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
<a:anyType i:type="result">
<EmployeeCode>007</EmployeeCode>
<EmployeeName>Bond, James</EmployeeName>
</a:anyType>
<a:anyType i:type="result">
<EmployeeCode>006</EmployeeCode>
<EmployeeName>Foo, Bar</EmployeeName>
</a:anyType>
</results>
</response>
I would like the xml to be in this format:
<response xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<totalResultCount>10</totalResultCount>
<results xmlns:a="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
<result>
<EmployeeCode></EmployeeCode>
<EmployeeName></EmployeeName>
</result>
</results>
</response>
Data Contracts
internal static class KnownTypesProvider
{
public static IEnumerable<Type> GetKnownTypes(ICustomAttributeProvider provider)
{
// collect and pass back the list of known types
List<Type> types = new List<Type>();
types.Add(typeof(EmployeeDTO));
return types;
}
}
[DataContract(Name = "response")]
public class Response
{
[DataMember(Order = 1)]
public int totalResultCount { get; set; }
[DataMember(Order = 2)]
public IEnumerable results { get; set; }
}
[DataContract(Name = "result")]
public class EmployeeDTO
{
[DataMember]
public string EmployeeCode { get; set; }
[DataMember]
public string EmployeeName { get; set; }
}
What am I missing here?
IEnumerable is a list of Object, so WCF is adding the type to the output. Can you use IEnumerable<EmployeeDTO> or List<EmployeeDTO>?

Serialize Partial DataContract

I have a DataContract that looks like:
[DataContract(Name = User.Root, Namespace = "")]
public class RegisterUser
{
[DataMember(Name = User.EmailAddress)]
public string EmailAddress { get; set; }
[DataMember(Name = User.UserName)]
public string UserName { get; set; }
[DataMember(Name = User.Password)]
public string Password { get; set; }
[DataMember(Name = User.FirstName)]
public string FirstName { get; set; }
[DataMember(Name = User.LastName)]
public string LastName { get; set; }
[DataMember(Name = User.PhoneNumber)]
public string PhoneNumber { get; set; }
[DataMember(Name = "RequestMessage")]
public string RequestMsg { get; set; }
}
And I would like to get the elements out of it. So instead of
<ROOT> <Element1/>...</ROOT>. I would just like to get <Element1/> (for partial xsd validation).
I thought I could use this function:
public static string Serialize<T>(T obj)
{
DataContractSerializer ser = new DataContractSerializer(obj.GetType());
String text;
using (MemoryStream memoryStream = new MemoryStream())
{
ser.WriteObject(memoryStream, obj);
byte[] data = new byte[memoryStream.Length];
Array.Copy(memoryStream.GetBuffer(), data, data.Length);
text = Encoding.UTF8.GetString(data);
}
return text;
}
and just pass it
string str = Serialize(test.EmailAddress);
That works great but the xml looks like:
"<string xmlns=\"http://schemas.microsoft.com/2003/10/Serialization/\">myemail.com</string>"
I lost the DataMember info. How can I retain that as well?
Use WriteObjectContent instead of WriteObject:
http://msdn.microsoft.com/en-us/library/ms573853.aspx