ServiceStack - 消息队列服务(验证和过滤)

时间:2013-12-12 14:41:32

标签: c# servicestack fluentvalidation

我是ServiceStack的新手。我使用版本4.04。

我创建了两个程序,他们使用Redis队列相互通信。 一个是Asp.Net主机,另一个是Windows服务。

虽然基本的发送和接收消息运行良好,但我在Windows服务程序中为请求DTO配置验证时遇到了一些问题。

这些是我的请求,响应DTO是验证器:

public class RegisterCustomer : IReturn<RegisterCustomerResponse>
{
  public string FirstName { get; set; }
  public string LastName { get; set; }
  public string CompanyName { get; set; }
  public string EMailAddress { get; set; }
  public string Password { get; set; }
}

public class RegisterCustomerValidator : AbstractValidator<RegisterCustomer>
{
  public RegisterCustomerValidator()
  {
    RuleFor(m => m.FirstName).NotEmpty();
    RuleFor(m => m.LastName).NotEmpty();
    RuleFor(m => m.EMailAddress).NotEmpty().EmailAddress();
    RuleFor(m => m.Password).NotEmpty().Length(5, 100);
  }
}

public class RegisterCustomerResponse
{
  public ResponseStatus ResponseStatus { get; set; }
}

这是我配置验证的部分:

private void configureValidation(Container container)
{
  Plugins.Add(new ValidationFeature());
  // container.RegisterValidators(typeof(RegisterCustomerValidator).Assembly);
  container.Register<IValidator<RegisterCustomer>>(new RegisterCustomerValidator());
}

这是我的服务:

public class RegisterCustomerService : RavenService
{
  public RegisterCustomerService(IDocumentSession ravenSession)
    : base(ravenSession)
  {
  }

  public RegisterCustomerResponse Any(RegisterCustomer request)
  {
    Logger.Info("Start: Handel message '{0}' ({1})".Fmt(request.ToString(), request.GetType().Name));

    RegisterCustomerResponse result = new RegisterCustomerResponse();     

    Logger.Info("End: Handel message '{0}' ({1})".Fmt(request.ToString(), request.GetType().Name));
    return result;
  }
}
  1. 消息&amp;验证器位于单独的组件中。 通过IOC自动注册验证器 container.RegisterValidators(typeof(RegisterCustomerValidator).Assembly); 不是傻瓜。在我通过以下方式注册Validator之后:
  2. container.Register<IValidator<RegisterCustomer>>(new RegisterCustomerValidator());

    我能够通过“TryResolve”解析服务中的Validator

    1. 我想,只要我在IOC注册验证器,请求DTO就会得到验证。但看起来情况并非如此:调用者获取响应并且“ResponseStatus”属性为null。

    2. 我创建了RequestFilter来进行验证:

      public class ValidationFilterAttribute:RequestFilterAttribute {   public override void Execute(IRequest req,IResponse res,object requestDto)   {     string dummy =“HelloWorld”;   } }

    3. 并将其应用于请求dto:

      [ValidationFilter]
      public class RegisterCustomer : IReturn<RegisterCustomerResponse>
      {
        ...
      }
      

      未调用“执行”方法。我在这里想念什么?

      非常感谢任何帮助。

1 个答案:

答案 0 :(得分:2)

这是因为验证是作为全局RequestFilter执行的,它不会被MQ Requests执行,它被认为是内部服务并跳过全局请求过滤器。

我们在 v4.05 中添加了新的IAppHost.GlobalMessageRequestFilters,ValidationFeature现在也使用它来验证通过MQ的请求。

注意:任何验证或服务错误都会发送到Response DLQ(例如QueueNames<RegisterCustomerResponse>.Dlq)而不是默认的INQ(例如QueueNames<RegisterCustomerResponse>.Inq),以获得有效响应,如下例所示:

public class ValidateTestMq
{
    public int Id { get; set; }
}

public class ValidateTestMqResponse
{
    public int CorrelationId { get; set; }

    public ResponseStatus ResponseStatus { get; set; }
}

public class ValidateTestMqValidator : AbstractValidator<ValidateTestMq>
{
    public ValidateTestMqValidator()
    {
        RuleFor(x => x.Id)
            .GreaterThanOrEqualTo(0)
            .WithErrorCode("PositiveIntegersOnly");
    }
}

以下测试发布无效请求,后跟有效请求:

using (var mqFactory = appHost.TryResolve<IMessageFactory>())
{
    var request = new ValidateTestMq { Id = -10 };
    mqFactory.CreateMessageProducer().Publish(request);
    var msg = mqFactory.CreateMessageQueueClient()
        .Get(QueueNames<ValidateTestMqResponse>.Dlq, null)
        .ToMessage<ValidateTestMqResponse>();

    Assert.That(msg.GetBody().ResponseStatus.ErrorCode,
        Is.EqualTo("PositiveIntegersOnly"));

    request = new ValidateTestMq { Id = 10 };
    mqFactory.CreateMessageProducer().Publish(request);
    msg = mqFactory.CreateMessageQueueClient()
         .Get(QueueNames<ValidateTestMqResponse>.In, null)
        .ToMessage<ValidateTestMqResponse>();
    Assert.That(msg.GetBody().CorrelationId, Is.EqualTo(request.Id));
}