Альтернатива ViewBag.Title в ASP.NET MVC 3 - PullRequest
24 голосов
/ 08 августа 2011

По умолчанию новый шаблон проекта для ASP.NET MVC 3 добавляет следующее к макету по умолчанию (главная страница в бритве):

<title>@ViewBag.Title</title>

Представление должно содержать следующее, чтобы назначить заголовокpage, например:

@{
     ViewBag.Title = "Log On";
}

Возможно, это просто мои собственные предпочтения, но я считаю, что использование ViewBag для удержания заголовка немного неправильно (я слишком много думаю о магии).Поэтому мой вопрос таков: рекомендуется ли это людям, использующим ASP.NET MVC 3 и бритву (используя динамический пакет свойств), или вы выбираете что-то более строго типизированное (возможно, с использованием собственного базового класса?)

Ответы [ 8 ]

26 голосов
/ 08 августа 2011

Я не думаю, что есть что-то плохое с функцией обработки заголовков по умолчанию, которая поставляется с asp.net MVC 3, это нормально.

Я лично делаю это (написано ниже) для обработки заголовка, Я не одобряю приведенный ниже код и не говорю, что он лучше, чем функциональность по умолчанию, это просто предпочтение.

Мастер

<title>
    @RenderSection("Title");
</title>

View

@section Title
{
    write title
}

Одна вещь, которую я мог бы предложить, чтобы улучшить функциональность по умолчанию

@{
    string pageTitle = @ViewBag.Title ?? "Title Not Set";
}
<title>@pageTitle</title>

Поэтому, когда вы забудете добавить его в viewbag, на странице будет отображаться заголовок = Title Not Set

Можно также создать базовый класс, а затем сделать все ваши контроллеры наследуемыми от этого базового класса. Но я думаю, что это приносит столько боли за title.

7 голосов
/ 08 августа 2011

ViewBag для заголовка прекрасно (я бы даже сказал, что это цель использования ViewBag) - динамика не является абсолютным злом. «Заголовок» общеизвестен, вряд ли изменится и даже предопределен в шаблонах представления. Я лично использую следующий заголовок:

<title>@(ViewBag.Title == null ? string.Empty : ViewBag.Title + " | ")Site Name</title>

Если вы беспокоитесь о неправильном наборе ViewBag.Title, вы можете сделать его строгим типом, создав пользовательский WebViewPage, но вам все равно придется использовать ViewBag или, возможно, HttpContext.Items внутри этого строго типизированного свойства, поскольку существует несколько экземпляров WebViewPage создано во время рендеринга IIRC.

Я бы рекомендовал придерживаться ViewBag, создавая собственный WebViewPage, потому что это кажется излишним - даже создание отдельного свойства для него, если у вас уже есть пользовательский WebViewPage, на мой взгляд, просто бесполезное усложнение - и это исходит от человека, который часто переигрывает.

3 голосов
/ 22 декабря 2016

Я также вообще не использую ViewBag.

В верхней части _Layout.shtml ...

@model <YourWebAppNameSpace>.Models.Base.EveryPageViewModel

В _Layout.shtml ...

<title>@Model.Title</title>

в вашей модели ...

/// <summary>
/// Index View Model
/// </summary>
public class IndexViewViewModel : EveryPageViewModel {

}

в EveryPageViewModel

/// <summary>
/// Every Page View Model
/// </summary>
public abstract class EveryPageViewModel {
    /// <summary>
    /// Title
    /// </summary>
    public string Title { get; set; }
    /// <summary>
    /// Sub Title
    /// </summary>
    public string SubTitle { get; set; }
}

в действии вашего контроллера

    /// <summary>
    /// Index
    /// </summary>
    /// <returns></returns>
    public ActionResult Index() {
        var model = new IndexViewViewModel();
        model.Title = "Home";
        return View(model);
    }
2 голосов
/ 20 марта 2015

Мне нравится создавать атрибуты PageTitle ActionFilter, а не редактировать отдельные ViewBags

Использование: сохранять вид неизменным

<title>@ViewBag.Title</title>

Для заголовка страницы всего контроллера:

[PageTitle("Manage Users")]
public class UsersController : Controller {
    //actions here
}

Для отдельных видов:

public class UsersController : Controller {
    [PageTitle("Edit Users")]
    public ActionResult Edit(int id) {
          //method here
    }
}

Код атрибута:

public class PageTitleAttribute : ActionFilterAttribute
{
    private readonly string _pageTitle;
    public PageTitleAttribute(string pageTitle)
    {
        _pageTitle = pageTitle;
    }

    public override void OnActionExecuted(ActionExecutedContext filterContext)
    {
        base.OnActionExecuted(filterContext);
        var result = filterContext.Result as ViewResult;
        if (result != null)
        {
            result.ViewBag.Title = _pageTitle;
        }
    }
}

Прост в управлении и работает как шарм.

1 голос
/ 08 августа 2011

В использовании ViewBag.Title = "My Title" нет ничего плохого;

Все, что вы делаете, это используете динамическое свойство.

Вопрос в том, где информация должна быть «объявлена».

Т.е. где он наиболее доступен для текущих целей.

Если это для каждой страницы, то это правильное место.

Если, однако, заголовок страницы может быть получен из Модели, то вам следует это сделать.

В этом случае я бы, вероятно, использовал бы базовый класс для используемой вами ViewModel и создал бы там свойство PageTitle, содержащее логику для получения заголовка страницы из свойств в модели.

Итак:

<title>Model.PageTitle</title>

Таким образом, лошади для курсов и не бойтесь использовать динамические свойства ... до тех пор, пока вы понимаете, что они и что они делают.

1 голос
/ 08 августа 2011

мы предпочитаем настройку строгого заголовка .. несколько примеров из нашего класса BaseController. (Страница определяет модальный инкапсулированный вид)

protected override ViewResult View(string viewName, string masterName, object model)
{
    if (model is Page)
    {
        ViewBag.Title = ((Page)model).Title;
        //HACK: SEO
        //TODO: SEO
    }
    return base.View(viewName, masterName, model);
}
1 голос
/ 08 августа 2011

Я бы сказал, что, если вы хотите установить только заголовок, можно использовать ViewBag. Ну, может быть, не только - максимум 2-3 свойства.

Но если вы начнете видеть, что вы устанавливаете все больше и больше (общих) свойств в каждом действии контроллера, я бы выбрал строго типизированный «класс ViewModelBase». Но это только я.

1 голос
/ 08 августа 2011

Лично для меня, я думаю, что этот случай является приемлемым использованием ViewBag.Он ограничен «хорошо известным» свойством и, скорее всего, не вызовет никаких проблем в будущем.В конце концов, все дело в том, чтобы быть прагматичным и находить способ быть максимально быстрым.На мой взгляд, наличие базового класса, в котором вам нужно установить заголовок, было бы слишком большим кодом, чтобы стоить безопасности типов.

Удачи!

...