XmlRootAttribute issue

  • Thread starter Thread starter John Lee
  • Start date Start date
J

John Lee

Hi,

I created a strong-typed (Class1) collection class for my web service, it
actually serialized to <ArrayOfClass1 /> and I need to make the root named
as <Class1Collection /> so I was trying to add an XmlRootAttribute but I
always got error message when I tried to serialize this collection class,
Could anyone point me out why and how to achieve the goal?


[XmlRoot("Class1Collection")]
public class Class1Collection : Collectionbase
{
...
}

2. What should I do if I need the serialized xml has namespace prefix like
the following:

<ns0:Class1Collection xmlns:ns0="http://mynamespace">
...
</ns0:Class1Collection>


Thanks very much in advance!

John
 
Hi John,

First of all, I would like to confirm my understanding of your issue. From
your description, I understand that you need to add a root element for your
Xml serialization, and also add a namespace for the xml document. If there
is any misunderstanding, please feel free to let me know.

We can use the XmlRootAttribute and assign the Namespace and ElementName
properties to achieve that. Here is an example:

[XmlRoot(Namespace = "www.contoso.com", ElementName = "Class1Collection")]
public class Class1Collection : Collectionbase
{
//.....
}

HTH.

Kevin Yu
=======
"This posting is provided "AS IS" with no warranties, and confers no
rights."
 
Hi, Kevin,

Thanks for your reply but did you read my post? In my post, I stated when I
added the XmlRoot attribute and I got error when I serialize the object - I
knew we could use XmlRoot but I thought XmlRoot has some restriction on
certain type of class? Because I could serialize it before I added "XmlRoot"
attribute and it serialized to "<ArrayOfClass1 />" - after I added
XmlRoot("Class1Collection") then I could not use the same code to do the
serialization.

Thanks!
John
 
Hi John,

I think the problem you encountered is caused by the following things:

1. XmlRoot Attribute indicate that this class will be serizlied as the
RootElement of a XML document , however the Collection class is just a sub
element in the webservice SOAP message which can't be validated by the
runtime. So I think XmlRoot attribute can't be applied on your class.

