4

我正在开发一个 API,我希望能够根据来自客户端的参数自定义响应结构。响应过滤器似乎是执行此操作的好地方,以避免在每个服务或操作中这样做。问题是,虽然我可以访问操作返回的响应 DTO,并且可以更改其属性,但我无法找到完全替换对象的方式或位置。

天真地替换响应过滤器中的对象不起作用,但这有助于说明我正在尝试做的事情:

public class ChangeResponseAttribute : ResponseFilterAttribute
{
    public override void Execute(IHttpRequest req, IHttpResponse res, object responseDto)
    {
        var overrideText = req.QueryString["override"];
        if (!String.IsNullOrEmpty(overrideText))
            responseDto = new { Message = overrideText };
    }
}

[ChangeResponse]
public class TodosService : Service
{
    public object Get(Todos request)
    {
        return new object[0];
    }
}

看起来另一种选择是直接编写自定义响应并结束请求,但这将绕过 ServiceStack 留下的任何其他处理。

有没有比响应过滤器更好的地方来做到这一点?还是我需要硬着头皮在每个动作中返回最佳 DTO?

4

1 回答 1

4

您不能在过滤器中更改响应 DTO,但是是的,一种选择是将响应写入过滤器本身(有关如何执行此操作的示例,请参见此答案)。

另一种选择是使用ServiceRunner并覆盖OnAfterExecute()自定义钩子,它可以让您修改返回的响应,例如:

public class MyServiceRunner<T> : ServiceRunner<T> 
{
    public override object OnAfterExecute(
        IRequestContext requestContext, object response) 
    {
        // Called just after any Action is executed
        var overrideText = req.Get<IHttpRequest>().QueryString["override"];
        return !string.IsNullOrEmpty(overrideText) 
            ? new { Message = overrideText } : null;
    }
}

要让 ServiceStack 使用它,您需要覆盖CreateServiceRunnerAppHost 中的方法,例如:

public override IServiceRunner<TRequest> CreateServiceRunner<TRequest>(
    ActionContext actionContext)
{           
    return new MyServiceRunner<TRequest>(this, actionContext); 
}
于 2013-01-30T20:52:45.730 回答