在validation器中访问Servicstack.net会话
如何在validation代码中访问ServiceStack.net会话?
public class UserSettingsValidator : AbstractValidator { public UserSettingsValidator() { RuleFor(x => x.UserId) .SetValidator(new PositiveIntegerValidator()) .SetValidator(new UserAccessValidator(session.UserId)); //<-- I need to pass the UserID from the session here } }
在服务实现中,我只是这样做:
var session = base.SessionAs();
但这对我的抽象validation器不起作用。
谢谢!
编辑:这是版本3.9.71.0
我假设您正在使用ValidationFeature
插件,就像大多数人一样。 如果是这样,那么我认为不可能。 最终, ValidationFeature
是一个使用RequestFilter
的插件。
我之前想做类似的事情,然后意识到这是不可能的。
RequestFilter
在ServiceRunner
之前运行。 请参阅此处的操作顺序指南 。
这对您来说意味着您的填充请求DTO到达您的服务,validationfunction的请求filter将尝试validation您的请求,甚至在创建ServiceRunner
。
ServiceRunner
是服务类实例变为活动状态的位置。 它是您的UserSession
对象注入的服务类实例。
因此,您无法在此时执行任何依赖会话的validation。
过于复杂?:
可以在服务方法中进行validation,并且可以创建一个自定义对象,允许您将会话与要validation的对象一起传递。 (见下一节)。 但我会问你自己,你的validation过于复杂吗?
对于匹配会话的UserId
的请求UserId
的简单检查,可能是你这样做,所以用户只能对自己的记录进行更改; 为什么不检查服务的操作方法并抛出Exception
? 我猜人们不应该改变这个Id,所以它不是一个validation问题,而是更多的安全例外。 但就像我说的,也许你的情况有所不同。
public class SomeService : Service { public object Post(UserSettingsRequest request) // Match to your own request { if(request.UserId != Session.UserId) throw new Exception("Invalid UserId"); } }
服务行动中的validation:
您应该阅读使用Fluentvalidation器 。 您可以在服务方法中自行调用自定义validation器。
// This class allows you to add pass in your session and your object public class WithSession { public UserSession Session { get; set; } public T Object { get; set; } } public interface IUserAccessValidator { bool ValidUser(UserSession session); } public class UserAccessValidator : IUserAccessValidator { public bool ValidUser(UserSession session) { // Your validation logic here // session.UserId return true; } } public class UserSettingsValidator : AbstractValidator> { public IUserAccessValidator UserAccessValidator { get; set; } public UserSettingsValidator() { // Notice check now uses .Object to access the object within RuleFor(x => x.Object.UserId) .SetValidator(new PositiveIntegerValidator()); // Custom User Access Validator check, passing the session RuleFor(x => x.Session).Must(x => UserAccessValidator.ValidUser(x)); } }
然后在您的服务中实际使用validation器:
public class SomeService : Service { // Validator with be injected, you need to registered it in the IoC container. public IValidator> { get; set; } public object Post(UserSettingsRequest request) // Match to your own request { // Combine the request with the current session instance var requestWithSession = new WithSession { Session = this.Session, Object = request }; // Validate the request ValidationResult result = this.Validator.Validate(requestWithSession); if(!result.IsValid) { throw result.ToException(); } // Request is valid // ... more logic here return result; } }
我希望这有帮助。 注意:代码未经测试
看来,在从一群遇到类似问题的人那里阅读,然后花了几个小时玩基于SS4 Cookbook等的几个解决方案,这是一个已经解决的问题:
https://forums.servicestack.net/t/blaz-miheljak-355-feb-3-2015/176/2
在validation器上实现IRequiresRequest接口,瞧。