从SSv6.x迁移至SS8.x后ServiceStack ValidationRules不生效问题
问题描述
我们有一个基于.NET 6、ServiceStack 6.x的项目,使用AutoQuery生成DTO并通过运行x csharp命令保存到项目中,示例DTO如下:
[Route("/vehicles", "GET")] [Route("/vehicles/{Id}", "GET")] [DataContract] public class QueryVehicles : QueryDb<Vehicle>, IReturn<QueryResponse<Vehicle>>, IGet { [DataMember(Order = 1)] public long? Id { get; set; } } [Route("/vehicletypes", "GET")] [Route("/vehicletypes/{Id}", "GET")] [DataContract] public class QueryVehicleTypes : QueryDb<VehicleType>, IReturn<QueryResponse<VehicleType>>, IGet { [DataMember(Order = 1)] public long? Id { get; set; } }
我们通过ValidationRule表配置动态验证规则,上述两个DTO需应用IsAuthenticated规则。
该配置在.NET6/SS6.x中运行正常,但迁移至.NET8/SS8.2.2后,IsAuthenticated验证规则不再生效,未登录即可查询这些端点。
有趣的是,我们重写了部分AutoQuery服务(如下示例),这类端点的IsAuthenticated ValidationRule是生效的:
public class CompaniesService : Service { public IAutoQueryDb AutoQuery { get; set; } public IDbConnectionFactory ConnectionFactory { get; set; } public CompaniesService(IDbConnectionFactory dbConnectionFactory) { ConnectionFactory = dbConnectionFactory; } public async Task<object> Any(QueryCompanies query) { using var db = AutoQuery.GetDb(query, base.Request); var q = AutoQuery.CreateQuery(query, base.Request, db); if (query.CompanyTypeId.HasValue) { var session = await SessionAsAsync<SeritiUserSession>(); q = q .Join<CompanyCompanyTypeMapping>() .Where<CompanyCompanyTypeMapping>(x => x.CompanyTypeId == query.CompanyTypeId) .Where<Company>(x => x.CountryId == session.CountryId); var implicitJoin = db.Select(q); return await AutoQuery.ExecuteAsync(query, q, base.Request, db); } else { return await AutoQuery.ExecuteAsync(query, q, base.Request, db); } } }
请问这是什么原因导致的?
原因分析
这是ServiceStack 8.x对AutoQuery内置服务的验证规则应用逻辑做了调整导致的:
- 在ServiceStack 6.x中,通过
ValidationRule表配置的动态验证规则会自动应用到所有匹配的请求DTO,包括AutoQuery生成的QueryDb类对应的内置AutoQuery服务。 - 而ServiceStack 8.x中,为了优化AutoQuery的默认性能,内置AutoQuery服务默认不再自动应用全局/动态配置的
ValidationRule,仅当请求DTO对应自定义服务(即你重写的CompaniesService这类手动实现的服务)时,才会触发动态验证规则的校验。
简单来说,直接继承QueryDb但未手动实现服务类的AutoQuery内置通用服务,在SS8中默认跳过了动态ValidationRule的校验;而手动实现的服务类因为走标准Service请求处理流程,所以依然会正常应用验证规则。
解决办法
要让AutoQuery内置服务也应用动态ValidationRule,可选择以下方式处理:
- 全局启用AutoQuery验证:在AppHost配置
AutoQueryFeature时开启ValidateAutoQueryRequests选项:
Plugins.Add(new AutoQueryFeature { ValidateAutoQueryRequests = true });
该配置会让AutoQuery内置服务重新启用对全局/动态ValidationRule的校验。
- 给DTO添加强制验证特性:直接在AutoQuery生成的DTO类上添加
[Validate]特性,强制触发验证规则:
[Route("/vehicles", "GET")] [Route("/vehicles/{Id}", "GET")] [DataContract] [Validate] // 添加此特性 public class QueryVehicles : QueryDb<Vehicle>, IReturn<QueryResponse<Vehicle>>, IGet { [DataMember(Order = 1)] public long? Id { get; set; } }
- 手动实现AutoQuery服务:类似
CompaniesService,为每个AutoQuery DTO创建对应的服务类,自动走标准服务验证流程,动态规则会正常生效。
内容的提问来源于stack exchange,提问作者Shawn de Wet
相关产品推荐
相关产品推荐

