在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的插件。

我之前想做类似的事情,然后意识到这是不可能的。

RequestFilterServiceRunner之前运行。 请参阅此处的操作顺序指南 。

这对您来说意味着您的填充请求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接口,瞧。