How to get current model in action filter

|▌冷眼眸甩不掉的悲伤 提交于 2019-12-18 05:41:56

问题


I have a generic action filter, and i want to get current model in the OnActionExecuting method. My current implementation is like below:

public class CommandFilter<T> : IActionFilter where T : class, new()
{
    public void OnActionExecuting(ActionExecutingContext actionContext)
    {
        var model= (T)actionContext.ActionArguments["model"];
    }
}

It works well if my all model names are same. But i want to use differnet model names.

How to solve this problem?

Edit

public class HomeController : Controller
{
    [ServiceFilter(typeof(CommandActionFilter<CreateInput>))]
    public IActionResult Create([FromBody]CreateInput model)
    {
        return new OkResult();
    }
}

回答1:


ActionExecutingContext.ActionArguments is just a dictionary,

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

And you need to loop through it if you need to avoid hardcoded parameter name ("model"). From the same SO answer for asp.net:

When we create a generic action filter that needs to work on a class of similar objects for some specific requirements, we could have our models implement an interface => know which argument is the model we need to work on and we can call the methods though the interface.

In your case you may write something like this:

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



回答2:


You can use ActionExecutingContext.Controller property

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

and converting result to base MVC Controller get access to model:

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



回答3:


In case your controller action has multiple arguments and in your filter you want to select the one that is bound via [FromBody], then you can use reflection to do the following:

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...


来源:https://stackoverflow.com/questions/38895830/how-to-get-current-model-in-action-filter

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!