Jak ustawić właściwości ViewBag dla wszystkich widoków bez użycia klasy bazowej dla kontrolerów?
W przeszłości przyklejałem wspólne właściwości, takie jak obecny użytkownik, do ViewData/ViewBag w sposób globalny, ponieważ wszystkie kontrolery dziedziczą ze wspólnego kontrolera bazowego.
To pozwoliło mi użyć IoC na kontrolerze bazy, a nie tylko dotrzeć do global shared dla takich danych.
Zastanawiam się, czy istnieje alternatywny sposób wstawiania tego typu kodu do rurociągu MVC?
8 answers
Nie próbowałem przeze mnie, ale możesz spojrzeć na rejestrowanie widoków , a następnie ustawianie danych widoku podczas procesu aktywacji.
Ponieważ widoki są rejestrowane w locie, składnia rejestracji nie pomaga w połączeniu się ze zdarzeniem Activated
, więc musisz skonfigurować je w Module
:
class SetViewBagItemsModule : Module
{
protected override void AttachToComponentRegistration(
IComponentRegistration registration,
IComponentRegistry registry)
{
if (typeof(WebViewPage).IsAssignableFrom(registration.Activator.LimitType))
{
registration.Activated += (s, e) => {
((WebViewPage)e.Instance).ViewBag.Global = "global";
};
}
}
}
To może być jedna z tych sugestii typu"only tool' s a hammer " ode mnie; mogą być prostsze sposoby na uzyskanie tego.
Edit: Alternate, less podejście kodowe - wystarczy dołączyć do kontrolera
public class SetViewBagItemsModule: 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.Config = e.Context.Resolve<Config>();
viewBag.Identity = e.Context.Resolve<IIdentity>();
};
}
}
}
Edit 2: inne podejście, które działa bezpośrednio z kodu rejestracyjnego kontrolera:
builder.RegisterControllers(asm)
.OnActivated(e => {
dynamic viewBag = ((Controller)e.Instance).ViewBag;
viewBag.Config = e.Context.Resolve<Config>();
viewBag.Identity = e.Context.Resolve<IIdentity>();
});
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-05-20 00:57:52
Najlepszym sposobem jest użycie ActionFilterAttribute i zarejestrowanie własnej klasy w Twoim global. asax (Application_Start)
public class UserProfilePictureActionFilter : ActionFilterAttribute
{
public override void OnResultExecuting(ResultExecutingContext filterContext)
{
filterContext.Controller.ViewBag.IsAuthenticated = MembershipService.IsAuthenticated;
filterContext.Controller.ViewBag.IsAdmin = MembershipService.IsAdmin;
var userProfile = MembershipService.GetCurrentUserProfile();
if (userProfile != null)
{
filterContext.Controller.ViewBag.Avatar = userProfile.Picture;
}
}
}
Zarejestruj swoją klasę niestandardową w global. asax (Application_Start)
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
GlobalFilters.Filters.Add(new UserProfilePictureActionFilter(), 0);
}
Następnie można go używać we wszystkich widokach
@ViewBag.IsAdmin
@ViewBag.IsAuthenticated
@ViewBag.Avatar
Jest też inny sposób
Tworzenie metody rozszerzenia na HtmlHelper
[Extension()]
public string MyTest(System.Web.Mvc.HtmlHelper htmlHelper)
{
return "This is a test";
}
Następnie można go używać we wszystkich widokach
@Html.MyTest()
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-09-21 05:42:10
Ponieważ właściwości ViewBag są z definicji powiązane z prezentacją widoku i dowolną logiką widoku świetlnego, która może być konieczna, utworzyłbym bazową stronę WebViewPage i ustawił właściwości przy inicjalizacji strony. Jest bardzo podobny do koncepcji kontrolera bazowego dla powtarzającej się logiki i wspólnej funkcjonalności, ale dla twoich poglądów: {]}
public abstract class ApplicationViewPage<T> : WebViewPage<T>
{
protected override void InitializePage()
{
SetViewBagDefaultProperties();
base.InitializePage();
}
private void SetViewBagDefaultProperties()
{
ViewBag.GlobalProperty = "MyValue";
}
}
A następnie w \Views\Web.config
ustaw właściwość pageBaseType
:
<system.web.webPages.razor>
<host factoryType="System.Web.Mvc.MvcWebRazorHostFactory, System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
<pages pageBaseType="MyNamespace.ApplicationViewPage">
<namespaces>
<add namespace="System.Web.Mvc" />
<add namespace="System.Web.Mvc.Ajax" />
<add namespace="System.Web.Mvc.Html" />
<add namespace="System.Web.Routing" />
</namespaces>
</pages>
</system.web.webPages.razor>
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-01-11 23:46:10
Brandon ' s post is right on the money. W rzeczywistości, chciałbym pójść o krok dalej i powiedzieć, że należy po prostu dodać swoje wspólne obiekty jako Właściwości{[2] } z podstawowej strony WebViewPage , więc nie trzeba rzucać elementów z worka widoków w każdym widoku. Wykonuję moją aktualną konfigurację użytkownika w ten sposób.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-04-07 04:29:23
Możesz użyć niestandardowego ActionResult:
public class GlobalView : ActionResult
{
public override void ExecuteResult(ControllerContext context)
{
context.Controller.ViewData["Global"] = "global";
}
}
Lub nawet ActionFilter:
public class GlobalView : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
filterContext.Result = new ViewResult() {ViewData = new ViewDataDictionary()};
base.OnActionExecuting(filterContext);
}
}
Miał otwarty projekt MVC 2, ale obie techniki nadal mają zastosowanie z niewielkimi zmianami.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-03-28 00:42:37
Jeśli chcesz sprawdzić czas kompilacji i intellisense dla właściwości w Twoich widokach, to ViewBag nie jest dobrym rozwiązaniem.
Rozważ klasę BaseViewModel i niech inne modele widoku dziedziczą z tej klasy, np.:
Base ViewModel
public class BaseViewModel
{
public bool IsAdmin { get; set; }
public BaseViewModel(IUserService userService)
{
IsAdmin = userService.IsAdmin;
}
}
View specific ViewModel
public class WidgetViewModel : BaseViewModel
{
public string WidgetName { get; set;}
}
Teraz kod widoku może uzyskać dostęp do właściwości bezpośrednio w widoku
<p>Is Admin: @Model.IsAdmin</p>
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-01-22 02:35:25
Nie musisz zadzierać z akcjami ani zmieniać modelu, wystarczy użyć kontrolera bazowego i rzucić istniejący kontroler z widoku układu.
Utwórz kontroler bazowy z żądanymi wspólnymi danymi (tytuł/strona/lokalizacja itp.) i inicjalizacją akcji...
public abstract class _BaseController:Controller {
public Int32 MyCommonValue { get; private set; }
protected override void OnActionExecuting(ActionExecutingContext filterContext) {
MyCommonValue = 12345;
base.OnActionExecuting(filterContext);
}
}
Upewnij się, że każdy kontroler używa kontrolera bazowego...
public class UserController:_BaseController {...
Wyrzuć istniejący kontroler bazowy z kontekstu widoku na stronie _Layout.cshml
...
@{
var myController = (_BaseController)ViewContext.Controller;
}
Teraz możesz odnosić się do wartości w swoim kontroler bazowy ze strony układu.
@myController.MyCommonValue
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-07-25 15:49:39
Uznałem następujące podejście za najbardziej efektywne i daje doskonałą kontrolę przy użyciu _ViewStart.plik chtml i instrukcje warunkowe w razie potrzeby:
_ViewStart :
@{
Layout = "~/Views/Shared/_Layout.cshtml";
var CurrentView = ViewContext.Controller.ValueProvider.GetValue("controller").RawValue.ToString();
if (CurrentView == "ViewA" || CurrentView == "ViewB" || CurrentView == "ViewC")
{
PageData["Profile"] = db.GetUserAccessProfile();
}
}
ViewA :
@{
var UserProfile= PageData["Profile"] as List<string>;
}
Uwaga :
PageData sprawdzi się doskonale w widokach, jednak w przypadku PartialView, będzie musiał zostać przekazany z widoku do dziecko częściowe.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-09-07 21:20:24