如何在动作过滤器中获取当前模型

时间:2016-08-11 12:02:01

标签: c# asp.net-core asp.net-core-mvc

我有一个通用的动作过滤器,我想在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();
    }
}

3 个答案:

答案 0 :(得分:8)

ActionExecutingContext.ActionArguments只是一个字典,

    /// <summary>
    /// Gets the arguments to pass when invoking the action. Keys are parameter names.
    /// </summary>
    public virtual IDictionary<string, object> ActionArguments { get; }

如果你需要避免硬编码的参数名称(&#34; model&#34;),你需要循环它。来自the same SO answer for asp.net:

  

当我们创建一个通用的动作过滤器,需要针对某些特定需求处理一类类似的对象时,我们可以让我们的模型实现一个接口=&gt;知道哪个参数是我们需要处理的模型,我们可以通过接口调用方法。

在你的情况下,你可以这样写:

public void OnActionExecuting(ActionExecutingContext actionContext)
{
    foreach(var argument in actionContext.ActionArguments.Values.Where(v => v is T))
    {
         T model = argument as T;
         // your logic
    }
}

答案 1 :(得分:5)

您可以使用ActionExecutingContext.Controller属性

    /// <summary>
    /// Gets the controller instance containing the action.
    /// </summary>
    public virtual object Controller { get; }

并将结果转换为base MVC Controller即可访问模型:

((Controller)actionExecutingContext.Controller).ViewData.Model

答案 2 :(得分:1)

如果您的控制器操作有多个参数,并且在您的过滤器中您想要选择通过[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...