2. As for changing the Serlized Element name of our custom Collection
class, after some local tests, I think we can't modify it directly if our
webmethod return the custom Collection class instance directly as return
type. This is because the ASP.NET webservice geneator will by default treat
such custom Collection class as a Array Type, ( you can verify this by
check the webservice 's webreference/ client proxy in client application),
the client side return Type is an Array of the ArrayItem's class rather
than the Collection class itself. And for Array Type, the .net will always
serilized it as "ArrayOf[ItemTypeName]" .

Currently I haven't found any direct means(Attribute) to modify the output
XML Element of an Array Type if we're using the default serlization of the
..net. However, we can workaround it through a wrapper class which contain
the Custom Collection class as a class member, then we can apply XmlElement
attribute on it to modify it's output ElementName, for example:

#we can specify attribute to customize the Wrapper element and the inner
collection property:


[XmlType("MyWrapper")]
public class Employees
{
private EmployeeCollection _items;

[XmlArray("MyEmployeeColletion")]
public EmployeeCollection Items
{
get
{return _items;}
set
{_items = value;}
}
}

public class EmployeeCollection:ICollection
{
.....
}

public class Employee
{
........
}

===========================

the output will be something like:


<MyWrapper xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://tempuri.org/">
<MyEmployeeColletion>
<Employee>
<EmpName>EmpName_0</EmpName>
<EmpID>EmpID_0</EmpID>
</Employee>
<Employee>
<EmpName>EmpName_1</EmpName>
<EmpID>EmpID_1</EmpID>
</Employee>
........................
</MyEmployeeColletion>
</MyWrapper>

=====================================


Thanks,

Steven Cheng
Microsoft Online Support

Get Secure! www.microsoft.com/security
(This posting is provided "AS IS", with no warranties, and confers no
rights.)
 
Thanks very much, Steven!

I understand your approach perfectly to have a wrapper class but the issue
is
the generated xml would have <MyWrapper> as its root - But I have to create
an object model that can produce the xml exactly as 3rd party's
specification which is

<Class1Collection>
<Class1 />
<Class1 />
</Class1Collection>

How could I create an object model (classes) that would produce the above
xml?

Thanks a lot!
John

Steven Cheng said:
Hi John,

I think the problem you encountered is caused by the following things:

1. XmlRoot Attribute indicate that this class will be serizlied as the
RootElement of a XML document , however the Collection class is just a sub
element in the webservice SOAP message which can't be validated by the
runtime. So I think XmlRoot attribute can't be applied on your class.

2. As for changing the Serlized Element name of our custom Collection
class, after some local tests, I think we can't modify it directly if our
webmethod return the custom Collection class instance directly as return
type. This is because the ASP.NET webservice geneator will by default
treat
such custom Collection class as a Array Type, ( you can verify this by
check the webservice 's webreference/ client proxy in client application),
the client side return Type is an Array of the ArrayItem's class rather
than the Collection class itself. And for Array Type, the .net will
always
serilized it as "ArrayOf[ItemTypeName]" .

Currently I haven't found any direct means(Attribute) to modify the output
XML Element of an Array Type if we're using the default serlization of the
net. However, we can workaround it through a wrapper class which contain
the Custom Collection class as a class member, then we can apply
XmlElement
attribute on it to modify it's output ElementName, for example:

#we can specify attribute to customize the Wrapper element and the inner
collection property:


[XmlType("MyWrapper")]
public class Employees
{
private EmployeeCollection _items;

[XmlArray("MyEmployeeColletion")]
public EmployeeCollection Items
{
get
{return _items;}
set
{_items = value;}
}
}

public class EmployeeCollection:ICollection
{
.....
}

public class Employee
{
.......
}

===========================

the output will be something like:


<MyWrapper xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://tempuri.org/">
<MyEmployeeColletion>
<Employee>
<EmpName>EmpName_0</EmpName>
<EmpID>EmpID_0</EmpID>
</Employee>
<Employee>
<EmpName>EmpName_1</EmpName>
<EmpID>EmpID_1</EmpID>
</Employee>
.......................
</MyEmployeeColletion>
</MyWrapper>

=====================================


Thanks,

Steven Cheng
Microsoft Online Support

Get Secure! www.microsoft.com/security
(This posting is provided "AS IS", with no warranties, and confers no
rights.)
 
Glad to hear from you John!

I was just back from the holiday of the Labor Day :-). As for the further
question you mentioned, I think it's possible if what you want is just
build a class which can be serialized as the below output:


<myclassCollection xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<myclass id="0">Value_0</myclass>
<myclass id="1">Value_1</myclass>
<myclass id="2">Value_2</myclass>
</myclassCollection>


we can generate the above xml through the following class definition:
===================
public class myclassCollection
{

[System.Xml.Serialization.XmlElementAttribute("myclass",
Form=System.Xml.Schema.XmlSchemaForm.Unqualified, IsNullable=true)]
public myclassCollectionMyclass[] Items;
}

public class myclassCollectionMyclass
{
[System.Xml.Serialization.XmlAttributeAttribute()]
public string id;

[System.Xml.Serialization.XmlTextAttribute()]
public string Value;
}
=======================

The important thing is that we can't use our own custom Collection class,
but use a simple class which contains an Array member of the ArrayItem
class instances. In addition, I get the above class definition through the

xsd.exe tool. It's a quite good tool which can help auto-generate
XmlSchema definiation / class file through a given xml file. I think it'll
be helpful to you when you are wanting to create some class model for xml
serializaiton from some given xml template.

#XML Schema Definition Tool (Xsd.exe)
http://msdn.microsoft.com/library/en-us/cptools/html/cpconxmlschemadefinitio
ntoolxsdexe.asp?frame=true

Thanks,

Steven Cheng
Microsoft Online Support

Get Secure! www.microsoft.com/security
(This posting is provided "AS IS", with no warranties, and confers no
rights.)
 
Back
Top