views:

343

answers:

2

I'm building a web service to accept notifications from a company. The company informed me that the service is incorrectly structured and provided me the .asmx of a working web service. It looks like this:

Request:

<?xml version="1.0" encoding="utf-8"?>
<soap12:Envelope
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:xsd="http://www.w3.org/2001/XMLSchema"
       xmlns:soap12="http://www.w3.org/2003/05/soap-envelope"&gt;
  <soap12:Body>
    <AuthenticationInfo
           xmlns="http://www.usps.com/postalone/services/UserAuthenticationSchema"&gt;
      <UserId xmlns="">string</UserId>
      <UserPassword xmlns="">string</UserPassword>
    </AuthenticationInfo>
    <fullServiceAddressCorrectionNotification
            xmlns="http://www.usps.com/postalone/services/POCustomerMailXMLServices"&gt;string&lt;/fullServiceAddressCorrectionNotification&gt;
  </soap12:Body>
</soap12:Envelope>

Response:

<?xml version="1.0" encoding="utf-8"?>
<soap12:Envelope
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:xsd="http://www.w3.org/2001/XMLSchema"
       xmlns:soap12="http://www.w3.org/2003/05/soap-envelope"&gt;
  <soap12:Body>
    <FullServiceNixieDetailNotificationResponse
         xmlns="http://idealliance.org/maildat/Specs/md091/mailxml70C/mailxml"&gt;
      <FullServiceNixieDetailNotificationResult>string</FullServiceNixieDetailNotificationResult>
    </FullServiceNixieDetailNotificationResponse>
  </soap12:Body>
</soap12:Envelope>

Mine looks like this: Request:

<?xml version="1.0" encoding="utf-8"?>
<soap12:Envelope
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:xsd="http://www.w3.org/2001/XMLSchema"
       xmlns:soap12="http://www.w3.org/2003/05/soap-envelope"&gt;
  <soap12:Body>
    <FullServiceNixieDetailNotification
          xmlns="http://idealliance.org/maildat/Specs/md091/mailxml70C/mailxml"&gt;
      <AuthenticationInfo>
        <UserID>string</UserID>
        <Password>string</Password>
      </AuthenticationInfo>
      <fullServiceAddressCorrectionNotification>string</fullServiceAddressCorrectionNotification>
    </FullServiceNixieDetailNotification>
  </soap12:Body>
</soap12:Envelope>

Response:

<?xml version="1.0" encoding="utf-8"?>
<soap12:Envelope
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:xsd="http://www.w3.org/2001/XMLSchema"
       xmlns:soap12="http://www.w3.org/2003/05/soap-envelope"&gt;
  <soap12:Body>
    <notificationResponse
       xmlns="http://www.usps.com/postalone/services/POCustomerMailXMLServices"&gt;string&lt;/notificationResponse&gt;
  </soap12:Body>
</soap12:Envelope>

As you can see, my stuff is wraped in an extra element I need to get rid of. Unfortunatley, I'm not sure how to do this. My web service code is as follows:

Imports System.Web.Services
Imports System.Web.Services.Protocols
Imports System.ComponentModel
Imports System.Data.SqlClient

Public Structure AuthenticationInfoType
    Dim UserID As String
    Dim Password As String
End Structure

' To allow this Web Service to be called from script, using ASP.NET AJAX, uncomment the following line.
' <System.Web.Script.Services.ScriptService()> _
<System.Web.Services.WebService(Namespace:="http://idealliance.org/maildat/Specs/md091/mailxml70C/mailxml")&gt; _
<System.Web.Services.WebServiceBinding(ConformsTo:=WsiProfiles.BasicProfile1_1)> _
<ToolboxItem(False)> _
Public Class USPSMailXML
    Inherits System.Web.Services.WebService  

    <WebMethod()> _
    Public Function FullServiceNixieDetailNotification(ByVal AuthenticationInfo As AuthenticationInfoType, ByVal fullServiceAddressCorrectionNotification As String) As String

        'Some code here

        Return "MyResponse"

    End Function
+2  A: 

Couple up-front things before getting to the actual question.

  1. The first thing you should do is get away from ASMX and use WCF. If you don't already know WCF, there will a learning curve for you. But I'm guessing - and don't take this the wrong way - you're not really an expert in ASMX. If so, don't spend the time becoming an expert in ASMX, which is yesterday's technology; invest some time in learning WCF. It's better for you, for your company.

  2. Just to get the terminology straight, The first two snips that you are showing are neither ASMX, nor WSDL. They are the actual wire-level messages.

  3. Regardless of the choice of implementation technology on your side, let me tell you that the example incoming and outgoing messages you showed are pretty strange. First, it's not WSI BP1.0 compliant: The incoming message elements are not wrapped in a toplevel element. Why not? And yet, the response message is wrapped in a toplevel element. Why? The inconsistency seems arbitrary. Also, the element names are all TitleCase, except for one -- the fullServiceAddressCorrectionNotification, which uses camelCase. Why? Additionally, the incoming message is a USPS namespace, yet the parameters use the null namespace. Huh? Who does that? It's legal, but it seems vvvverrrry odd. Finally, the xml namespace on the response is totally different from the xml namespace on the incoming message. (I can imagine a good justification for this last one). I gather you are not in charge of designing the messages. But these inconsistencies raise a red flag to me. That's what I would call a jalopy message design.


