2009-11-27 15 views
54

Se creo un oggetto in un filtro azione personalizzata in ASP.NET MVC inASP.NET MVC Passo oggetto dalla azione personalizzata di filtro per azione

public override void OnActionExecuting(ActionExecutingContext filterContext) 
{ 
    DetachedCriteria criteria = DetachedCriteria.For<Person>(); 
    criteria.Add("stuff"); 

    // Now I need to access 'criteria' from the Action..... 

} 

c'è un modo per accedere all'oggetto dalla Azione che è attualmente in esecuzione.

risposta

43

Suggerirei metterlo nei dati del percorso.

protected override void OnActionExecuting(ActionExecutingContext filterContext) 
    { 
     filterContext.RouteData.Values.Add("test", "TESTING"); 
     base.OnActionExecuting(filterContext); 
    } 

    public ActionResult Index() 
    { 
     ViewData["Message"] = RouteData.Values["test"]; 

     return View(); 
    } 
+2

Per quanto tempo sopravvive un elemento in RouteData? Ho solo bisogno di mantenere l'oggetto per la durata dell'azione attualmente in esecuzione, o al massimo per la richiesta corrente, se questo è il modo in cui funzionano i dati dell'itinerario, allora questa è la risposta altrimenti HttpContext.Items è probabilmente migliore. – reach4thelasers

+1

RouteData è dati relativi al percorso attualmente in esecuzione (azione). Pensalo come un contenitore che rappresenta l'url della richiesta analizzato e mappato in base alle tue regole di routing. – Neal

+0

'RouteData' è sicuramente ottimo per fare questo come ho imparato oggi grazie alla tua risposta qui. Il mio bel libro MVC nero e giallo qui di fronte a me (quarta edizione) non menziona nulla o fa qualcosa di simile a questo nel capitolo intero sui filtri (o almeno non l'ho ancora trovato?). Ad ogni modo, +1 e grazie! – Funka

30

È possibile utilizzare il HttpContext:

filterContext.HttpContext.Items["criteria"] = criteria; 

E si può leggere nell'azione:

[YourActionFilter] 
public ActionResult SomeAction() 
{ 
    var criteria = HttpContext.Items["criteria"] as DetachedCriteria; 
} 
+1

Stavo pensando di usare HttpContext.Items [] e la sua una soluzione accettabile in quanto verrà cancellata al termine della richiesta. Non ero sicuro se ci fosse un posto in cui potessi immagazzinare cose che esistono solo per la durata dell'azione. – reach4thelasers

3

Set elemento in Viewdata o di un ViewModel se si passa come parametro nella vostra azione. Qui impostare la proprietà di un ViewModel

public override void OnActionExecuting(ActionExecutingContext filterContext) 
{ 
    ViewModelBase viewModel = null; 
    foreach (object parameter in filterContext.ActionParameters.Values) 
    { 
     if (parameter is ViewModelBase) 
     { 
      viewModel = (ViewModelBase)parameter; 
      break; 
     } 
    } 
    if(viewModel !=null) 
    { 
     viewModel.SomeProperty = "SomeValue"; 
    } 
} 


    public ActionResult About(ViewModelBase model) 
    { 
     string someProperty= model.SomeProperty; 
} 

Ecco la versione non tipizzata penso che si preferisce:

public override void OnActionExecuting(ActionExecutingContext filterContext) 
    { 
     filterContext.Controller.ViewData.Add("TestValue", "test"); 

    } 

     [FilterWhichSetsValue] 
     public ActionResult About() 
     { 
      string test = (string)ViewData["TestValue"]; 
      return View(); 
     } 
+0

Grazie per il tuo suggerimento. Le mie azioni non considerano ViewModelBase come parametro, e preferirei non presentarlo solo per risolvere il mio problema. – reach4thelasers

+0

Vedere il post modificato per la versione non tipizzata. Userò ancora la prima versione. Forse il parametername suona male. Può essere di qualsiasi classe e non deve essere la classe della vista tipizzata. –

59

Il better approach è descritto da Phil Haack.

Fondamentalmente questo è ciò che si fa:

public class AddActionParameterAttribute : ActionFilterAttribute 
{ 
    public override void OnActionExecuting(ActionExecutingContext filterContext) 
    { 
     base.OnActionExecuting(filterContext); 

     // Create integer parameter. 
     filterContext.ActionParameters["number"] = 123; 

     // Create object parameter. 
     filterContext.ActionParameters["person"] = new Person("John", "Smith"); 
    } 
} 

L'unico punto è che se si sta creando parametri degli oggetti, quindi la classe (in questo caso persona) deve avere un costruttore di default, altrimenti si otterrà un eccezione.

Ecco come devi usare il filtro di cui sopra:

[AddActionParameter] 
public ActionResult Index(int number, Person person) 
{ 
    // Now you can use number and person variables. 
    return View(); 
} 
+1

Un modo molto carino per farlo, penso che sia decisamente meglio della risposta accettata. Questa dovrebbe essere la risposta accettata! Grazie! – avb

+0

Perché è meglio della risposta accettata?Non sembra esserci alcuna ragione per cui questo sarebbe il caso e l'addizionale [AddActionParameter] è chiaramente un lavoro aggiuntivo che l'altro metodo non richiede per funzionare. –

+0

@ChrisBertrand È più pulito ed evita errori di compilazione nel controller, utilizzando la tipizzazione forte, ad esempio la classe 'Person'. Rende anche molto più semplice il collaudo delle unità. – niaher

Problemi correlati