2009-07-06 17 views
8

Sto provando a scrivere un unit test che eseguirà il ciclo di tutti i metodi di azione sulle mie classi di controller cercando i metodi di azione che non hanno alcun attributo relativo alla sicurezza su di essi (ad es. [Autorizza]).In che modo ASP.NET MVC sa che un metodo è un metodo di azione?

In che modo il motore di routing ASP.NET determina quali metodi sono i metodi di azione? Ovviamente i metodi di azione devono essere pubblici, ma metodi come ToString() non sono metodi di azione, quindi c'è un po 'di logica in questo.

risposta

1

ho smesso di essere pigro e ho trovato la risposta, la maggior parte dei quali era in System.Web.Mvc.ActionMethodSelector.PopulateLookupTables() (grazie riflettore!)

private IEnumerable<MethodInfo> GetActionMethods(Type controllerType) 
    { 
     return Array.FindAll(controllerType.GetMethods(BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Instance), IsValidActionMethod); 
    } 

    private static bool IsValidActionMethod(MethodInfo methodInfo) 
    { 
     return (!methodInfo.IsSpecialName && !methodInfo.GetBaseDefinition().DeclaringType.IsAssignableFrom(typeof(Controller)) && 
      !methodInfo.GetCustomAttributes(typeof(NonActionAttribute), true).Any()); 
    } 

sono rimasto sorpreso di vedere tutto il metodi pubblici sulle mie classi di controller di base che sono stati esposti senza alcuna sicurezza su di essi!

+1

Se hai bisogno di tutti i tuoi metodi di azione in un controller per avere il filtro [Autorizza] su di essi, sono abbastanza sicuro che potresti aggiungerlo all'inizio del controller. Ha lo stesso effetto di aggiungerlo ad ogni azione.Non credo che influenzerà i metodi di non azione, ma potrei sbagliarmi. –

8

Tutti i metodi in un controller sono considerati Azioni, tranne che per metodi non pubblici.

In primo luogo, i metodi sono identificati dal nome: MethodName = ActionName.

Se si desidera sovrascrivere il comportamento predefinito, si utilizza l'attributo [NomeAzione].

public MyController 
{ 
    [ActionName("ActionY")] 
    public MethodX() 
    { 
    } 
} 

Quindi questo metodo scatterà quando viene richiesto un URL http://..../ActionY.

Per saperne di più nel blog di Phil: How a Method Becomes An Action

EDIT: Okay, forse questo: tutti i metodi pubblici definiti direttamente nella classe controller, ma non ereditate da classi base, non ignorando quelli di classi base, a meno che non ricorsivamente identificato quei metodi di base sono già azioni, non decorati con attributo NoAction.

+1

"Tutti i metodi in un controller sono considerati azioni, ad eccezione di non-pubblico metodi ". - Non vero, ToString() è un metodo pubblico ma non è un metodo di azione. –

+0

Per aggiungere a questo, è anche possibile aggiungere un attributo [NonAction] a un metodo pubblico se è necessario che sia pubblico per scopi di testing unitario. –

+0

Ok, quello ovviamente non è, ma hai un'idea generale. Si eredita dalla classe controller e quali metodi pubblici definiti verranno trasformati in azioni. – User

1

C'è una spiegazione molto bella di come i metodi di azione vengono elaborati nel libro MVC ASP.NET che sto usando come riferimento. Come spesso accade, le pagine relative sono disponibili su Google books:

http://books.google.com/books?id=Xb3a1xTSfZgC&lpg=PA308&ots=J9GgXhsads&dq=action%20method%20selection%20sanderson&pg=PA310

Nel caso in cui il collegamento muore, è Pagina 310 di Pro ASP.NET MVC Framework da Steven Sanderson.

Non sono sicuro che vi aiuterà a capire come scrivere il test di unità, ma potrebbe aiutare a seguire il codice riflettore ...

+0

Questo è un grande articolo! Grazie! –

Problemi correlati