Asp.NET MVC ModelBinder, obtendo o método de ação

9

Eu tenho um ModelBinder personalizado e gostaria de receber a ação. Porque eu quero obter os atributos da ação usando reflexão, o nome da ação não é suficiente.

meu método de ação:

[MyAttribute]
public ActionResult Index([ModelBinder(typeof(MyModelBinder))] MyModel model)
{
}

e aqui normalmente um ModelBinder

public class MyModelBinder : IModelBinder
{
    public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) 
    {
        // here i would like to get the action method and his "MyAttribute"
    }
}

alguma sugestão, outras soluções?

muito obrigado antecipadamente

    
por dknaack 01.06.2011 в 10:14

3 respostas

4

Não, você não pode, com 100% de certeza, obter a ação atual de um fichário de modelo. O fichário do modelo não está acoplado à ação, mas à vinculação a um modelo. Por exemplo, você pode ligar para

TryUpdateMode(model)

Em um filtro antes de uma ação ser escolhida. Observe também que um método de ação pode nem ser um método CLR (consulte link ) que pode ser refletido em.

Acho que a verdadeira questão é: o que exatamente você está tentando realizar e é esse o caminho certo? Se você quiser que as informações da ação sejam passadas para o fichário do modelo (atendendo ao conselho de que o fichário de modelo deve ser degradado normalmente se as informações não estiverem lá), use um filtro de ação para colocar as informações em HttpContext.Items (ou em algum lugar como esse) e, em seguida, ter seu fichário recuperá-lo.

O método OnActionExecuting de um filtro de ação recebe um ActionExecutingContext que possui um ActionDescriptor. Você pode chamar GetCustomAttributes sobre isso.

    
por Haacked 01.06.2011 / 18:03
1

Você pode tentar isso:

var actionName = controllerContext.RouteData.GetRequiredString("action");
var myAttribute = (MyAttribute) Attribute.GetCustomAttribute(controllerContext.Controller.GetMethod(actionName), typeof(MyAttribute));
    
por Fabiano 01.06.2011 / 14:34
0

Você pode substituir ControllerActionInvoker.FindAction() para obter o atributo da ação e armazená-lo em HttpContext.Current.Items , conforme mencionado aqui, ou estendido ControllerContext.RequestContext , da seguinte maneira:

public class MyControllerActionInvoker : ControllerActionInvoker
{
    protected override ActionDescriptor FindAction(ControllerContext controllerContext, ControllerDescriptor controllerDescriptor, string actionName)
    {
        var action = base.FindAction(controllerContext, controllerDescriptor, actionName);

        if (action != null)
        {
            var requestContext = ExtendedRequestContext.Bind(controllerContext);
            var attr = action.GetCustomAttributes(typeof(MyAttribute), false).FirstOrDefault();

            if (attr != null)
                requestContext.CustomAttribute = (MyAttribute)attr;
        }

        return action;
    }
}

public class ExtendedRequestContext : RequestContext
{
    public MyAttribute CustomAttribute { get; set; }

    public static ExtendedRequestContext Bind(ControllerContext controllerContext)
    {
        var requestContext = new ExtendedRequestContext
        {
            HttpContext = controllerContext.RequestContext.HttpContext,
            RouteData = controllerContext.RequestContext.RouteData
        };

        controllerContext.RequestContext = requestContext;
        return requestContext;
    }
}

O invocador de ação padrão é substituído no construtor do seu controlador ou em uma fábrica de controladores personalizados:

public MyController() : base()
{
    ActionInvoker = new MyControllerActionInvoker();
}

A propósito, Controller.TempData já contém um item de ReflectedParameterDescriptor type, que dá acesso a ActionDescriptor , então o código acima pode ser redundante. No entanto, tenha cuidado, isto é específico da implementação, por isso pode mudar ao longo do tempo.

Por fim, obtenha o atributo desse armazenamento na sua classe de fichário:

var requestContext = (ExtendedRequestContext)controllerContext.RequestContext;
if (requestContext.CustomAttribute != null)
{
    // apply your logic here
}
    
por Herman Kan 26.11.2016 / 11:58