在集合中找不到 ServiceStack 标记属性

ServiceStack marker Attribute not found in Collection

我有一个自定义属性,我想通过 GlobalFilter 检查我调用的方法是否有这个标记属性。 我找不到一种方法来获取我的请求所针对的被调用方法具有属性的信息。 我已经找到了另一个 post,它建议使用 FilterAttributeCache.GetRequestFilterAttributes(request.GetType()),但是这个和其他方法都没有重新调整任何元素。

你能帮我解决我在这里遗漏的问题吗?

示例代码如下:

自定义属性:

using ServiceStack;
using ServiceStack.Web;

namespace MyProject.Web
{
    public class CustomAttribute : RequestFilterAttribute
    {
        public string ServiceName;
        public string ServiceClass;
        public string ServiceMethod;

        public JwtAuthAttribute(string serviceName, string serviceClass, string serviceMethod)
        {
            ServiceName = serviceName;
            ServiceClass = serviceClass;
            ServiceMethod = serviceMethod;
        }

        public override void Execute(IRequest req, IResponse res, object requestDto)
        {
            //Nothing in here
        }
    }
}

过滤器:

using System;
using System.Linq;
using ServiceStack.Support.WebHost;
using ServiceStack.Web;

namespace MyProject.Web
{
    public class CustomFilter
    {
        private readonly ICustomManager _customManager;

        public CustomFilter(ICustomManager customManager)
        {
            _customManager= customManager;
        }

        public void Execute(IRequest request)
        {
            var customHeader = request.Headers.GetValues("CustomHeader");

            if (customHeader == null)
            {
                return;
            }

            var customAttribute = FilterAttributeCache.GetRequestFilterAttributes(request.GetType())
                .OfType<CustomAttribute>().FirstOrDefault();

            if (customAttribute == null)
            {
                return;
            }

            // Do other things here
        }
    }
}

在 Global.asax 中注册 GlobalFilter:

public override void Configure(Container container)
{
    //other configurations
    
    GlobalRequestFilters.Add((req, res, dto) => req.ResponseContentType = MimeTypes.Json);
    GlobalRequestFilters.Add((req, res, dto) =>
    {
        var customFilter = new CustomFilter(request.TryResolve<ICustomManager>());
        customFilter.Execute(req);
    });
}

带有标记 CustomAttribute 的方法:

namespace MyProject.Web
{
    [Authenticate]
    [RequiredRole("CustomUser")]
    public class CustomService : Service
    {
        [Custom("Service", "ServiceClass", "ServiceMethod")]
        public object Get(CustomRequest request)
        {
            //Additional code
        }   
    }
}

我建议在 Request DTO 上添加属性,这样更容易访问,因为 Request DTO 在整个 ServiceStack 请求管道中随处可用,例如dto.GetType() 在全局过滤器中或 IRequest.Dto.GetType() 其他任何地方。

要访问 ServiceStack 操作,您需要先访问服务类型,然后再访问其操作,例如:

GlobalRequestFilters.Add((req, res, dto) =>
{
    var serviceType = HostContext.AppHost.Metadata.GetServiceTypeByRequest(dto.GetType());
    var action = serviceType.GetActions().First(x => x.RequestType == dto.GetType());
    var attrs = action.AllAttributes<CustomAttribute>();
});

之后,我解决了这个问题。我通过 requestDto 扩展了“CustomFilter”的“Execute”方法,该方法由 GobalRequestFilter 注册提供。

不幸的是,我无法访问 属性“RequestType”,可能是因为我使用的是旧版本(ServiceStack 5.9.2、.Net Framework 4.7.2),所以我不得不去在方法参数上。

这是最终代码,它让我可以访问“CustomAttribute”

var serviceTypeDto = HostContext.AppHost.Metadata.GetServiceTypeByRequest(requestDto.GetType());
var methodInfo = serviceTypeDto.GetDeclaredMethods().FirstOrDefault(x =>
                x.GetParameters().FirstOrDefault(y => y.ParameterType == requestDto.GetType()) != null && x.IsPublic);

var customAttribute = methodInfo.AllAttributes<CustomAttribute>().FirstOrDefault();