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

.NET6 SoapCore XmlSerializer下CancellationToken致WSDL生成失败

.NET 6 SoapCore XmlSerializer模式下CancellationToken导致WSDL生成异常问题

问题表现

  • 环境为.NET 6,引用SoapCore NuGet包搭建异步WCF服务,序列化器配置为SoapSerializer.XmlSerializer。给标记[OperationContract]特性的异步服务方法添加CancellationToken参数后,访问WSDL地址https://localhost:7026/Services.svc?WSDL抛出异常:ArgumentException: .NET type CancellationToken cannot be resolved into XML schema type。
  • 异常原因:System.Threading.CancellationToken是System命名空间下的值类型,被SoapCore识别为与bool、int、long同类的基础类型,生成XML架构映射时无法匹配对应XML架构类型,最终触发异常。
  • 已尝试的无效方案:给CancellationToken参数添加[XmlIgnore]特性未生效;[MessageContract(IsWrapped = false)]特性无法直接应用于方法参数,无法绕过该问题。[XmlIgnore]无效的根因是SoapCore在XmlSerializer模式下生成WSDL时,会先遍历操作方法的所有参数判断是否需要生成对应XML架构,该逻辑既没有识别[XmlIgnore]特性做跳过处理,也没有内置将CancellationToken作为运行时注入参数排除。
  • 替代方案的缺陷:切换序列化器为SoapSerializer.DataContractSerializer可正常运行,但生成的WSDL会枚举大量未使用的基础类型,文档冗余度高,不符合使用需求。

复现代码

Program.cs

using Microsoft.Extensions.DependencyInjection.Extensions;
using SoapCore;

namespace TestSoapCore;

public static class Program
{
    public static void Main(string[] args)
    {
        var builder = WebApplication.CreateBuilder(args);
        builder.Services.AddSoapCore();
        builder.Services.TryAddSingleton<MyService>();
        builder.Services.AddMvc();

        var app = builder.Build();
        app.UseRouting();
        app.UseEndpoints(endpoints =>
        {
            endpoints.UseSoapEndpoint<MyService>(
                "/Services.svc",
                new SoapEncoderOptions(),
                SoapSerializer.XmlSerializer
                // 切换为SoapSerializer.DataContractSerializer可正常运行,但优先选择XmlSerializer
            );
        });
        app.Run();
    }
}

Contract.cs

using System.Runtime.Serialization;

namespace TestSoapCore;

[DataContract]
public class Contract {
    [DataMember]
    public string? TestProperty { get; set; }
}

MyService.cs

using System.ServiceModel;
using System.Xml.Serialization;

namespace TestSoapCore;

[ServiceContract]
public class MyService
{
    [OperationContract]
    public async Task<string> Test(
        Contract contract,
        // [MessageContract(IsWrapped = false)] 无法应用于参数
        [XmlIgnore] // 该特性未生效
        CancellationToken cancellationToken)
    {
        cancellationToken.ThrowIfCancellationRequested();

        return contract?.TestProperty + "2";
    }
}

已验证结论

  • 移除方法的CancellationToken参数后,XmlSerializer模式下可正常生成精简无冗余的WSDL
  • DataContractSerializer模式下服务可正常运行,但WSDL包含大量无用基础类型定义,不符合预期

可行解决方案

核心逻辑:CancellationToken属于服务运行时注入的参数,不属于SOAP消息契约的一部分,本就不该出现在WSDL定义中。通过分离服务契约与实现类,将CancellationToken参数从WSDL生成扫描的契约定义中移除,同时保留SoapCore运行时自动注入取消令牌的能力。

  1. 定义独立的服务契约接口,接口中标记服务契约与操作契约,操作方法不声明CancellationToken参数,作为WSDL生成的依据:
using System.ServiceModel;
using System.Threading.Tasks;

namespace TestSoapCore;

[ServiceContract]
public interface IMyService
{
    [OperationContract]
    Task<string> Test(Contract contract);
}
  1. 编写服务实现类,继承上述契约接口,实现操作方法时额外添加CancellationToken类型参数。SoapCore调用方法时,会自动从当前请求上下文获取HttpContext.RequestAborted取消令牌,传入该参数,不需要额外配置绑定:
using System.Threading;
using System.Threading.Tasks;

namespace TestSoapCore;

public class MyService : IMyService
{
    public async Task<string> Test(
        Contract contract,
        CancellationToken cancellationToken)
    {
        cancellationToken.ThrowIfCancellationRequested();
        return contract?.TestProperty + "2";
    }
}
  1. 修改Program.cs中的服务注册与端点配置,将服务注册为接口与实现的映射,端点泛型参数指定为服务契约接口类型:
using Microsoft.Extensions.DependencyInjection.Extensions;
using SoapCore;

namespace TestSoapCore;

public static class Program
{
    public static void Main(string[] args)
    {
        var builder = WebApplication.CreateBuilder(args);
        builder.Services.AddSoapCore();
        // 注册契约接口与实现类的映射
        builder.Services.TryAddSingleton<IMyService, MyService>();
        builder.Services.AddMvc();

        var app = builder.Build();
        app.UseRouting();
        app.UseEndpoints(endpoints =>
        {
            // 端点指定契约接口类型
            endpoints.UseSoapEndpoint<IMyService>(
                "/Services.svc",
                new SoapEncoderOptions(),
                SoapSerializer.XmlSerializer
            );
        });
        app.Run();
    }
}

调整后可同时满足三个核心诉求:

  • 保留CancellationToken的请求取消能力,运行时可正常接收取消信号
  • 继续使用XmlSerializer序列化器,生成的WSDL精简无冗余类型
  • 访问WSDL地址不会抛出类型解析异常

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 13:12:18