【问题标题】:How to get current model in action filter如何在动作过滤器中获取当前模型
【发布时间】:2016-12-18 03:52:21
【问题描述】:

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

【问题讨论】:

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


【解决方案1】:

你可以使用ActionExecutingContext.Controller属性

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

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

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

【讨论】:

  • 它抛出一个强制转换异常:无法将“MyNamespace.HomeController”类型的对象强制转换为“Microsoft.AspNetCore.Mvc.Controller”类型。
  • 很抱歉,我忘记了Controller 基本定义。我编辑了代码,但现在模型为空(也许我错过了任何东西)。查看我的更新。
  • 现在我明白了 - 你想要获取请求模型,而不是视图模型。我已经发布了另一个答案
【解决方案2】:

ActionExecutingContext.ActionArguments 只是一个字典,

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

如果您需要避免硬编码参数名称(“模型”),则需要循环遍历它。来自the same SO answer 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
    }
}

【讨论】:

  • "is T" 然后 "as T" 以某种方式改进该代码?从我的角度来看,你投了两次......
  • 我使用了context.ActionArguments.Values.OfType&lt;MyType&gt;().Single(),因为我知道我想要的具体类型
【解决方案3】:

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

【讨论】:

  • 如果我的模型没有正确反序列化,我会得到given key 'model' was not found in dictionary吗?
猜你喜欢
  • 2017-02-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-10-06
  • 2018-01-14
相关资源
最近更新 更多