如何更改ASP.NET Webservice的WebMethod XML输出,特别是名称空间声明?

时间:2013-11-14 09:59:17

标签: c# asp.net xml web-services

我正在为给定的客户端开发ASP.NET Web服务(而不是WCF)。这是其中一种情况,您无法在客户端进行任何更改。

客户端发送以下XML以请求方法:

<?xml version="1.0" encoding="UTF-8"?>
<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"
                   xmlns:cometxsd="http://werk-ii.de/soap/comet/Schema"
                   xmlns:comet="http://werk-ii.de/soap/comet"
                   xmlns:xop="http://www.w3.org/2004/08/xop/include"
                   xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing"
                   xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
                   xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
                   xmlns:xmime5="http://www.w3.org/2005/05/xmlmime"
                   xmlns:ns1="http://soap.comet.werkii.com/">
  <SOAP-ENV:Body>
    <ns1:login xsi:type="ns1:login">
      <user>myusername</user>
      <password>mypassword</password>
      <client>whatever</client>
      <language>de</language>
    </ns1:login>
  </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

我的服务提供了这样的登录方法:

[WebService(Namespace = "http://soap.comet.werkii.com/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.ComponentModel.ToolboxItem(false)]
public class CometService : WebService
{
    [WebMethod(MessageName = "login")]
    [return: XmlElement("return")]
    public LoginResult Login (string user, string password, string client, string language)
    {
        return new LoginResult() {
            ResultCode = 0,
            SessionId = user + "-" + password + "-" + client + "-" + language
        };
    }
}

public class LoginResult
{
    [XmlElement("resultCode")]
    public int ResultCode { get; set; }

    [XmlElement("sessionId")]
    public string SessionId { get; set; }
}

如果我启动该服务,它会告诉我作为请求我必须发送什么SOAP 1.1代码,即:

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Body>
    <login xmlns="http://soap.comet.werkii.com/">
      <user>string</user>
      <password>string</password>
      <client>string</client>
      <language>string</language>
    </login>
  </soap:Body>
</soap:Envelope>

当我使用这个代码 - 正如服务所说 - 来自另一个测试客户端(我在PHP中编写一个)时,一切正常,我得到了一个结果。但是当我从头开始发送代码时(这是真正的客户端将发送的代码),调用该方法,但所有4个参数都为null

从XML视图来看,在我看来两个请求都是一样的。唯一的区别是,定义了命名空间,以及元素是否使用ns1前缀。当服务将其作为XML读取时,这应该没有任何区别。也许我错了。

第一个XML中的4个参数可能与方法(ns1)具有不同的命名空间(无)。这可能是所有参数都为空的原因吗?我如何仅更改参数的命名空间?

当我仅更改XML中的方法行时 - 将<ns1:login xsi:type="ns1:login">替换为<login xmlns="http://soap.comet.werkii.com/">以及结束标记 - 它可以正常工作!因此,如果方法元素使用名称空间前缀,服务似乎不理解我的请求,尽管在根元素中正确定义了名称空间。

我尝试了以下方法来更改服务所需的XML格式:

  • System.Web.Services.Protocols.SoapDocumentMethodAttribute - 完全没有效果
  • XmlNamespaceDeclarationsAttribute如图所示here - 这似乎不起作用,因为它是为了操纵复杂类型而不是服务类或方法

所以问题是,如何告诉我的服务接受第一个示例中的XML?

1 个答案:

答案 0 :(得分:1)

很高兴知道参数也可以有属性:

public LoginResult Login (
    [XmlElement(Namespace = "")] string user,
    [XmlElement(Namespace = "")] string password,
    [XmlElement(Namespace = "")] string client,
    [XmlElement(Namespace = "")] string language)
{
    return new LoginResult() {
        ResultCode = 0,
        SessionId = user + "-" + password + "-" + client + "-" + language
    };
}

这是将参数放入全局命名空间的解决方案 - 解决了问题。