You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C#实现带自定义字段的WSSE安全SOAP请求时遇运行时错误

解决WSSE UsernameToken带自定义字段的SOAP服务调用问题

你现在遇到的是调用带WSSE身份验证(还包含自定义字段CustomField)的SOAP服务时的两个核心问题:一是WSE代理类调用时的空引用错误,二是服务端返回的SoapHeaderException(MustUnderstand头未被处理),同时Blue Prism原生不支持SOAP头,给实现增加了难度。先看你提供的示例SOAP请求:

<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生成代理类后,遇到的具体错误:

  • Blue Prism中运行时出现Object reference not set to an instance of an object.,定位到mWebService.RequestSoapContext.Security.Tokens.Add(token);这行
  • Visual Studio控制台程序中出现SoapHeaderException: MustUnderstand headers:[{http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd}Security] are not understood

错误原因分析

  1. 空引用错误:RequestSoapContext未被初始化,通常是因为WSE的配置未正确启用,导致代理类没有创建SOAP上下文对象;另外,WSE默认的UsernameToken类不包含服务端要求的CustomField,这也可能引发后续异常。
  2. MustUnderstand头错误:服务端要求Security头必须被客户端正确处理,但你的代理类没有启用WSE的SOAP扩展来识别WSSE头,导致框架无法解析这个头从而抛出异常。
  3. Blue Prism限制:Blue Prism原生SOAP工具不支持自定义SOAP头,必须通过自定义代码构造完整请求。

解决方案

一、修正WSE代理类的配置(VS环境)

确保项目的app.config/web.config中添加WSE 3.0的必要配置,启用SOAP扩展:

<configuration>
  <configSections>
    <section name="microsoft.web.services3" type="Microsoft.Web.Services3.Configuration.WebServicesConfiguration, Microsoft.Web.Services3, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
  </configSections>
  <microsoft.web.services3>
    <security>
      <tokenIssuer>
        <add URI="http://webservice.com" />
      </tokenIssuer>
    </security>
    <soapServerProtocolFactory type="Microsoft.Web.Services3.WseProtocolFactory, Microsoft.Web.Services3, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
  </microsoft.web.services3>
  <system.web>
    <webServices>
      <soapExtensionImporterTypes>
        <add type="Microsoft.Web.Services3.Description.WseExtensionImporter, Microsoft.Web.Services3, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
      </soapExtensionImporterTypes>
      <soapServerProtocolFactory type="Microsoft.Web.Services3.WseProtocolFactory, Microsoft.Web.Services3, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
    </webServices>
  </system.web>
</configuration>

二、自定义UsernameToken类以支持CustomField

WSE默认的UsernameToken不包含CustomField,需要继承并重写方法添加该字段:

using System.Xml;
using Microsoft.Web.Services3.Security;
using Microsoft.Web.Services3.Security.Tokens;

public class CustomUsernameToken : UsernameToken
{
    public string CustomField { get; set; }

    public CustomUsernameToken(string username, string customField, PasswordOption passwordOption) 
        : base(username, string.Empty, passwordOption) // 你的示例中无Password字段,故传空
    {
        CustomField = customField;
    }

    protected override void WriteTokenXml(XmlWriter writer)
    {
        base.WriteTokenXml(writer);
        // 写入自定义字段
        writer.WriteStartElement("CustomField", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd");
        writer.WriteString(CustomField);
        writer.WriteEndElement();
    }
}

三、修正VS控制台程序的调用代码

使用自定义CustomUsernameToken,确保SOAP上下文正确初始化:

// 初始化代理类
var mWebService = new YourWebServiceProxy();

// 确保WSE上下文已启用(配置正确后通常无需手动初始化)
if (mWebService.RequestSoapContext == null)
{
    mWebService.RequestSoapContext = new SoapContext();
}

// 创建自定义身份令牌
var customToken = new CustomUsernameToken("abc", "123", PasswordOption.SendPlainText);
mWebService.RequestSoapContext.Security.Tokens.Add(customToken);

// 构造请求参数
queryNoSorguType q = new queryNoSorguType();
q.queryNo = "12345678901";

// 调用服务
ResultType[] r = mWebService.documentQuerybyQueryNo(q);

// 处理结果到DataTable
System.Data.DataTable outputDataTable = new System.Data.DataTable();
foreach (var result in r)
{
    var row = outputDataTable.NewRow();
    row["field1"] = result.Field1; // 替换为ResultType的实际字段名
    outputDataTable.Rows.Add(row);
}
var output = outputDataTable;

四、Blue Prism中的实现方案

由于Blue Prism原生不支持SOAP头,推荐用**C#代码阶段(Code Stage)**直接构造完整SOAP请求并发送HTTP请求:

  1. 创建Code Stage,设置输入参数:username(文本)、customField(文本)、queryNo(文本)、serviceUrl(文本);输出参数:responseXml(文本)、errorMessage(文本)。
  2. 在Code Stage中编写以下代码:
using System;
using System.Net;
using System.Text;
using System.Xml;

public class Script
{
    public static void Main(string username, string customField, string queryNo, string serviceUrl, out string responseXml, out string errorMessage)
    {
        responseXml = string.Empty;
        errorMessage = string.Empty;
        try
        {
            // 构造完整SOAP请求
            string soapRequest = $@"
<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>{username}</wsse:Username>
        <wsse:CustomField>{customField}</wsse:CustomField>
      </wsse:UsernameToken>
    </wsse:Security>
  </soapenv:Header>
  <soapenv:Body>
    <kas:method1>
      <method1>
        <queryNo>{queryNo}</queryNo>
      </method1>
    </kas:method1>
  </soapenv:Body>
</soapenv:Envelope>";

            // 发送HTTP请求
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(serviceUrl);
            request.Method = "POST";
            request.ContentType = "text/xml;charset=utf-8";
            request.Headers.Add("SOAPAction", "\"http://webservice.com/method1\""); // 替换为实际SOAPAction

            // 写入请求内容
            using (var stream = request.GetRequestStream())
            {
                byte[] buffer = Encoding.UTF8.GetBytes(soapRequest);
                stream.Write(buffer, 0, buffer.Length);
            }

            // 获取响应
            using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
            {
                using (var reader = new XmlTextReader(response.GetResponseStream()))
                {
                    responseXml = reader.ReadOuterXml();
                }
            }
        }
        catch (Exception ex)
        {
            errorMessage = ex.ToString();
        }
    }
}
  1. 配置输入输出映射后,即可在Blue Prism流程中调用该Code Stage,后续可使用Blue Prism的XML工具解析responseXml得到结果。

内容的提问来源于stack exchange,提问作者Vesnog

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 07:14:47