2013-12-12 58 views
3

我是ServiceStack的新手。我使用版本4.04。ServiceStack - 消息隊列服務(驗證和篩選)

我創建了兩個程序,它們使用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. 消息&驗證器位於一個獨立的程序集中。 通過 container.RegisterValidators(typeof(RegisterCustomerValidator).Assembly); 在IOC自動註冊驗證器不是有效的。我通過註冊驗證後:

container.Register<IValidator<RegisterCustomer>>(new RegisterCustomerValidator());

我能夠通過「TryResolve」

  1. 我馬上想到我在註冊驗證解決在服務的驗證國際奧委會,請求DTO得到驗證。但看起來情況並非如此:調用者獲取響應並且「ResponseStatus」屬性爲空。

  2. 我創建RequestFilter做驗證:

    公共類ValidationFilterAttribute:RequestFilterAttribute { 公共覆蓋無效執行(IRequest REQ,IResponse資源,對象requestDto) { 串虛設= 「HelloWorld」 的; } }

,並將其應用到該請求DTO:

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

「執行」 的方法不被調用。我在這裏錯過什麼?

任何幫助,非常感謝。

+0

您不應該使用Request過濾器,如ValidationFilter,因爲驗證應該自動發生。也驚訝container.RegisterValidators不工作,因爲這是我所使用和需要的。你打電話給你的服務?即通過C#,Ajax,MQ? – mythz

+0

我更新我的問題以添加問題的答案。 – Soernt

+0

我無法更新我的問題!?該驗證適用於Asp.Net項目,但不適用於Windows服務項目。 Windows服務項目僅通過Redis MQ功能處理消息。 AppHost派生自AppHostBase,創建RedisMqServer並通過'mqService.RegisterHandler (ServiceController.ExecuteMessage)'註冊消息處理程序。 – Soernt

回答

2

這是因爲驗證是作爲全局請求過濾器執行的,它們對MQ Requests沒有執行,它們被認爲是內部服務並跳過全局請求過濾器。

我們在v4.05中增加了新的IAppHost.GlobalMessageRequestFilters,ValidationFeature使用它來通過MQ驗證請求。

注意:任何驗證或服務錯誤被髮送到響應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)); 
} 
+0

只要我添加過濾器,我得到這個異常: 'ServiceBase ::服務異常 Der Wert darf nicht NULL sein。 參數名稱:鍵 貝System.Collections.Generic.Dictionary'2.FindEntry(TKEY的鍵) 貝System.Collections.Generic.Dictionary'2.TryGetValue(TKEY的鍵,TValue&值) 貝ServiceStack.ApplyToUtils.HttpMethodAsApplyTo(IRequest req) bei ServiceStack.RequestFilterAttribute.RequestFilter(IRequest req,IResponse res,Object requestDto) bei ServiceStack.Host.ServiceRunner'1.Execute(IRequest request,Object instance,TRequest requestDto)' – Soernt

+0

您的第二個選項正在工作。謝謝。我認爲處理服務調用的一般行爲並不取決於它們的使用/調用方式(REST vs. MQ)。 – Soernt

+0

@Soernt指的是體系結構圖,MQ被視爲內部請求,Filter的常見用例是用於處理外部HTTP邏輯。我同意驗證是一種異常現象,並且會考慮在MQ中啓用驗證。 – mythz