Using different classes with the same name as a return type in a c# webservice
I am creating a webservice that should return two complex types from the same class library that have the same class name (but live in different namespaces). When I open the TestService.asmx in my browser I get an exception (see below). Is there a way to fix this (other than renaming the classes of course :D )
I tried decorating my methods with
[WebMethod(MessageName="MyNamespace1.SomeClass")]
and with
[return: XmlElement("SomeClass1", Namespace = "http://tempuri.org/NameSpace1")]
-
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Services;
namespace MyWebservice
{
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.ComponentModel.ToolboxItem(false)]
public class TestService : System.Web.Services.WebService
{
public MyNamespace1.SomeClass GetSomeClass1()
{
return new MyNamespace1.SomeClass() { Name = "SomeClass1" };
}
public MyNamespace2.SomeClass GetSomeClass2()
{
return new MyNamespace2.SomeClass() { Name = "SomeClass1" };
}
}
}
namespace MyNamespace1
{
public class SomeClass
{
public string Name { get; set; }
}
}
namespace MyNamespace2
{
public class SomeClass
{
public string Name { get; set; }
}
}
throws this exception:
[InvalidOperationException: Die Typen 'MyNamespace2.SomeClass' und 'MyNamespace1.SomeClass' verwenden den XML-Typnamen 'SomeClass' im Namespace 'http://tempuri.org/'. Geben Sie mit XML-Attributen einen eindeutigen XML-Namen und/oder Namespace für den Typ an.]
System.Xml.Serialization.XmlReflectionImporter.GetTypeMappi开发者_开发百科ng(String typeName, String ns, TypeDesc typeDesc, NameTable typeLib, Type type) +4071889
System.Xml.Serialization.XmlReflectionImporter.ImportStructLikeMapping(StructModel model, String ns, Boolean openModel, XmlAttributes a, RecursionLimiter limiter) +150
System.Xml.Serialization.XmlReflectionImporter.ImportTypeMapping(TypeModel model, String ns, ImportContext context, String dataType, XmlAttributes a, Boolean repeats, Boolean openModel, RecursionLimiter limiter) +1604
Ok, I found the solution by trial and error.
The key is to combine the [return: XmlRoot...]
and [return: XmlElement...]` decoration to make it work.
[WebMethod]
[return: XmlRoot(Namespace = "http://tempuri.org/Namespace1")]
[return: XmlElement(Namespace = "http://tempuri.org/Namespace1",
ElementName = "SomeClass")]
public MyNamespace1.SomeClass GetSomeClass1()
{
return new MyNamespace1.SomeClass() { Name = "SomeClass1" };
}
[WebMethod]
[return: XmlRoot(Namespace = "http://tempuri.org/Namespace2")]
[return: XmlElement(Namespace = "http://tempuri.org/Namespace2",
ElementName = "SomeClass")]
public MyNamespace2.SomeClass GetSomeClass2()
{
return new MyNamespace2.SomeClass() { Name = "SomeClass1" };
}
Update: This also applies to method parameters. Just change return:
to param:
and you're done. (You can't add the XmlRoot to params, but that's not necessary anyway.
[WebMethod]
public void AddSomeClass1([param: XmlElement(
Namespace = "http://tempuri.org/Namespace1",
ElementName = "SomeClass")] MyNamespace1.SomeClass class1)
{
}
[WebMethod]
public void AddSomeClass2([param: XmlElement(
Namespace = "http://tempuri.org/Namespace2",
ElementName = "SomeClass")] MyNamespace2.SomeClass class2)
{
}
try adding the following attribute above your classes
[XmlRoot(Namespace = "http://tempuri.org/SubNameSpace")]
With a different value for the sub namespace.
For the people, who want to know what the syntax for VB is (since I lost some time trying to find out what the equivalent to the return: statement is):
<WebMethod> _
Public Function GetSomeClass1() As <XmlRoot(Namespace:="http://tempuri.org/Namespace1"), XmlElement("SomeClass", Namespace:="http://tempuri.org/Namespace1")> MyNamespace1.SomeClass
' Return Stuff
End Function
精彩评论