2014-12-05 11 views
7

Come posso accedere ad alcune proprietà di ViewBag su tutte le mie viste? Voglio avere alcune informazioni come il nome utente corrente, ecc accessibile ovunque, ma senza dover definire in modo specifico le proprietà in ogni metodo ActionResult sul mio progettoAccesso alla proprietà Viewbag su tutte le viste

+0

È possibile creare un ActionFilter che aggiunge le proprietà 'ViewBag' a ogni richiesta –

risposta

13

Il modo migliore e diretto per soddisfare le tue esigenze è creare un Custom Base Controller ed eredita il controller da questo controller di base.

public class MyBaseController : Controller 
{ 
    protected override void OnActionExecuting(ActionExecutingContext filterContext) 
    { 
     ViewBag.someThing = "someThing"; //Add whatever 
     base.OnActionExecuting(filterContext); 
    } 
} 

Ora, invece di ereditare Controller classe, erediterà MyBaseController nel controller come indicato: -

public class MyOtherController : MyBaseController 
{ 
    public ActionResult MyOtherAction() 
    { 
     //Your Stuff 
     return View(); 
    } 
    //Other ActionResults 
} 
+1

Penso che questo sia meglio in quanto è il più simile a un controller normale (accedendo alla stessa cosa che potrei fare su uno), inoltre è meglio per la mia particolare applicazione visto che sto già usando un controller di base per l'internazionalizzazione. –

6

Un modo: creare un attributo personalizzato, quindi è possibile applicarlo a livello globale nel FilterConfig. Quindi non devi fare nulla nei tuoi controller.

public class MyCustomViewActionFilter : ActionFilterAttribute 
{ 
    public override void OnActionExecuting(ActionExecutingContext filterContext) 
    { 
     dynamic ViewBag = filterContext.Controller.ViewBag; 

     ViewBag.Id = "123"; 
     ViewBag.Name = "Bob"; 
    } 
} 

In App_Start/FilterConfig.cs:

public static void RegisterGlobalFilters(GlobalFilterCollection filters) 
    { 
     filters.Add(new MyCustomViewActionFilter()); 
    } 

Un altro modo, se tutto ciò che serve è l'informazione dell'utente. È possibile aggiungere il seguente alla parte superiore della visualizzazione:

@using Microsoft.AspNet.Identity 

quindi accedere il nome utente utilizzando la seguente sintassi:

@User.Identity.GetUserName() 

Si può anche ignorare l'attuazione IPrincipal e fornire le proprie proprietà e metodi per aggiungere più informazioni che devi rendere.

UPDATE: guardando MVC 6 in Asp.Net vSuccessivamente questo viene effettivamente inserito nel framework. http://www.asp.net/vnext/overview/aspnet-vnext/vc#inj

15

È possibile ottenere ciò che si desidera in diversi modi, ognuno con i suoi pro e contro.

1. Con una classe base

public class BaseController : Controller 
{ 
    protected override ViewResult View(IView view, object model) 
    { 
     this.ViewBag.MyProperty = "value"; 
     return base.View(view, model); 
    } 
} 

PRO: abbastanza semplice da implementare, poche righe di codice, altamente riutilizzabile, può essere optato-out a volontà (vedi commenti qui sotto) .

CONS: Essere costretti a derivare tutti i controller da una classe base potrebbe avere un impatto, soprattutto se sono già presenti molti controller e/o è necessario derivarli da altre classi base.

2. Con un modulo

public class ViewBagPropertyModule: Module 
{ 
    protected override void AttachToComponentRegistration(IComponentRegistry cr, 
                IComponentRegistration reg) 
    { 
     Type limitType = reg.Activator.LimitType; 
     if (typeof(Controller).IsAssignableFrom(limitType)) 
     { 
      registration.Activated += (s, e) => 
      { 
       dynamic viewBag = ((Controller)e.Instance).ViewBag; 
       viewBag.MyProperty= "value"; 
      }; 
     } 
    } 
} 

PRO: Nessuno io sappia.

CONS: Nessuno Ne sono a conoscenza (a parte essere un po 'controintuitivo).

3. Con un RegisterController Hook

builder.RegisterControllers(asm) 
    .OnActivated(e => { 
     dynamic viewBag = ((Controller)e.Instance).ViewBag; 
     viewBag.MyProperty = "value"; 
    }); 

PRO: Veloce, sicuro, riutilizzabile: ideale per qualsiasi modello di progettazione CIO.

CONS: Non sempre adatto per piccoli progetti e/o semplici siti Web: se non si utilizza IoC spesso non si utilizza RegisterController.

4. Con un attributo ActionFilter

public class MyPropertyActionFilter : ActionFilterAttribute 
{ 
    public override void OnResultExecuting(ResultExecutingContext filterContext) 
    { 
     filterContext.Controller.ViewBag.MyProperty = "value"; 
    } 
} 

e poi nel file Global.asax.cs:

protected void Application_Start() 
{ 
    AreaRegistration.RegisterAllAreas(); 
    GlobalFilters.Filters.Add(new MyPropertyActionFilter(), 0); 
} 

PRO: facilmente il metodo meno invadente tra quelli menzionati .

CONS: Nessuno ne sono a conoscenza.

Ho anche scritto an article spiegando tutti i metodi di cui sopra.

+0

Il cono dell'implementazione BaseController è un professionista allo stesso tempo: offre un opt-out (non ereditando il BaseController) che gli altri metodi non sembrano offrire. –

+1

Sì, questo è un vantaggio di sicuro :) Aggiornato sia la risposta che l'articolo. – Darkseal

+0

ciao, mi piacerebbe utilizzare il 4o metodo, ma il mio viewbag prende il suo valore da una query linq. Come lo posso fare? grazie – touinta

0

mia soluzione attuale:

Creare un controller di base con tutte le proprietà necessarie (molto utile e consigliabile).

public abstract class BaseController : Controller { 
    public string MyProperty { get; set; } 
} 

Eredita tutti i controller, dal controller di base.

public class MyController : BaseController { 
    //you can read your property here 
} 

Nel vostro punto di vista, aggiungere questa riga subito dopo la frase "@model":

@{ BaseController ctr = ViewContext.Controller as BaseController; } 

Ora, è possibile utilizzare la proprietà a suo avviso, non popolare il ViewBag, senza la necessità di controllare e gettato i valori ViewBag, ecc

Nella visualizzazione, è possibile utilizzare un semplice espressione in linea:

@(ctr.MyProperty) 

Oppure fai qualche logica magica ...

@{ 
    if(ctr.MyProperty == "whatelse") { 
     //do ... 
    } 
} 

Facile, veloce e confortevole.