Есть несколько особенностей, которые необходимо понимать, когда имеешь дело с тегом заголовка (<title></title>) в мастер-страницах (master pages) используя Web Forms и ASP.NET MVC. Они связаны с использованием котрола HtmlHead, больше известного как <head runat="server" /> .
Первая особенность связана с местом, где ставить ContentPlaceHolder, внутри тега заголовка, как это сделано в стандартном шаблоне в ASP.NET MVC:
<%@ Master … %>
<html> <head runat="server"> <title> <asp:ContentPlaceHolder ID="titleContent" runat="server" /> </title> </head> ...
Это позволяет нам в задавать тег заголовока из любого места на странице:
<asp:Content ContentPlaceHolderID="titleContent" runat="server"> Home </asp:Content>
Но что произойдет, если определить постоянную часть заголовка в мастер-странице? Например, необходимо добавить к заголовку всех стрниц суффикс “, – MySite”. Если сделать так:
<%@ Master ... %> <html> <head runat="server"> <title> <asp:ContentPlaceHolder ID="titleContent" runat="server" /> - MySite </title> </head> ...
Запустить страницу, увидим, что – MySite отсустствует. Это, является “индивидуальной оссобенностью” (quirk) HtmlHead контроля и происходит потому, что тег заголовка в HtmlHead контроле является самим контролом, что в сою очередь связано с работой метода AddParsedSubObject. Фактически, содержимым HtmlHead могут быть только другие контролы.
Исправить это довольно просто. Добавить свой текст в LiteralControl :
<%@ Master ... %> <html> <head runat="server"> <title> <asp:ContentPlaceHolder ID="titleContent" runat="server" /> <asp:LiteralControl runat="server" Text=" - MySite" /> </title> </head> ...
Вторая особенность связана с каким HeaderControl на выходе будет действительно валидная HTML разметка.
Если оставить <head runat=”server”> </ head> пустым, получим уведомление о пустом теге <title> из-за того, что во всех дочерних контролах не обнаруживается HtmlTitle конторола. Это может происходить при попытке использовать ContentPlaceHolder для установки содержания тега заголовка. Например так:
<%@ Master ... %> <html> <head runat="server"> <asp:ContentPlaceHolder ID="headContent" runat="server"> <title>Testing</title> </asp:ContentPlaceHolder> </head> ...
Такой подход является наиболее аккуратным, поскольку позволяет не только установить заголовок страницы из любого места, но и вывести любое другое содержание в <head>.
Однако, посмотрев на код, получаемый на выходе, увидим, что там оказывается два тега <title>, один из которых пустой.
Принимая во внимание то, о чем упоминалось выше, причина становится очевидной. Она в HtmlHead контроле, который содержит тег title в дочернем контроле. Не обнаружив заголовка, добавляется пустой.
Теперь, понимая, как работает контрол HtmlHead, что он позволяет размещать только контролы внутри себя, в то же время вставить текст, можно используя ContentPlaceHolder. Хоть это и выглядит, как тег title внутри ContentPlaceHolder, это не HTMLTitle контрол. Это просто текст, а HtmlHead контрол не будет его разбирать.
Именно поэтому, как правило, можно использовать следующий код в мастер-странице:
<%@ Master ... %> <html> <head runat="server"> <title><asp:ContentPlaceHolder ID="titleContent" runat="server" /></title> <asp:ContentPlaceHolder ID="headContent" runat="server"> </asp:ContentPlaceHolder> </head> ...Источник: TipJar: Title Tags and Master Pages

