{"id":4929,"date":"2016-11-13T06:00:22","date_gmt":"2016-11-13T05:00:22","guid":{"rendered":"https:\/\/u-labs.de\/portal\/?p=4929"},"modified":"2016-11-09T15:49:26","modified_gmt":"2016-11-09T14:49:26","slug":"asp-net-core-viewbag-eigenschaft-im-konstruktur-eines-controllers-setzen","status":"publish","type":"post","link":"https:\/\/u-labs.de\/portal\/asp-net-core-viewbag-eigenschaft-im-konstruktur-eines-controllers-setzen\/","title":{"rendered":"ASP.NET Core: ViewBag-Eigenschaft im Konstruktur eines Controllers setzen"},"content":{"rendered":"<p>In einer MVC-Anwendung kommt es immer wieder vor, dass man bestimmte Daten im gesamten Controller ben\u00f6tigt. Beispielsweise f\u00fcr eine Info-Box oder Sidebar, die man mittels ViewBag\/ViewData unabh\u00e4ngig vom Model der jeweiligen Aktionen \u00fcbergibt. Als objektorientierter Entwickler kommt man hier schnell auf die Idee, die Daten einfach im Konstruktur zu laden. Jedoch ist es nicht m\u00f6glich, im Konstruktor eines Controllers Eigenschaften zu ver\u00e4ndern, die in Relation zur aktuellen Anfrage stehen.<\/p>\n<p>Folgendes Beispiel zeigt dies:<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\n    class MyController : Controller {\r\n        public MyController() {\r\n            ViewBag.GlobalProperty = &quot;SomeValue&quot;;\r\n        }\r\n\r\n        public IActionResult DoSomething() {\r\n            return View();\r\n        }\r\n    }\r\n<\/pre>\n<p><code class=\"\" data-line=\"\">ViewBag.GlobalProperty<\/code> m\u00f6chten wir nun in einer Razor-Ansicht verwenden. Ob es sich um eine globale Layout-Datei (z.B. f\u00fcr eine Breadcrumb) oder die Ansicht der Aktion <code class=\"\" data-line=\"\">DoSomething<\/code> handelt, spielt keine Rolle: <code class=\"\" data-line=\"\">@ViewBag.GlobalProperty<\/code> ist in beiden F\u00e4llen <code class=\"\" data-line=\"\">null<\/code> &#8211; Obwohl der Controller aufgerufen und die Eigenschaft dort gesetzt wird. Wie l\u00f6sen wir das Problem also, ohne eine Hilfsmethode in jeder Action auszuf\u00fchren und damit das\u00a0<em>DRY (Dont repeat yourself)<\/em> Prinzip zu verletzen?<\/p>\n<h4><strong><em>OnActionExecuting<\/em> schafft Abhilfe<\/strong><\/h4>\n<p>F\u00fcr diese F\u00e4lle gibt es die <code class=\"\" data-line=\"\">OnActionExecuting<\/code> Methode, die jede von <code class=\"\" data-line=\"\">Controller<\/code> erbende Klasse \u00fcberschreiben kann. Sie wird wie der Name schon sagt vor dem Aufruf einer Aktion des Controllers gefeuert. Hier sind alle Eigenschaften, die sich auf die aktuelle Anfrage beziehen, initialisiert. Man kann daher Problemlos auf Attribute wie <code class=\"\" data-line=\"\">ViewBag<\/code> zugreifen, und diese ver\u00e4ndern:<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\n    class MyController :Controller {            \r\n        public override void OnActionExecuted(ActionExecutedContext context) {\r\n            ViewBag.GlobalProperty = &quot;SomeValue&quot;;\r\n        }\r\n\r\n        public IActionResult DoSomething() {\r\n            return View();\r\n        }\r\n    }\r\n<\/pre>\n<p>Nun ist der Zugriff auf <code class=\"\" data-line=\"\">ViewBag.GlobalProperty<\/code> problemlos aus jeder Razor-Ansicht heraus m\u00f6glich.<\/p>\n<h4><strong>Alternativ: DataAnnotations-Filter verwenden<\/strong><\/h4>\n<p>Je nach Anwendungsfall ist das \u00fcberschreiben der <code class=\"\" data-line=\"\">OnActionExecuted<\/code> Methode im Controller nicht immer die beste L\u00f6sung. Um etwa die Navigationsstruktur einer Breadcrumb zu erstellen, m\u00fcsste man die Methoden in jeden Controller kopieren &#8211; oder von einem Basis-Controller erben, der diese enth\u00e4lt. Diese Variante ist wenig flexibel, da .NET keine Mehrfachvererbung unterst\u00fctzt. Besser geeignet ist die Verwendung eines auf den vom EntityFramework bekannten DataAnnotations-Attribute basierten Filtern.<\/p>\n<p>Hier haben wir ebenfalls die M\u00f6glichkeit, die OnActionExecuted-Methode des Controllers zu \u00fcberschreiben.\u00a0Dies bindet uns nicht an die Limitierungen von Vererbung und l\u00e4sst sich flexibel einsetzen. Der Aufwand ist kaum h\u00f6her, wie folgendes Beispiel zeigt:<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\n    public class BreadCrumbAttribute : ResultFilterAttribute {\r\n        readonly string pageName;\r\n\r\n        public BreadCrumbAttribute(string pageName) {\r\n            this.pageName = pageName;\r\n        }\r\n\r\n        public override void OnResultExecuting(ResultExecutingContext context) {\r\n            var controller = context.Controller as Controller;\r\n            controller.ViewBag.BreadCrumbPageName = pageName;\r\n            base.OnResultExecuting(context);\r\n        }\r\n    }\r\n<\/pre>\n<p>Nun muss lediglich das DataAnnotation-Attribute <code class=\"\" data-line=\"\">[BreadCrumb]<\/code> f\u00fcr den Controller gesetzt werden:<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\n    &#x5B;BreadCrumb(&quot;Verwaltungsbereich&quot;)]\r\n    public class MyController : Controller {\r\n        public IActionResult DoSomething() {\r\n            return View();\r\n        }\r\n    }\r\n<\/pre>\n<p>F\u00fcr alle Actions des <code class=\"\" data-line=\"\">MyControllers<\/code> wird <code class=\"\" data-line=\"\">ViewBag.BreadCrumbPageName<\/code> dadurch auf <i>Verwaltungsbereich<\/i> gesetzt.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In einer MVC-Anwendung kommt es immer wieder vor, dass man bestimmte Daten im gesamten Controller ben\u00f6tigt. Beispielsweise f\u00fcr eine Info-Box oder Sidebar, die man mittels ViewBag\/ViewData unabh\u00e4ngig vom Model der jeweiligen Aktionen \u00fcbergibt. Als objektorientierter Entwickler kommt man hier schnell auf die Idee, die Daten einfach im Konstruktur zu laden. Jedoch ist es nicht m\u00f6glich, &#8230;<\/p>\n","protected":false},"author":5,"featured_media":4930,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[61],"tags":[522,159,571],"class_list":["post-4929","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-softwareentwicklung","tag-asp-net-core","tag-mvc","tag-viewbag"],"_links":{"self":[{"href":"https:\/\/u-labs.de\/portal\/wp-json\/wp\/v2\/posts\/4929","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/u-labs.de\/portal\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/u-labs.de\/portal\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/u-labs.de\/portal\/wp-json\/wp\/v2\/users\/5"}],"replies":[{"embeddable":true,"href":"https:\/\/u-labs.de\/portal\/wp-json\/wp\/v2\/comments?post=4929"}],"version-history":[{"count":25,"href":"https:\/\/u-labs.de\/portal\/wp-json\/wp\/v2\/posts\/4929\/revisions"}],"predecessor-version":[{"id":4999,"href":"https:\/\/u-labs.de\/portal\/wp-json\/wp\/v2\/posts\/4929\/revisions\/4999"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/u-labs.de\/portal\/wp-json\/wp\/v2\/media\/4930"}],"wp:attachment":[{"href":"https:\/\/u-labs.de\/portal\/wp-json\/wp\/v2\/media?parent=4929"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/u-labs.de\/portal\/wp-json\/wp\/v2\/categories?post=4929"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/u-labs.de\/portal\/wp-json\/wp\/v2\/tags?post=4929"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}