WCF datacontractserialization - unexpected elements <a:anyType> - wcf

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>?

Related

RestSharp - Serialization and "[XmlAttribute]"

RestSharp - I have a class which contains nested classes.
public class Extension
{
public ID ID { get; set; }
public Extension()
{
ID = new ID();
}
}
public class ID
{
public string typeCode { get; set; }
public string Value { get; set; }
}
I'm trying to serialise an instance using RestSharp
XmlSerializer xmlSerializer = new XmlSerializer("HellThere");
string myXml = xmlSerializer.Serialize(getCatalog);
This work perfectly, and gives me (snippet)
<Extension>
<ID>
<typeCode>PriceListShortName</typeCode>
<Value>GLUS</Value>
</ID>
</Extension>
But what I want is
<Extension>
<ID typeCode="PriceListShortName">GLUS</ID>
</Extension>
I've based my class ID on the "public class Image" suggestion at
RestSharp Documentation
I've also tried using
public class ID
{
[System.Xml.Serialization.XmlAttribute("typeCode")]
public string typeCode { get; set; }
public string Value { get; set; }
}
But that doesn't fix it. Any suggestions please?
Solution found!
I changed
XmlSerializer xmlSerializer = new XmlSerializer("HelloThere");
to
DotNetXmlSerializer xmlSerialiser = new DotNetXmlSerializer("HelloThere");
And now it works!!

Deserialize Xml with RestSharp

I'm having problems getting RestSharp to deserialize some XML
this is a sample of the xml
<data xmlns:xlink="http://www.w3.org/1999/xlink">
<parameters xmlns="">
<query-strings>
<query-string value="testValue"></query-string>
</query-strings>
<sources>
<source id="database"></source>
</sources>
</parameters>
<objects>
<object xmlns="" type="testType">
<source id="database"></source>
</object>
<object xmlns="" type="testType">
<source id="database2"></source>
</object>
<object xmlns="" type="testType">
<source id="database3"></source>
</object>
</objects>
</data>
Below is the Class that I'm trying to deserialize to
public class Data
{
public Parameter Parameters { get; set; }
}
public class Parameter
{
public string InverseLookup { get; set; }
public string TypeFilters { get; set; }
public List<QueryString> QueryStrings { get; set; }
public List<Source> Sources { get; set; }
public List<Item> objects { get; set; }
}
public class QueryString
{
public string value { get; set; }
}
public class Source
{
public string Id { get; set; }
}
public class Item
{
public string Type { get; set; }
public Source Source { get; set; }
}
The problem that I have is the objects element, I just can't seem to get this to deserialize. Does anyone have any idea what's going on?
The problem appears to have been between the Keyboard and Chair. (aka I'm an idiot.)
public class Data
{
public Parameter Parameters { get; set; }
}
Should have been
public class Data
{
public Parameter Parameters { get; set; }
Public List<Item> Objects {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.....

WCF DataContractSerialzer xml to object incomplete results

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.

wcf serialization problem

I have a type MyParameter that i pass as a parameter to a wcf service
[Serializable]
public class MyParameter : IXmlSerializable
{
public string Name { get; set; }
public string Value { get; set; }
public string Mytype { get; set; }
#region IXmlSerializable Members
public System.Xml.Schema.XmlSchema GetSchema()
{
return null;
}
public void ReadXml(System.Xml.XmlReader reader)
{
XElement e = XElement.Parse(reader.ReadOuterXml());
IEnumerable<XElement> i = e.Elements();
List<XElement> l = new List<XElement>(i);
Name = l[0].Name.ToString();
Value = l[0].Value.ToString();
Mytype = l[0].Attribute("type").Value.ToString();
}
public void WriteXml(System.Xml.XmlWriter writer)
{
writer.WriteStartElement(Name);
writer.WriteAttributeString("xsi:type", Mytype);
writer.WriteValue(Value);
writer.WriteEndElement();
}
#endregion
}
The service contract looks like this:
[ServiceContract]
public interface IOperation
{
[OperationContract]
void Operation(List<Data> list);
}
Where data defines a data contract
[DataContract]
public class Data
{
public string Name { get; set; }
public List<MyParameter> Parameters{ get; set; }
}
When I run the service and test it
I get rhe exception in readXml of MyParameter
"the prefix xsi is not defined"
xsi should define the namespace "http://w3.org/2001/xmlschema-instance"
How do I fix the problem
I am very new to this so a sample code will be very very very helpful
thanks
Add:
writer.WriteAttributeString("xmlns","xsi", null,#"http://w3.org/2001/xmlschema-instance");