gpt4 book ai didi

c# - IAsyncActionFilter 中的 ParameterDescriptor 上的 GetCustomAttributes 丢失

转载 作者:行者123 更新时间:2023-12-04 04:24:01 24 4
gpt4 key购买 nike

使用 .NET 核心 2.1。

我正在尝试访问 IAsyncActionFilter 内部操作参数的属性。

public IActionResult DoSomething([MyAttribute] MyParameter p) { ... }

在我的 IAsyncActionFilter 中,我想访问参数 p 上的 MyAttribute,但 GetCustomAttributes 不存在。

public class MyActionFilter : IAsyncActionFilter
{
public Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
{
// GetCustomAttributes does not exist here...
var attributes = context.ActionDescriptor.Parameters[0].GetCustomAttributes<MyAttribute>();
return next();
}
}

在 ASP.NET MVC 5.2 中,您可以使用 GetCustomAttributes:

https://learn.microsoft.com/en-us/dotnet/api/system.web.mvc.parameterdescriptor.getcustomattributes?view=aspnet-mvc-5.2#System_Web_Mvc_ParameterDescriptor_GetCustomAttributes_System_Boolean_

在 .NET Core 中实现相同的方法是什么?


更新 1

看来我们可以将 ActionDescriptor 转换为 ControllerActionDescriptor 以访问底层 MethodInfo,然后访问参数及其属性。

public class TempDataActionFilter : IAsyncActionFilter
{
public Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
{
var actionDescriptor = (ControllerActionDescriptor)context.ActionDescriptor;
var parameters =
from p in actionDescriptor.MethodInfo.GetParameters()
where p.GetCustomAttributes(typeof(MyAttribute), true) != null
select p;

var controller = context.Controller as Controller;
foreach (var p in parameters)
{
// Do something with the parameters that have an attribute
}
return next();
}
}

这感觉不对。看到 Microsoft 自己的文档中提出这种类型的解决方案,我总是感到沮丧。这是等待发生的运行时错误。有没有更好的办法?

最佳答案

方法一

您似乎在尝试绑定(bind)操作参数。如果是这种情况,ModelBinding 优于过滤器,因此您不必将 ActionDescriptor 转换为 ControllerActionDescriptor 来检查参数是否具有一个指定的属性,

在您的场景中,一种更简单和更安全的方法是让您的 FromTempDataAttribute 实现 IBindingSourceMetadata 以指示您想要绑定(bind)来自 TempData 的数据>:

internal class FromTempDataAttribute : Attribute, IBindingSourceMetadata
{
public static readonly BindingSource Instance = new BindingSource(
"id-FromTempData",
"TempData Binding Source",
true,
true
);
public BindingSource BindingSource {get{
return FromTempDataAttribute.Instance;
}}
}

然后创建一个ModelBinder和一个相关的Provider:

public class MyFromTempDataModelBinder : IModelBinder
{
private readonly IServiceProvider sp;

public MyFromTempDataModelBinder(IServiceProvider sp)
{
this.sp = sp;
}

public Task BindModelAsync(ModelBindingContext bindingContext)
{
var factory = this.sp.GetRequiredService<ITempDataDictionaryFactory>();
var tempData = factory.GetTempData(bindingContext.HttpContext);
var name = bindingContext.FieldName;
var o = tempData.Peek(name);
if (o == null) {
bindingContext.ModelState.AddModelError(name, $"cannot get {name} from TempData");
} else {
var result = Convert.ChangeType(o,bindingContext.ModelType);
bindingContext.Result = ModelBindingResult.Success(result);
}
return Task.CompletedTask;
}

}

public class FromTempDataBinderProvider : IModelBinderProvider
{
public IModelBinder GetBinder(ModelBinderProviderContext context)
{
if (context == null) { throw new ArgumentNullException(nameof(context)); }
var has = context.BindingInfo?.BindingSource == FromTempDataAttribute.Instance;
if(has){
return new BinderTypeModelBinder(typeof(MyFromTempDataModelBinder));
}
return null;
}
}

如果 context.BindingInfo.BindingSource 等于所需的属性,则提供程序返回 MyFromTempDataModelBinder 的实例。

另外不要忘记在您的初创公司中注册此提供商:

services.AddMvc(opts => {
opts.ModelBinderProviders.Insert(0, new FromTempDataBinderProvider());
}).SetCompatibilityVersion(CompatibilityVersion.Version_2_1);

最后就可以自动获取数据了:

public IActionResult Test([FromTempDataAttribute] string a, string b )
{
return Json(new {A = a, B = b,});
}

方法二

如果你坚持使用Filter,你也可以像上面那样让FromTempDataAttribute实现IBindingSourceMetadata接口(interface),然后你就可以得到这些参数如下:

public class TempDataActionFilter : IAsyncActionFilter
{
public Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
{
var parameteres = context.ActionDescriptor.Parameters.Where(p => p.BindingInfo?.BindingSource == FromTempDataAttribute.Instance);
foreach(var p in parameteres){
// ...
}
return next();
}
}

关于c# - IAsyncActionFilter 中的 ParameterDescriptor 上的 GetCustomAttributes 丢失,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58296102/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com