代码之家  ›  专栏  ›  技术社区  ›  Vesnog

在SOAP请求中使用自定义字段实现WSSE安全头时发生C#运行时错误

  •  4
  • Vesnog  · 技术社区  · 7 年前

    我想寄封信 SOAP请求 到使用 WSSE 以及用于身份验证的UsernameToken。示例查询如下(屏蔽机密数据):

    <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:kas="http://webservice.com">
            <soapenv:Header>
          <wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
             <wsse:UsernameToken>
                <wsse:Username>abc</wsse:Username>
                <wsse:CustomField>123</wsse:CustomField>
             </wsse:UsernameToken>
          </wsse:Security>
       </soapenv:Header>
       <soapenv:Body>
          <kas:method1>
             <!--Optional:-->
             <method1>
                <!--Optional:-->
                <queryNo>12345678901</queryNo>
             </method1>
          </kas:method1>
       </soapenv:Body>
    </soapenv:Envelope> 
    

    我已经使用 WSE 3.0 问题是我得到了错误:“对象引用未设置为对象的实例。”我的C#代码有问题的部分如下:

    queryNoSorguType q = new queryNoSorguType();
    string query_parameter = query_no;
    q.queryNo = query_parameter;
    
    ResultType[] r = new ResultType[10];
    
    UsernameToken token = new UsernameToken("abc", "123",PasswordOption.SendPlainText);
    //mWebService.SetClientCredential<UsernameToken>(token);
    //Policy webServiceClientPolicy = new Policy();
    mWebService.RequestSoapContext.Security.Tokens.Add(token);
    //mWebService.SetPolicy(webServiceClientPolicy);
    
    //r = mWebService.documentQuerybyQueryNo(q);
    
    System.Data.DataTable outputDataTable = new System.Data.DataTable();
    //System.Data.DataRow outRow = outputDataTable.Rows.Add();
    //outRow["field1"] = r;
    output = outputDataTable;
    

    我通过系统地注释代码中的部分内容,找到了有问题的部分。我对web服务非常不熟悉,C#实际上我是在 蓝色棱镜 。尽管该程序可以使用现成的SOAP web服务,但不幸的是,它本机不支持SOAP头。

    SOAP请求在应用程序中运行良好 SOAP用户界面 Blue Prism中没有编译器错误。我试着按照手册和网络上的说明添加标题,但没有成功。如果你能给我指出正确的方向,我将不胜感激。

    编辑 在Visual Studio 2017中编写控制台应用程序后,我发现以下错误。据我所知,它没有标题的定义。

    Unhandled Exception: System.Web.Services.Protocols.SoapHeaderException: MustUnderstand headers:[{http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd}Security] are not understood
       at System.Web.Services.Protocols.SoapHttpClientProtocol.ReadResponse(SoapClientMessage message, WebResponse response, Stream responseStream, Boolean asyncCall)
       at System.Web.Services.Protocols.SoapHttpClientProtocol.Invoke(String methodName, Object[] parameters)
       at WebService.queryByQueryNo(queryNoQueryType queryByQueryNo1) in C:\Users\user\source\repos\ConsoleApp1\ConsoleApp1\Web References\WebService\Reference.cs:line 1533
       at ConsoleApp1.Program.Main(String[] args) in C:\Users\user\source\repos\ConsoleApp1\ConsoleApp1\Program.cs:line 33
    
    2 回复  |  直到 7 年前
        1
  •  1
  •   Emiliano    7 年前

    我认为xml结构会准时出现在标题中吗 当你使用

    <wsse:Security wsse没有定义,我知道您在同一行中定义了wsse,但为什么不尝试将其放在文档中,类似这样的内容

    <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:kas="http://webservice.com" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
       <soapenv:Header>
          <wsse:Security>
             <wsse:UsernameToken>
                <wsse:Username>abc</wsse:Username>
                <wsse:CustomField>123</wsse:CustomField>
             </wsse:UsernameToken>
          </wsse:Security>
       </soapenv:Header>
    
        2
  •  1
  •   SteveC    5 年前

    我决定使用另一种方法,暂时停止尝试使用代理类,因为存在与之相关的问题。利用此链接上的答案: Client to send SOAP request and receive response 经过一些定制,我想出了自己的解决方案。

    然而,我仍然想知道如何继续,以使其工作使用 包装类 由Visual Studio或WSE 3.0定义。在编写代码并在VisualStudio中进行测试之后,将其移植到Blue Prism中非常容易。

    using System;
    using System.Collections.Generic;
    using System.Data;
    using System.Text;
    using System.Threading.Tasks;
    using System.Xml;
    using System.Net;
    using System.IO;
    using System.Xml.Linq;
    namespace WebService
    {
        class Program
        {
            /// <summary>
            /// Execute a Soap WebService call
            /// </summary>
            public static string Execute(string queryNo)
            {
                HttpWebRequest request = CreateWebRequest();
                XmlDocument soapEnvelopeXml = new XmlDocument();
                soapEnvelopeXml.LoadXml(@"<?xml version=""1.0"" encoding=""utf-8""?>
                    <soapenv:Envelope xmlns:soapenv=""http://schemas.xmlsoap.org/soap/envelope/"" xmlns:customNAMESPACE=""http://webservice.com"">
                    <soapenv:Header>
                        <wsse:Security xmlns:wsse=""http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"">
                            <wsse:UsernameToken>
                                <wsse:Username>USER</wsse:Username>
                                <wsse:CustomField>CODE</wsse:CustomField>
                            </wsse:UsernameToken>
                         </wsse:Security>
                      </soapenv:Header>
                      <soapenv:Body>
                         <customNAMESPACE:QueryByQueryNo>
                            <!--Optional:-->
                            <QueryByQueryNo>
                                <!--Optional:-->
                                <queryNo>" + queryNo + @"</queryNo>
                            </QueryByQueryNo>
                          </customNAMESPACE:QueryByQueryNo>
                      </soapenv:Body>
                    </soapenv:Envelope>");
    
                using (Stream stream = request.GetRequestStream())
                {
                    soapEnvelopeXml.Save(stream);
                }
    
                using (WebResponse response = request.GetResponse())
                {
                    using (StreamReader rd = new StreamReader(response.GetResponseStream()))
                    {
                        string soapResult = rd.ReadToEnd();
                        Console.WriteLine(soapResult);
                        return soapResult;
                    }
                }
            }
            /// <summary>
            /// Create a soap webrequest to [Url]
            /// </summary>
            /// <returns></returns>
            public static HttpWebRequest CreateWebRequest()
            {
                HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(@"https://webservice.com/webservice?wsdl");
                webRequest.Headers.Add(@"SOAP:Action");
                webRequest.ContentType = "text/xml;charset=\"utf-8\"";
                webRequest.Accept = "text/xml";
                webRequest.Method = "POST";
                return webRequest;
            }
            static void Main(string[] args)
            {
                if (args.Length == 0 || args.Length > 1)
                {
                    System.Console.WriteLine("Please provide a query no");
                    System.Console.WriteLine("Usage: WebService.exe 3523423333");
                    return;
                }
    
                string output, XMLresponse;
                try
                {
                    XMLresponse = Execute(args[0]);
                    output = "Successful query";
                    XmlDocument xml = new XmlDocument();
                    xml.LoadXml(XMLresponse);  // suppose that str string contains the XML data. You may load XML data from a file too.
                    XmlNodeList resultCodeList = xml.GetElementsByTagName("resultCode");
                    XmlNodeList resultNoList = xml.GetElementsByTagName("resultNo");
                    int i = 0;
                    var OutputTable = new DataTable();
                    OutputTable.Columns.Add("Result Code", typeof(string));
                    OutputTable.Columns.Add("Result No", typeof(string));
                    foreach (XmlNode xn in resultCodeList)
                    {
                        Console.WriteLine(resultCodeList[i].InnerText + "  " + resultNoList[i].InnerText);
                        OutputTable.Rows.Add(resultCodeList[i].InnerText, resultNoList[i].InnerText);
                        i++;
                    }
    
                }
                catch (System.Net.WebException exc)
                {
                    Console.WriteLine("HTTP POST request failed!");
                    output = "!!!HTTP POST request failed!!!";
                }
            }
        }
    }