2017-01-23 3 views
1

Мы превратили наше приложение в ASP.NET Core, но у меня возникла проблема с правильной заполнением ViewBag. Мы имеем следующий базовый контроллерViewBag не переходит от базового контроллера

public abstract class ControllerBase : Controller 
{ 
    public ControllerBase() 
    { 
     ViewBag.Title = "MySite"; 
    } 
    ...// lots of other stuff here also 
} 

Все наши другие контроллеры наследуют от ControllerBase, но к тому времени, мы получаем к виду и использовать следующие

@{ 
    ViewBag.Title = ViewBag.Title + " - " + Model.PageTitle; 
} 

Но в зрения ViewBag.Title равна нулю. Это не вызывает ошибки, но в итоге мы получаем только «- MyPage», а не «MySite - MyPage» для названия браузера.

Все это правильно работало в предыдущей версии .net, просто не работая сейчас в ASP.NET Core. Когда я перехожу к отладчику, я вижу, что вызывается конструктор ControllerBase, но данные ViewBag не сохраняются.

Это оставляет меня два вопроса:

  1. Есть ли что-то новое/отличается в ASP.NET Ядра, которые изменили сферу ViewBag?
  2. Каков наилучший способ исправить это? (Без добавления значения в куче мест.)

Edit: я установить отладчик остановится на первую линии базового контроллера и шагнул с ViewBag.Title набором, как мои переменные часов. Когда я выхожу, я вижу, что значение get установлено, а затем я перехожу от базового контроллера к конструктору для конкретного контроллера действий. Когда я перехожу через этот конструктор, ViewBag.Title все еще установлен. Как только я ударил первую строку метода Index(), ViewBag.Title превращается в null.

edit2: Вот простой Foo проект, иллюстрирующий проблему https://github.com/nurdyguy/ViewBagIssue

+0

Как насчет того, чтобы вы прошли через свой код и посмотрели, где 'ViewBag.Title' переписывается? – CodeCaster

+0

Я не вижу, чтобы его переписывали где угодно. В любом месте (кроме базового контроллера) значение равно null. – nurdyguy

+0

И вы уверены, что контроллер, отлаживаемый на самом деле, наследует 'ControllerBase'? В зеркале нет ничего особенного, это просто обычная собственность. Наследование не должно нарушать этого. – CodeCaster

ответ

3

Я до сих пор не знаю, почему это происходит, но здесь обходной путь я нашел. Создать OnActionExecuting фильтр:

using Microsoft.AspNetCore.Mvc; 
using Microsoft.AspNetCore.Mvc.Filters; 

namespace MyProj.Filters 
{ 
    public class ViewBagFilter : IActionFilter 
    { 
     public void OnActionExecuting(ActionExecutingContext context) 
     { 
      // do something before the action executes 
      var controller = context.Controller as Controller; 
      controller.ViewBag.Title = "MyPage"; 
     } 

     public void OnActionExecuted(ActionExecutedContext context) 
     { 
      // do something after the action executes 
     } 
    } 
} 

и добавьте следующие строки в методе ConfigureServices в Startup.cs:

services.AddMvc(options => 
{ 
    options.Filters.Add(typeof(ViewBagFilter)); 
    ... // you may have more here... 
}); 

Вы заметите var controller = context.Controller as Controller; имеет оттенок, так как объект управления на context является object но достаточно легко исправить.

Я отправлю сообщение здесь, если я когда-либо узнаю, в чем именно состояла проблема. Хорошая охота!

+0

Вы когда-нибудь могли понять, что вызвало это? Я сейчас испытываю одну и ту же проблему ... Я мог бы пойти по пути «IActionFilter», но предпочел бы установить его в конструкторе базового контроллера, так как у меня есть несколько разных базовых контроллеров, которые добавляют другое поведение. –

+0

Насколько я мог судить, это была ошибка. Мы закончили тем, что использовали обходной путь выше. В какой-то момент я намеревался представить ошибку в github, но не думаю, что когда-либо делал. – nurdyguy

+1

Ах. Похоже, есть ошибка. Сформулировал его по дизайну: https://github.com/aspnet/Mvc/issues/1422#issuecomment-59997202. Я использую ваше решение фильтра. Работает как шарм. Благодаря! –

Смежные вопросы