Ok, with all that out of the way...

There is a way to shape the request and response in ASMX, using the SoapDocumentMethodAttribute, and strategic placements of the XmlElement attribute, along with the existing WebMethod attribute. SoapDocumentMethodAttribute gives you access to the knobs and levers to specify the element names and namespaces for the incoming and outgoing messages.

This should get you pretty close:

<%@
  WebService
  Language="VB"
  Class="USPSMailXML"
%>

Imports System
Imports System.Web.Services
Imports System.Web.Services.Protocols
Imports System.ComponentModel
Imports System.Diagnostics
Imports System.Xml.Serialization


Public Structure AuthenticationInfoType
    <XmlElement(Namespace := "")> _
    Dim UserID As String
    <XmlElement(Namespace := "")> _
    Dim Password As String
End Structure


Public Structure NixieResponse
    <XmlElement("FullServiceNixieDetailNotificationResult")> _
    Dim Message As String
End Structure


' Must not claim WSI compliance; there are multiple toplevel elements in the Request body
'
'<System.Web.Services.WebServiceBinding(ConformsTo:=WsiProfiles.BasicProfile1_1)> _
<System.Web.Services.WebService(Namespace:="http://idealliance.org/maildat/Specs/md091/mailxml70C/mailxml"), _
       System.Web.Services.WebServiceBinding(ConformsTo := WsiProfiles.None), _
       ToolboxItem(False)> _
Public Class USPSMailXML
    Inherits System.Web.Services.WebService

    <WebMethod(), _
     SoapDocumentMethod( _
                        Action := "", _
                        RequestElementName := "AuthenticationInfo", _
                        ResponseElementName := "FullServiceNixieDetailNotificationResponse", _
                        RequestNamespace := "http://www.usps.com/postalone/services/UserAuthenticationSchema", _
                        ResponseNamespace := "http://idealliance.org/maildat/Specs/md091/mailxml70C/mailxml", _
                        Use := System.Web.Services.Description.SoapBindingUse.Literal, _
                        ParameterStyle := System.Web.Services.Protocols.SoapParameterStyle.Bare)> _
    Public Function FullServiceNixieDetailNotification(ByVal AuthenticationInfo As AuthenticationInfoType, _
                                                       <XmlElement(Namespace := "http://www.usps.com/postalone/services/POCustomerMailXMLServices")&gt; _
                                                       ByVal fullServiceAddressCorrectionNotification As String) _
              As  <XmlElement("FullServiceNixieDetailNotificationResponse")> NixieResponse

        Dim r As New NixieResponse
        r.Message = "My Response"

        Return r

    End Function

End Class

I had to mark it as ParameterStyle = Bare, because the incoming message has 2 toplevel elements. This means the outgoing message was also Bare, which in your case is NOT what you want. Therefore the outgoing message, which is just a string - I had to wrap it into a structure, in order to get the shape the way you showed.

I already commented on the design of the incoming and outgoing messages. Some of these contortions would not be necessary if the message design were more "sane".

Cheeso
Thank you, and you are correct. I am not an expert in Web Services, ASMX or WCF. My specialty in in application development. This is our companies first web service implementation. We are familiar with WCF, but I was directed not to implement it by management.Your code has gotten me where I need to be. Thank you for taking the time to post that, it has helped me imensley.
Brett
A: 

According to XMLspy, your version is correct. Here's the request it generates:

<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" 
    xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"&gt;
    <SOAP-ENV:Body>
        <m:AuthenticationInfo 
            xmlns:m="http://www.usps.com/postalone/services/UserAuthenticationSchema"&gt;
            <UserId>String</UserId>
            <UserPassword>String</UserPassword>
        </m:AuthenticationInfo>
        <m2:fullServiceNixieDetailQuery 
            xmlns:m2="http://www.usps.com/postalone/services/POAppointmentServices20"&gt;
            String
        </m2:fullServiceNixieDetailQuery>
    </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

Note that the authentication "header" and the query are in two different namspaces.

John Saunders
Saunders, seems to me it's not a matter of "correctness". He's got some target message formats he needs to comply with. He needs to provide the ASMX code that will accept requests and generate responses in those formats. The sample messages server as an informal WSDL.
Cheeso
It is a matter of correctness, since he's been given a WSDL.
John Saunders
OBTW, if those samples came from the USPS, then they're suspect. They have a horrible record when it comes to support of XML. They entered the field early, before SOAP, then never changed until very recently.
John Saunders