.NET 网络服务。 (ASMX) 如何塑造请求和响应消息?

发布于 2024-08-15 04:23:33 字数 3897 浏览 2 评论 0 原文

我正在构建一个网络服务来接受来自公司的通知。该公司通知我该服务的结构不正确,并为我提供了可用的网络服务的 .asmx。它看起来像这样:

请求:

<?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">
  <soap12:Body>
    <AuthenticationInfo
           xmlns="http://www.usps.com/postalone/services/UserAuthenticationSchema">
      <UserId xmlns="">string</UserId>
      <UserPassword xmlns="">string</UserPassword>
    </AuthenticationInfo>
    <fullServiceAddressCorrectionNotification
            xmlns="http://www.usps.com/postalone/services/POCustomerMailXMLServices">string</fullServiceAddressCorrectionNotification>
  </soap12:Body>
</soap12:Envelope>

响应:

<?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">
  <soap12:Body>
    <FullServiceNixieDetailNotificationResponse
         xmlns="http://idealliance.org/maildat/Specs/md091/mailxml70C/mailxml">
      <FullServiceNixieDetailNotificationResult>string</FullServiceNixieDetailNotificationResult>
    </FullServiceNixieDetailNotificationResponse>
  </soap12:Body>
</soap12:Envelope>

我的看起来像这样: 请求:

<?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">
  <soap12:Body>
    <FullServiceNixieDetailNotification
          xmlns="http://idealliance.org/maildat/Specs/md091/mailxml70C/mailxml">
      <AuthenticationInfo>
        <UserID>string</UserID>
        <Password>string</Password>
      </AuthenticationInfo>
      <fullServiceAddressCorrectionNotification>string</fullServiceAddressCorrectionNotification>
    </FullServiceNixieDetailNotification>
  </soap12:Body>
</soap12:Envelope>

响应:

<?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">
  <soap12:Body>
    <notificationResponse
       xmlns="http://www.usps.com/postalone/services/POCustomerMailXMLServices">string</notificationResponse>
  </soap12:Body>
</soap12:Envelope>

如您所见,我的东西被包裹在一个我需要删除的额外元素中。不幸的是,我不知道该怎么做。我的网络服务代码如下:

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")> _
<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

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">
  <soap12:Body>
    <AuthenticationInfo
           xmlns="http://www.usps.com/postalone/services/UserAuthenticationSchema">
      <UserId xmlns="">string</UserId>
      <UserPassword xmlns="">string</UserPassword>
    </AuthenticationInfo>
    <fullServiceAddressCorrectionNotification
            xmlns="http://www.usps.com/postalone/services/POCustomerMailXMLServices">string</fullServiceAddressCorrectionNotification>
  </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">
  <soap12:Body>
    <FullServiceNixieDetailNotificationResponse
         xmlns="http://idealliance.org/maildat/Specs/md091/mailxml70C/mailxml">
      <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">
  <soap12:Body>
    <FullServiceNixieDetailNotification
          xmlns="http://idealliance.org/maildat/Specs/md091/mailxml70C/mailxml">
      <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">
  <soap12:Body>
    <notificationResponse
       xmlns="http://www.usps.com/postalone/services/POCustomerMailXMLServices">string</notificationResponse>
  </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")> _
<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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

孤君无依 2024-08-22 04:23:33

在讨论实际问题之前先把前面的事情结合起来。

  1. 您应该做的第一件事就是摆脱 ASMX 并使用 WCF。如果您还不了解 WCF,您将有一个学习曲线。但我猜测 - 不要误解 - 您并不是真正的 ASMX 专家。如果是这样,请不要花时间成为 ASMX 专家,因为这已经是昨天的技术了;投入一些时间学习WCF。这对您和您的公司都更好。

  2. 为了弄清楚术语,您显示的前两个片段既不是 ASMX,也不是 WSDL。它们是实际的线路级消息。

  3. 无论您选择何种实现技术,让我告诉您,您显示的示例传入和传出消息都非常奇怪。首先,它不符合 WSI BP1.0:传入的消息元素未包装在顶级元素中。为什么不呢?然而,响应消息包装在顶级元素中。为什么?这种不一致似乎是任意的。此外,元素名称均采用 TitleCase,除了 fullServiceAddressCorrectionNotification(使用驼峰式命名法)之外。为什么?此外,传入消息是 USPS 命名空间,但参数使用 null 命名空间。啊?谁做的??这是合法的,但看起来vvvverrrry很奇怪。最后,响应上的 xml 命名空间与传入消息上的 xml 命名空间完全不同。 (我可以想象最后一个的充分理由)。我猜你不负责设计这些消息。但这些不一致给我带来了危险信号。这就是我所说的jalopy消息设计。


好吧,所有这些都已经解决了......

有一种方法可以在 ASMX 中使用 SoapDocumentMethodAttribute,以及 XmlElement 属性的战略放置以及现有的 WebMethod 属性。 SoapDocumentMethodAttribute 使您可以访问旋钮和控制杆来指定传入和传出消息的元素名称和命名空间。

这应该会让您非常接近:

<%@
  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")> _
                                                       ByVal fullServiceAddressCorrectionNotification As String) _
              As  <XmlElement("FullServiceNixieDetailNotificationResponse")> NixieResponse

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

        Return r

    End Function

End Class

我必须将其标记为 ParameterStyle = Bare,因为传入消息有 2 个顶级元素。这意味着传出的消息也是裸露的,在您的情况下这不是您想要的。因此,传出的消息只是一个字符串 - 我必须将其包装到一个结构中,以便获得您显示的形状。

我已经评论了传入和传出消息的设计。如果消息设计更加“理智”,那么其中一些扭曲就没有必要。

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")> _
                                                       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".

琉璃繁缕 2024-08-22 04:23:33

根据 XMLspy,您的版本是正确的。这是它生成的请求:

<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">
    <SOAP-ENV:Body>
        <m:AuthenticationInfo 
            xmlns:m="http://www.usps.com/postalone/services/UserAuthenticationSchema">
            <UserId>String</UserId>
            <UserPassword>String</UserPassword>
        </m:AuthenticationInfo>
        <m2:fullServiceNixieDetailQuery 
            xmlns:m2="http://www.usps.com/postalone/services/POAppointmentServices20">
            String
        </m2:fullServiceNixieDetailQuery>
    </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

请注意,身份验证“标头”和查询位于两个不同的命名空间中。

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">
    <SOAP-ENV:Body>
        <m:AuthenticationInfo 
            xmlns:m="http://www.usps.com/postalone/services/UserAuthenticationSchema">
            <UserId>String</UserId>
            <UserPassword>String</UserPassword>
        </m:AuthenticationInfo>
        <m2:fullServiceNixieDetailQuery 
            xmlns:m2="http://www.usps.com/postalone/services/POAppointmentServices20">
            String
        </m2:fullServiceNixieDetailQuery>
    </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文