我正在开发一个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?
答案 0 :(得分:4)
您无法在过滤器中更改Response DTO,但是有一个选项是在过滤器本身中写入响应(see this answer以获取如何执行此操作的示例)。
另一个选项是使用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使用它,您需要覆盖AppHost中的CreateServiceRunner
方法,例如:
public override IServiceRunner<TRequest> CreateServiceRunner<TRequest>(
ActionContext actionContext)
{
return new MyServiceRunner<TRequest>(this, actionContext);
}