ServiceStack使用全局过滤器与CompressResponse属性压缩响应报500错误求助
现有实现的问题
自定义全局过滤器的错误
- 序列化逻辑不匹配:使用
BinaryFormatter序列化请求DTO,但要返回的是application/json格式响应,二者完全不兼容,序列化结果不是合法JSON字符串。 - 压缩逻辑完全无效:创建了
GZipStream但没有将压缩后的数据写入响应,反而直接调用response.WriteToResponse输出原始未压缩内容,同时提前添加了Content-Encoding: gzip头,客户端会把未压缩内容当成gzip格式解析,直接触发报错。 - 流处理错误:
MemoryStream和GZipStream都没有正确设置读写位置,也没有主动释放,会引发资源泄漏和运行时异常。
[CompressResponse]属性使用错误
- 特性作用位置错误:ServiceStack的
[CompressResponse]特性只能作用于继承自Service的服务类/服务方法,你将特性加在DAL实现类上,ServiceStack的拦截器无法识别,不会生效。 - 客户端未声明支持压缩:仅添加了
Accept: application/json头,没有添加Accept-Encoding头声明支持gzip/deflate格式,ServiceStack默认不会返回压缩响应。
正确实现方案
方案1:全局启用响应压缩(推荐,无需修改业务代码)
在AppHost的Configure方法中注册压缩插件即可全局启用所有接口的压缩能力:
public override void Configure(Container container) { // 全局启用gzip/deflate响应压缩 Plugins.Add(new CompressionFeature()); // 其他配置... }
修改Mvc侧客户端代码,添加接受压缩的请求头:
// 声明支持的压缩格式 httpClient.DefaultRequestHeaders.AcceptEncoding.Add(new StringWithQualityHeaderValue("gzip")); httpClient.DefaultRequestHeaders.AcceptEncoding.Add(new StringWithQualityHeaderValue("deflate")); httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); // 建议替换.Result为await避免线程阻塞 HttpResponseMessage response = await httpClient.GetAsync(url);
方案2:单独指定接口启用压缩
如果不需要全局开启,只需要给特定接口加压缩,将[CompressResponse]特性加在正确的服务类/服务方法上即可:
// 特性加在服务类上,整个类的所有接口都会启用压缩 [CompressResponse] public class CommonService : Service { public ICommonDAL CommonDAL { get; set; } public async Task<string> Get(Getvalue request) { return await CommonDAL.Getdefaultvalue(request); } } // 也可以单独加在服务方法上,仅该接口启用压缩 // public class CommonService : Service // { // public ICommonDAL CommonDAL { get; set; } // // [CompressResponse] // public async Task<string> Get(Getvalue request) // { // return await CommonDAL.Getdefaultvalue(request); // } // }
同样需要客户端添加Accept-Encoding请求头才能生效。
注意事项
不要自定义全局过滤器实现压缩,ServiceStack自带的压缩逻辑已经处理了所有边界情况,包括小响应自动跳过压缩避免负优化、异常时的头回退、多压缩格式兼容等,直接使用内置实现即可。
内容的提问来源于stack exchange,提问作者Prabhu
相关产品推荐
相关产品推荐

