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(); } } }
问题原因分析
- 序列化标记缺失:
ApiResponse类未标记[DataContract]和[DataMember],SOAP的DataContractSerializer无法正确序列化该类,导致返回空白。 - 必填校验拦截:RequestModel的属性标记了
[Required],空请求时校验失败抛出异常,但异常返回的响应未被正确序列化。 - 默认值未生效:SOAP序列化器创建的RequestModel实例不会触发C#属性的默认赋值,空请求时属性值为默认类型值而非预设的模拟数据。
- 类型不匹配:仓储返回泛型
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
相关产品推荐
相关产品推荐

