SOAP and using a Class containing two sub classes with same name problem
-
Hi I have an existing class that sits in a library project that is used natively for handling data object instances and also serialized/deserialized for use with json, xml and datasets. Changing the class looks to be tricky without compromising other projects. I'm trying to put a SOAP wrapper around some of the class logic but running into problems because the class has multiple Subclasses with the same name. Error Types 'Library.DataModel.HardwareOrder.ResponseSet' and 'Library.DataModel.ProduceOrder.ResponseSet' both use the XML type name, 'ResponseSet', from namespace 'http://MyTest.com/'. Use XML attributes to specify a unique XML name and/or namespace for the type. This is my ASMX
Public Function SubmitHardwareOrder(ByVal Parameters As DataModel.HardwareOrder.Parameters) As DataModel.HardwareOrder.ResponseSet 'other code logic here End Function Public Function SubmitProduceOrder(ByVal Parameters As DataModel.ProduceOrder.Parameters) As DataModel.ProduceOrder.ResponseSet 'other code logic here End Function
This is a small sample of my class
Public Class DataModel
Public Class HardwareOrder Public Class ResponseSet Public Property ResponseHeader As List(Of ResponseHeaderRow) Public Class ResponseHeaderRow Public Property TransactSucceed As Boolean Public Property TransactCode As String Public Property TransactDescription As String Public Property TransactionReference As String Public Property TpxID As String End Class End Class End Class Public Class ProduceOrder Public Class ResponseSet Public Property ResponseHeader As List(Of ResponseHeaderRow) Public Class ResponseHeaderRow Public Property TransactSucceed As Boolean Public Property TransactCode As String Public Property TransactDescription As String Public Property StaffID As String Public Property PurchaseOrder As String End Class End Class End Class
End Class
I've been looking for solutions but so far I haven't found anything that has enabled me to use my existing class without alteration. Does anyone know of any tricks that can be done in the ASMX to make it work?
-
Hi I have an existing class that sits in a library project that is used natively for handling data object instances and also serialized/deserialized for use with json, xml and datasets. Changing the class looks to be tricky without compromising other projects. I'm trying to put a SOAP wrapper around some of the class logic but running into problems because the class has multiple Subclasses with the same name. Error Types 'Library.DataModel.HardwareOrder.ResponseSet' and 'Library.DataModel.ProduceOrder.ResponseSet' both use the XML type name, 'ResponseSet', from namespace 'http://MyTest.com/'. Use XML attributes to specify a unique XML name and/or namespace for the type. This is my ASMX
Public Function SubmitHardwareOrder(ByVal Parameters As DataModel.HardwareOrder.Parameters) As DataModel.HardwareOrder.ResponseSet 'other code logic here End Function Public Function SubmitProduceOrder(ByVal Parameters As DataModel.ProduceOrder.Parameters) As DataModel.ProduceOrder.ResponseSet 'other code logic here End Function
This is a small sample of my class
Public Class DataModel
Public Class HardwareOrder Public Class ResponseSet Public Property ResponseHeader As List(Of ResponseHeaderRow) Public Class ResponseHeaderRow Public Property TransactSucceed As Boolean Public Property TransactCode As String Public Property TransactDescription As String Public Property TransactionReference As String Public Property TpxID As String End Class End Class End Class Public Class ProduceOrder Public Class ResponseSet Public Property ResponseHeader As List(Of ResponseHeaderRow) Public Class ResponseHeaderRow Public Property TransactSucceed As Boolean Public Property TransactCode As String Public Property TransactDescription As String Public Property StaffID As String Public Property PurchaseOrder As String End Class End Class End Class
End Class
I've been looking for solutions but so far I haven't found anything that has enabled me to use my existing class without alteration. Does anyone know of any tricks that can be done in the ASMX to make it work?
I was going to answer this a couple of days ago when I was compiling; sorry about that. Had to test it. You really just have a bad design and should change it. If your using this for soap you should decorate the class with serializable, so the data sent back to the client can be encoded. I would of wrote it like this to make ResponseSet reusable.
Public Class DataModel
[Serializable()]
Public Class HardwareOrderPublic Class ResponseSet Public Property TpxID As String Public Property ResponseHeader As List(Of ResponseHeaderRow) End Class End Class \[Serializable()\] Public Class ProduceOrder Public Class ResponseSet Public Property StaffID As String Public Property ResponseHeader As List(Of ResponseHeaderRow) End Class End Class \[Serializable()\] Public Class ResponseHeaderRow Public Property TransactSucceed As Boolean Public Property TransactCode As String Public Property TransactDescription As String Public Property TransactionReference As String End Class
End Class
Or perhaps add a property to the ResponseHeader called ID, a generic name and drop your property of TpxId. But if you do that then there is no need to have HardwareOrder and ProduceOrder because they become the same model. Technically this can just become
[Serializable()]
Public Class OrderPublic Property Id As String Public Property TransactSucceed As Boolean Public Property TransactCode As String Public Property TransactDescription As String Public Property TransactionReference As String End Class
If it ain't broke don't fix it Discover my world at jkirkerx.com
-
I was going to answer this a couple of days ago when I was compiling; sorry about that. Had to test it. You really just have a bad design and should change it. If your using this for soap you should decorate the class with serializable, so the data sent back to the client can be encoded. I would of wrote it like this to make ResponseSet reusable.
Public Class DataModel
[Serializable()]
Public Class HardwareOrderPublic Class ResponseSet Public Property TpxID As String Public Property ResponseHeader As List(Of ResponseHeaderRow) End Class End Class \[Serializable()\] Public Class ProduceOrder Public Class ResponseSet Public Property StaffID As String Public Property ResponseHeader As List(Of ResponseHeaderRow) End Class End Class \[Serializable()\] Public Class ResponseHeaderRow Public Property TransactSucceed As Boolean Public Property TransactCode As String Public Property TransactDescription As String Public Property TransactionReference As String End Class
End Class
Or perhaps add a property to the ResponseHeader called ID, a generic name and drop your property of TpxId. But if you do that then there is no need to have HardwareOrder and ProduceOrder because they become the same model. Technically this can just become
[Serializable()]
Public Class OrderPublic Property Id As String Public Property TransactSucceed As Boolean Public Property TransactCode As String Public Property TransactDescription As String Public Property TransactionReference As String End Class
If it ain't broke don't fix it Discover my world at jkirkerx.com
Hi Jkirkerx Thanks for your posting. I tried it the code compiles fine but the same error I described earlier arises from the asmx at runtime Error Types 'Library.DataModel.HardwareOrder.ResponseSet' and 'Library.DataModel.ProduceOrder.ResponseSet' both use the XML type name, 'ResponseSet', from namespace 'http://MyTest.com/'. Use XML attributes to specify a unique XML name and/or namespace for the type. When serializing to xml or json the class works fine but in SOAP things start to get a little ugly. I found a solution that makes it work by adding the following XmlElement tags to the routines.
Public Function SubmitHardwareOrder( Parameters As DataModel.HardwareOrder.Parameters) As XmlElement("ResponseSet", Namespace:="http://MyTest.com/HardwareOrder.ResponseSet")> DataModel.HardwareOrder.ResponseSet 'other code logic here End Function Public Function SubmitProduceOrder( Parameters As DataModel.ProduceOrder.Parameters) As XmlElement("ResponseSet", Namespace:="http://MyTest.com/ProduceOrder.ResponseSet")> DataModel.ProduceOrder.ResponseSet 'other code logic here End Function
I note that yes the above makes it work but its not beautiful because when you generate your web reference in visual studio the generated class does not have levels eg not not do this "DataModel.ProduceOrder.ResponseSet" instead its just "ResponseSet" and so next time it sees another class called "ResponseSet" it renames it to "ResponseSet1" and next time "ResponseSet2" and so on. So if you are working of a large complicated namespace/class with many levels the web references created wont be overly intuitive if naming is not unique. Clearly SOAP (Simple Object Access Protocol) is just that simple and this endeavor hits it's limitations bang on. The foreseeable options are -consume the webservice as per my above example with the inconvenience of none intuitive naming -modify the class or create a separate duplicated class just for SOAP webservice -use SOAP differently with passing/returning literals/datasets not strictly working of object model -modify or build the wsdl class manually (this is the biggest time waster! I stay well away from wsdls that dont work as is especially if not generated by visual studio) -just use xml or json and stream the data back v
-
Hi Jkirkerx Thanks for your posting. I tried it the code compiles fine but the same error I described earlier arises from the asmx at runtime Error Types 'Library.DataModel.HardwareOrder.ResponseSet' and 'Library.DataModel.ProduceOrder.ResponseSet' both use the XML type name, 'ResponseSet', from namespace 'http://MyTest.com/'. Use XML attributes to specify a unique XML name and/or namespace for the type. When serializing to xml or json the class works fine but in SOAP things start to get a little ugly. I found a solution that makes it work by adding the following XmlElement tags to the routines.
Public Function SubmitHardwareOrder( Parameters As DataModel.HardwareOrder.Parameters) As XmlElement("ResponseSet", Namespace:="http://MyTest.com/HardwareOrder.ResponseSet")> DataModel.HardwareOrder.ResponseSet 'other code logic here End Function Public Function SubmitProduceOrder( Parameters As DataModel.ProduceOrder.Parameters) As XmlElement("ResponseSet", Namespace:="http://MyTest.com/ProduceOrder.ResponseSet")> DataModel.ProduceOrder.ResponseSet 'other code logic here End Function
I note that yes the above makes it work but its not beautiful because when you generate your web reference in visual studio the generated class does not have levels eg not not do this "DataModel.ProduceOrder.ResponseSet" instead its just "ResponseSet" and so next time it sees another class called "ResponseSet" it renames it to "ResponseSet1" and next time "ResponseSet2" and so on. So if you are working of a large complicated namespace/class with many levels the web references created wont be overly intuitive if naming is not unique. Clearly SOAP (Simple Object Access Protocol) is just that simple and this endeavor hits it's limitations bang on. The foreseeable options are -consume the webservice as per my above example with the inconvenience of none intuitive naming -modify the class or create a separate duplicated class just for SOAP webservice -use SOAP differently with passing/returning literals/datasets not strictly working of object model -modify or build the wsdl class manually (this is the biggest time waster! I stay well away from wsdls that dont work as is especially if not generated by visual studio) -just use xml or json and stream the data back v
I don't know. It looks like your still using the original models or classes to me and not the modified ones. I wrote mine like this, but used serialized classes and not actual XML Then tested it calling the API in the browser, and getting that white and blue page that shows the all the WSDL services. I remember seeing my class outputted on the screen, but can't remember if it was XML. But I wrote a Win App to call this web service and it worked really well.
Public Function customers\_load(
ByVal CustomerRequest As ws_customers_Request) As ws_customers_Response
Dim customer As New ws\_customers\_Response Dim customerList As List(Of ws\_customers\_list) = Nothing Dim dwXCode As Integer = crm\_ef\_login.administrator\_Login( CustomerRequest.Credentials\_Key, CustomerRequest.Credentials\_Password
)
If (0 = dwXCode) Then If CustomerRequest.PageIndex = 0 Then CustomerRequest.PageIndex = 1 If CustomerRequest.PageSize = 0 Then CustomerRequest.PageSize = 25 Dim m\_count As Integer = crm\_ws\_ef\_customers.customers\_Load( CustomerRequest.PageIndex, CustomerRequest.PageSize, customerList ) If (m\_count > 0) Then customer.response\_Code = "OK" customer.response\_Text = m\_count & " subscribers have loaded successfully" customer.customerList = customerList Else customer.response\_Code = "E001" customer.response\_Text = "No subscribers exist in the database" customer.customerList = customerList End If Else customer.response\_Code = "E000" customer.response\_Text = "Failed Authentication" customer.customerList = Nothing End If Return customer End Function
Public Class ws_customers_Response
Private m\_response\_Code As String Private m\_response\_Text As String Private m\_customerList As List(Of ws\_customers\_list) Public Property response\_Code As String Get Return m\_response\_Code End Get Set(value As String) m\_response\_Code = value End Set End Property Public Property response\_Text As String Get Return m\_response\_Text End Get Set(value As String) m\_response\_Text = val