如何在每个路由的基础上控制 ABP 中的响应包装?
How to control response wrapping in ABP on a per-route basis?
我正在使用 ABP (aspnetboilerplate) 7.0 到 ASP.NET Zero 11,我正在尝试让 OData 工作。我在 ABP 上关注了这篇文章,并从他们的样本中获得了灵感。
不应包装 OData 路由(/odata
和 /odata/$metadata
)的响应。 ABP 确实提供了一个名为 DontWrapResult
的属性来防止换行。但是,由于这些路由不在我可以直接访问的控制器上,因此我无法设置该属性。
这里有人问过同样的问题:
但是,他们想完全禁用换行,这不是我想要做的。
该问题的答案是使用 ResultFilter
来设置属性值。但是,我发现通过属性设置值也会设置来自注入 IAbpAspNetCoreConfiguration
.
的值
例如:
public class ODataResultFilter : IResultFilter, ITransientDependency
{
private readonly IAbpAspNetCoreConfiguration _configuration;
public ODataResultFilter(IAbpAspNetCoreConfiguration configuration)
{
_configuration = configuration;
}
public void OnResultExecuting(ResultExecutingContext context)
{
var methodInfo = context.ActionDescriptor.GetMethodInfo();
var wrapResultAttribute =
GetSingleAttributeOfMemberOrDeclaringTypeOrDefault(
methodInfo,
_configuration.DefaultWrapResultAttribute,
false
);
if (context.HttpContext.Request.Path.Value.Equals("/odata/$metadata") ||
context.HttpContext.Request.Path.Value.Equals("/odata"))
{
wrapResultAttribute.WrapOnSuccess = false;
}
}
public void OnResultExecuted(ResultExecutedContext context)
{
// No action
}
private TAttribute GetSingleAttributeOfMemberOrDeclaringTypeOrDefault<TAttribute>(MemberInfo memberInfo, TAttribute defaultValue = default(TAttribute), bool inherit = true)
where TAttribute : class
{
return memberInfo.GetCustomAttributes(true).OfType<TAttribute>().FirstOrDefault()
?? memberInfo.DeclaringType?.GetTypeInfo().GetCustomAttributes(true).OfType<TAttribute>().FirstOrDefault()
?? defaultValue;
}
}
只要我点击 wrapResultAttribute.WrapOnSuccess = false;
,_configuration.DefaultWrapResultAttribute
就会变为 false,所有其他请求最终都不会被包装。我的前端需要包装响应,因此一旦我点击 OData 路由,前端就会停止工作。
如何操作此属性并防止 OData 路由换行,但为其他路由保留默认 + 属性配置的换行行为?
GetSingleAttributeOfMemberOrDeclaringTypeOrDefault
方法应该可以正常工作,除了现在,因为 _configuration.DefaultWrapResultAttribute
被修改,没有显式设置 WrapResult
属性的控制器将获得默认值,被最后一个值集。
实现IWrapResultFilter
,在ABP v6.5中引入:
using Abp.Web.Results.Filters;
using System;
namespace AbpODataDemo.Web.Host.ResultWrapping
{
public class ODataWrapResultFilter : IWrapResultFilter
{
public bool HasFilterForWrapOnError(string url, out bool wrapOnError)
{
wrapOnError = false;
return new Uri(url).AbsolutePath.StartsWith("/odata", StringComparison.InvariantCultureIgnoreCase);
}
public bool HasFilterForWrapOnSuccess(string url, out bool wrapOnSuccess)
{
wrapOnSuccess = false;
return new Uri(url).AbsolutePath.StartsWith("/odata", StringComparison.InvariantCultureIgnoreCase);
}
}
}
将其添加到模块的 PreInitialize
方法中的 WrapResultFilters
:
Configuration.Modules.AbpWebCommon().WrapResultFilters.Add(new ODataWrapResultFilter());
参考:
- https://aspnetboilerplate.com/Pages/Documents/AspNet-Core#wrapresultfilters
- https://github.com/aspnetboilerplate/sample-odata/pull/20
带有 ABP v7.1 及更高版本的 OData
Abp.AspNetCore.OData
实现 AbpODataDontWrapResultFilter
以禁用以 "/odata"
.
开头的路径的结果换行
将其添加到模块的 PreInitialize
方法中的 WrapResultFilters
:
Configuration.Modules.AbpWebCommon().WrapResultFilters.Add(new AbpODataDontWrapResultFilter());
让库用户明确配置的基本原理是突出默认结果包装和 OData 用例之间的这种交互。
参考文献:
我正在使用 ABP (aspnetboilerplate) 7.0 到 ASP.NET Zero 11,我正在尝试让 OData 工作。我在 ABP 上关注了这篇文章,并从他们的样本中获得了灵感。
不应包装 OData 路由(/odata
和 /odata/$metadata
)的响应。 ABP 确实提供了一个名为 DontWrapResult
的属性来防止换行。但是,由于这些路由不在我可以直接访问的控制器上,因此我无法设置该属性。
这里有人问过同样的问题:
但是,他们想完全禁用换行,这不是我想要做的。
该问题的答案是使用 ResultFilter
来设置属性值。但是,我发现通过属性设置值也会设置来自注入 IAbpAspNetCoreConfiguration
.
例如:
public class ODataResultFilter : IResultFilter, ITransientDependency
{
private readonly IAbpAspNetCoreConfiguration _configuration;
public ODataResultFilter(IAbpAspNetCoreConfiguration configuration)
{
_configuration = configuration;
}
public void OnResultExecuting(ResultExecutingContext context)
{
var methodInfo = context.ActionDescriptor.GetMethodInfo();
var wrapResultAttribute =
GetSingleAttributeOfMemberOrDeclaringTypeOrDefault(
methodInfo,
_configuration.DefaultWrapResultAttribute,
false
);
if (context.HttpContext.Request.Path.Value.Equals("/odata/$metadata") ||
context.HttpContext.Request.Path.Value.Equals("/odata"))
{
wrapResultAttribute.WrapOnSuccess = false;
}
}
public void OnResultExecuted(ResultExecutedContext context)
{
// No action
}
private TAttribute GetSingleAttributeOfMemberOrDeclaringTypeOrDefault<TAttribute>(MemberInfo memberInfo, TAttribute defaultValue = default(TAttribute), bool inherit = true)
where TAttribute : class
{
return memberInfo.GetCustomAttributes(true).OfType<TAttribute>().FirstOrDefault()
?? memberInfo.DeclaringType?.GetTypeInfo().GetCustomAttributes(true).OfType<TAttribute>().FirstOrDefault()
?? defaultValue;
}
}
只要我点击 wrapResultAttribute.WrapOnSuccess = false;
,_configuration.DefaultWrapResultAttribute
就会变为 false,所有其他请求最终都不会被包装。我的前端需要包装响应,因此一旦我点击 OData 路由,前端就会停止工作。
如何操作此属性并防止 OData 路由换行,但为其他路由保留默认 + 属性配置的换行行为?
GetSingleAttributeOfMemberOrDeclaringTypeOrDefault
方法应该可以正常工作,除了现在,因为 _configuration.DefaultWrapResultAttribute
被修改,没有显式设置 WrapResult
属性的控制器将获得默认值,被最后一个值集。
实现IWrapResultFilter
,在ABP v6.5中引入:
using Abp.Web.Results.Filters;
using System;
namespace AbpODataDemo.Web.Host.ResultWrapping
{
public class ODataWrapResultFilter : IWrapResultFilter
{
public bool HasFilterForWrapOnError(string url, out bool wrapOnError)
{
wrapOnError = false;
return new Uri(url).AbsolutePath.StartsWith("/odata", StringComparison.InvariantCultureIgnoreCase);
}
public bool HasFilterForWrapOnSuccess(string url, out bool wrapOnSuccess)
{
wrapOnSuccess = false;
return new Uri(url).AbsolutePath.StartsWith("/odata", StringComparison.InvariantCultureIgnoreCase);
}
}
}
将其添加到模块的 PreInitialize
方法中的 WrapResultFilters
:
Configuration.Modules.AbpWebCommon().WrapResultFilters.Add(new ODataWrapResultFilter());
参考:
- https://aspnetboilerplate.com/Pages/Documents/AspNet-Core#wrapresultfilters
- https://github.com/aspnetboilerplate/sample-odata/pull/20
带有 ABP v7.1 及更高版本的 OData
Abp.AspNetCore.OData
实现 AbpODataDontWrapResultFilter
以禁用以 "/odata"
.
将其添加到模块的 PreInitialize
方法中的 WrapResultFilters
:
Configuration.Modules.AbpWebCommon().WrapResultFilters.Add(new AbpODataDontWrapResultFilter());
让库用户明确配置的基本原理是突出默认结果包装和 OData 用例之间的这种交互。
参考文献: