J'ai un filtre d'action générique et je veux obtenir le modèle actuel dans la méthode OnActionExecuting
. Ma mise en œuvre actuelle est comme ci-dessous:
public class CommandFilter<T> : IActionFilter where T : class, new()
{
public void OnActionExecuting(ActionExecutingContext actionContext)
{
var model= (T)actionContext.ActionArguments["model"];
}
}
Cela fonctionne bien si tous mes noms de modèles sont identiques. Mais je veux utiliser des noms de modèles différents.
Comment résoudre ce problème?
Modifier
public class HomeController : Controller
{
[ServiceFilter(typeof(CommandActionFilter<CreateInput>))]
public IActionResult Create([FromBody]CreateInput model)
{
return new OkResult();
}
}
ActionExecutingContext.ActionArguments est juste un dictionnaire,
/// <summary>
/// Gets the arguments to pass when invoking the action. Keys are parameter names.
/// </summary>
public virtual IDictionary<string, object> ActionArguments { get; }
Et vous devez le parcourir en boucle si vous devez éviter le nom de paramètre codé en dur ("modèle"). De même réponse SO pour asp.net:
Lorsque nous créons un filtre d'action générique devant travailler sur une classe d'objets similaires pour certaines exigences spécifiques, nos modèles peuvent implémenter une interface => savoir quel argument est le modèle sur lequel nous devons travailler et nous pouvons appeler les méthodes L'interface.
Dans votre cas, vous pouvez écrire quelque chose comme ceci:
public void OnActionExecuting(ActionExecutingContext actionContext)
{
foreach(var argument in actionContext.ActionArguments.Values.Where(v => v is T))
{
T model = argument as T;
// your logic
}
}
Vous pouvez utiliser la propriété ActionExecutingContext.Controller
/// <summary>
/// Gets the controller instance containing the action.
/// </summary>
public virtual object Controller { get; }
et convertir le résultat en contrôleur MVC de base obtenir l’accès au modèle:
((Controller)actionExecutingContext.Controller).ViewData.Model
Si votre action de contrôleur comporte plusieurs arguments et que dans votre filtre, vous souhaitez sélectionner celui lié via [FromBody]
, vous pouvez utiliser la réflexion pour effectuer les opérations suivantes:
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...