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

ASP.NET Core基于SoapCore的SOAP服务返回空白问题求助

问题场景

我在ASP.NET Core Web API中使用SoapCore包构建SOAP Web服务。期望提交请求时,即使未输入任何数据,服务也能返回RequestModel中设置的默认模拟数据,但在SOAP UI中测试时返回空白页面,寻求解决办法。

现有代码结构

请求模型

[DataContract]
public class RequestModel
{
    [DataMember]
    [Required]
    public decimal Amount { get; set; } = 88766.543233m;

    [DataMember]
    [Required]
    public string FirstName { get; set; } = "String content";

    [DataMember]
    [Required]
    public string LastName { get; set; } = "String content";
}

响应模型

[DataContract]
public class ResponseModel
{
    [DataMember]
    public decimal Amount { get; set; } = 88766.543233m;

    [DataMember]
    public string FirstName { get; set; } = "String content";

    [DataMember]
    public string LastName { get; set; } = "String content";
}

API响应类

public class ApiResponse
{
    public string ResponseCode { get; set; }
    public string ResponseDescription { get; set; }
    public string Message { get; set; }
    public ResponseModel Response { get; set; } // 新增属性

    public static ApiResponse Success(ResponseModel response, string message = "请求处理成功")
    {
        return new ApiResponse
        {
            ResponseCode = "200",
            ResponseDescription = "成功",
            Message = message
        };
    }
    public static ApiResponse Failure(string message)
    {
        return new ApiResponse
        {
            ResponseCode = "500",
            ResponseDescription = "失败",
            Message = message
        };
    }
}

仓储实现(SoapRepository)

public class SoapRepository : ISoapRepository
{
    public Task<ApiResponse<ResponseModel>> ProcessRequest(RequestModel request)
    {
        try
        {
            var validationContext = new ValidationContext(request);
            Validator.ValidateObject(request, validationContext, validateAllProperties: true);
            var processedResponse = new ResponseModel
            {
                Amount = request.Amount,
                FirstName = request.FirstName,
                LastName = request.LastName
            };
            return Task.FromResult(ApiResponse<ResponseModel>.Success(processedResponse));
        }
        catch (ValidationException ex)
        {
            return Task.FromResult(ApiResponse<ResponseModel>.Failure(ex.Message));
        }
        catch (Exception ex)
        {
            return Task.FromResult(ApiResponse<ResponseModel>.Failure(ex.Message));
        }
    }
}

服务实现(SoapProcessingService)

public class SoapProcessingService : ISoapProcessingService
{
    private readonly ISoapRepository _requestRepository;
    public SoapProcessingService(
        ISoapRepository requestRepository
        )
    {
        _requestRepository = requestRepository;
    }
    public async Task<ApiResponse> ProcessRequests(RequestModel request)
    {
        try
        {
            var response = await _requestRepository.ProcessRequest(request);
            return response;

        }
        catch (Exception ex)
        {
            return ApiResponse.Failure(ex.Message);
        }
    }
}

Program.cs配置

using SoapCore;
using SoapService.Api.Repositories.Implementations;
using SoapService.Api.Repositories.Interfaces;
using SoapService.Api.Services.Implementations;
using SoapService.Api.Services.Interfaces;

namespace SoapService.Api
{
    public class Program
    {
        public static async Task Main(string[] args)
        {
            var host = Host.CreateDefaultBuilder(args)
                .ConfigureWebHostDefaults(webBuilder =>
                {
                    webBuilder.ConfigureServices((context, services) =>
                    {
                        services.AddSingleton<ISoapRepository, SoapRepository>();
                        services.AddTransient<ISoapProcessingService, SoapProcessingService>();
                    });

                    webBuilder.Configure(app =>
                    {
                        // 配置SOAPCore中间件
                        app.UseSoapEndpoint<ISoapProcessingService>("/SoapService", new SoapEncoderOptions(), SoapSerializer.DataContractSerializer);

                        // 处理默认路由
                        app.Run(async (context) =>
                        {
                            await context.Response.WriteAsync("SOAP Web Service 运行中。");
                        });
                    });
                })
                .Build();

            await host.RunAsync();
        }
    }
}
问题原因分析
  1. 序列化标记缺失:ApiResponse类未标记[DataContract]和[DataMember],SOAP的DataContractSerializer无法正确序列化该类,导致返回空白。
  2. 必填校验拦截:RequestModel的属性标记了[Required],空请求时校验失败抛出异常,但异常返回的响应未被正确序列化。
  3. 默认值未生效:SOAP序列化器创建的RequestModel实例不会触发C#属性的默认赋值,空请求时属性值为默认类型值而非预设的模拟数据。
  4. 类型不匹配:仓储返回泛型ApiResponse<ResponseModel>,但服务返回非泛型ApiResponse,存在类型转换问题。
解决方案步骤

步骤1:修复ApiResponse的序列化标记

给ApiResponse添加SOAP序列化所需的标记,并补全Success方法的Response属性赋值:

[DataContract]
public class ApiResponse
{
    [DataMember]
    public string ResponseCode { get; set; }
    [DataMember]
    public string ResponseDescription { get; set; }
    [DataMember]
    public string Message { get; set; }
    [DataMember]
    public ResponseModel Response { get; set; }

    public static ApiResponse Success(ResponseModel response, string message = "请求处理成功")
    {
        return new ApiResponse
        {
            ResponseCode = "200",
            ResponseDescription = "成功",
            Message = message,
            Response = response // 补全属性赋值
        };
    }
    public static ApiResponse Failure(string message)
    {
        return new ApiResponse
        {
            ResponseCode = "500",
            ResponseDescription = "失败",
            Message = message,
            Response = null
        };
    }
}

步骤2:统一ApiResponse的类型定义

删除泛型版本的ApiResponse,修改仓储接口和实现,确保返回类型与服务一致:

// 修改ISoapRepository接口
public interface ISoapRepository
{
    Task<ApiResponse> ProcessRequest(RequestModel request);
}

// 修改SoapRepository实现
public class SoapRepository : ISoapRepository
{
    public Task<ApiResponse> ProcessRequest(RequestModel request)
    {
        try
        {
            // 为空请求填充默认值
            if (request.Amount == default)
                request.Amount = 88766.543233m;
            if (string.IsNullOrEmpty(request.FirstName))
                request.FirstName = "String content";
            if (string.IsNullOrEmpty(request.LastName))
                request.LastName = "String content";

            var validationContext = new ValidationContext(request);
            Validator.ValidateObject(request, validationContext, validateAllProperties: true);
            
            var processedResponse = new ResponseModel
            {
                Amount = request.Amount,
                FirstName = request.FirstName,
                LastName = request.LastName
            };
            return Task.FromResult(ApiResponse.Success(processedResponse));
        }
        catch (ValidationException ex)
        {
            return Task.FromResult(ApiResponse.Failure(ex.Message));
        }
        catch (Exception ex)
        {
            return Task.FromResult(ApiResponse.Failure(ex.Message));
        }
    }
}

步骤3:完善SOAP服务接口标记

给服务接口添加SOAP必需的契约标记:

[ServiceContract]
public interface ISoapProcessingService
{
    [OperationContract]
    Task<ApiResponse> ProcessRequests(RequestModel request);
}

步骤4:测试验证

重启服务后,在SOAP UI中发送仅包含信封结构的空请求,服务会自动填充预设的默认模拟数据,并返回正常序列化的响应。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 21:24:59