如何在每个路由的基础上控制 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());

参考:


带有 ABP v7.1 及更高版本的 OData

Abp.AspNetCore.OData 实现 AbpODataDontWrapResultFilter 以禁用以 "/odata".

开头的路径的结果换行

将其添加到模块的 PreInitialize 方法中的 WrapResultFilters

Configuration.Modules.AbpWebCommon().WrapResultFilters.Add(new AbpODataDontWrapResultFilter());

让库用户明确配置的基本原理是突出默认结果包装和 OData 用例之间的这种交互。

参考文献: