【问题标题】:How to write a ServiceStack plugin which needs both request and response Dtos如何编写需要请求和响应 Dtos 的 ServiceStack 插件
【发布时间】:2015-08-24 14:37:09
【问题描述】:

我需要为本地化数据提供服务。所有本地化的响应 Dto 共享相同的属性。 IE。我定义了一个接口 (ILocalizedDto) 来标记这些 Dto。在请求端,有一个ILocalizedRequest 用于需要本地化的请求。

使用IPlugin 我已经设法实现了所需的功能。但是我很确定该实现不是线程安全的,另外我不知道是否可以使用 IHttpRequest.GetHashCode() 作为一个请求/响应周期的标识符。

实现使用请求和响应 Dto 的 ServiceStack 插件的正确方法是什么? IE。是否有一些 IHttpRequest.Context 来存储数据,或者是否可以在响应时获取请求 dto?

internal class LocalizationFeature : IPlugin
{
    public static bool Enabled { private set; get; }

    /// <summary>
    ///     Activate the localization mechanism, so every response Dto which is a <see cref="ILocalizedDto" />
    ///     will be translated.
    /// </summary>
    /// <param name="appHost">The app host</param>
    public void Register(IAppHost appHost)
    {
        if (Enabled)
        {
            return;
        }
        Enabled = true;
        var filter = new LocalizationFilter();
        appHost.RequestFilters.Add(filter.RequestFilter);
        appHost.ResponseFilters.Add(filter.ResponseFilter);
    }
}

// My request/response filter
public class LocalizationFilter
{
    private readonly Dictionary<int,ILocalizedRequest> localizedRequests = new Dictionary<int, ILocalizedRequest>();

    public ILocalizer Localizer { get; set; }

    public void RequestFilter(IHttpRequest req, IHttpResponse res, object requestDto)
    {
        var localizedRequest = requestDto as ILocalizedRequest;
        if (localizedRequest != null)
        {
            localizedRequests.Add(GetRequestId(req), localizedRequest);
        }
    }

    public void ResponseFilter(IHttpRequest req, IHttpResponse res, object response)
    {
        var requestId = GetRequestId(req);
        if (!(response is ILocalizedDto) || !localizedRequests.ContainsKey(requestId))
        {
            return;
        }

        var localizedDto = response as ILocalizedDto;
        var localizedRequest = localizedRequests[requestId];
        localizedRequests.Remove(requestId);

        Localizer.Translate(localizedDto, localizedRequest.Language);
    }

    private static int GetRequestId(IHttpRequest req)
    {
        return req.GetHashCode();
    }
}

【问题讨论】:

标签: c# servicestack


【解决方案1】:

首先:为什么你需要请求本身,而你只需要Language 属性的值?

以下代码是您的方案的合法解决方案:

public class LocalizationFeature : IPlugin
{
  public const string LanguageKey = "X-Language";

  public void Register(IAppHost appHost)
  {
    this.GlobalRequestFilters.Add(this.InterceptRequest);
    this.GlobalResponseFilters.Add(this.InterceptResponse);
  }

  private void InterceptRequest(IRequest request,
                                IResponse response,
                                object dto)
  {
    var localizedRequest = dto as ILocalizedRequest;
    if (localizedRequest != null)
    {
      request.SetItem(LanguageKey,
                      localizedRequest.Language);
    }
  }

  private void InterceptResponse(IRequest request,
                                 IResponse response,
                                 object dto)
  {
    var localizedDto = dto as ILocalizedDto;
    if (localizedDto != null)
    {
      var language = request.GetParam(LanguageKey) ?? request.GetItem(LanguageKey);
      if (!string.IsNullOrEmpty(language))
      {
        Localizer.Translate(localizedDto,
                            language);
      }
    }
  }
}

这里有趣的是var language = request.GetParam(LanguageKey) ?? request.GetItem(LanguageKey);,它让您有机会使用带有“X-Language”键的 HTTP 标头、cookie 或表单数据(如果适用)注入语言。 (你也可以做另一个?? DefaultLanguage 来注入一个默认的翻译语言......)

如果不以这种方式提供,则从请求的Items中读取请求的集合Language并使用。

编辑: 另外,作为pointed out by @mythz,您还可以在InterceptResponse方法中使用request.Dto访问请求DTO:

private void InterceptResponse(IRequest request,
                               IResponse response,
                               object dto)
{
    var localizedRequest = request.Dto as ILocalizedRequest;
    var localizedDto = dto as ILocalizedDto;
    if (localizedRequest != null
        && localizedDto != null)
    {
      Localizer.Translate(localizedDto,
                          localizedRequest.Language);
    }
}

【讨论】:

  • 另外,Request DTO 保存在IRequest.Dto 中,Response 对象保存在IResponse.Dto
猜你喜欢
  • 1970-01-01
  • 2012-12-06
  • 1970-01-01
  • 2016-01-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多