我有一个通用动作过滤器,我想在
OnActionExecuting
方法中获取当前模型。我当前的实现如下:
public class CommandFilter<T> : IActionFilter where T : class, new()
{
public void OnActionExecuting(ActionExecutingContext actionContext)
{
var model= (T)actionContext.ActionArguments["model"];
}
}
如果我的所有型号名称都相同,效果很好。但我想使用不同的型号名称。
如何解决这个问题?
public class HomeController : Controller
{
[ServiceFilter(typeof(CommandActionFilter<CreateInput>))]
public IActionResult Create([FromBody]CreateInput model)
{
return new OkResult();
}
}
ActionExecutingContext.ActionArguments 只是一个字典,
/// <summary>
/// Gets the arguments to pass when invoking the action. Keys are parameter names.
/// </summary>
public virtual IDictionary<string, object> ActionArguments { get; }
如果需要避免硬编码参数名称(“模型”),则需要循环遍历它。来自 asp.net 的相同的答案:
当我们创建一个通用动作过滤器,需要在类似对象的类上工作以满足某些特定要求时,我们可以让我们的模型实现一个接口=>知道哪个参数是我们需要处理的模型,然后我们可以调用这些方法虽然界面。
在你的情况下,你可以写这样的东西:
public void OnActionExecuting(ActionExecutingContext actionContext)
{
foreach(var argument in actionContext.ActionArguments.Values.Where(v => v is T))
{
T model = argument as T;
// your logic
}
}
您可以使用
ActionExecutingContext.Controller
属性
/// <summary>
/// Gets the controller instance containing the action.
/// </summary>
public virtual object Controller { get; }
并将结果转换为基础 MVC 控制器访问模型:
((Controller)actionExecutingContext.Controller).ViewData.Model
如果您的控制器操作有多个参数,并且在过滤器中您想要选择通过
[FromBody]
绑定的参数,那么您可以使用反射来执行以下操作:
public void OnActionExecuting(ActionExecutingContext context)
{
foreach (ControllerParameterDescriptor param in context.ActionDescriptor.Parameters) {
if (param.ParameterInfo.CustomAttributes.Any(
attr => attr.AttributeType == typeof(FromBodyAttribute))
) {
var entity = context.ActionArguments[param.Name];
// do something with your entity...