Особенности использования тега title в Master Pages

апреля 7, 2009

Есть несколько особенностей, которые необходимо понимать, когда имеешь дело с тегом заголовка (<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

Отображение дерева (tree view) с помощью ASP.NET MVC Framework

марта 18, 2009

 

Перевод статьи:Rendering a tree view using the MVC Framework

Дерево (tree view) – это прекрасный метод отображения вложенных и древовидных структур данных. Например:

treeview

Создадим HTML helper, который будет предствлять древовидную структуру, как вложенный неупорядоченный HTML список. Начнем с интерфейса для представления узла дерева. Этот интерфейс назовем IComposite, в соответсвии с шаболоном проектирования компановщик.

public interface IComposite<T>
{
   T Parent { get; }
   ISet<T> Children { get; }
}

Теперь убедимся, что наша сущность реализует этот интерфейс на простом примере:

public class CompositeThing : IComposite<CompositeThing>
{
  public CompositeThing()
  {
      Children = newHashedSet<CompositeThing>();
  }
  public string Name { get; set; }
  public CompositeThing Parent { get; set; }
  public ISet<CompositeThing> Children { get; set; }
}

Теперь нам необходимо получить граф объекта из базы данных. Как это сделать, может являться темой для отдельной статьи, но наиболее приятный и простой путь это использование LINQ-to-SQL и NHibernate. И так, получив данные, можно передать их для последующего отображения:

<%= Html.RenderTree(ViewData.Model.CompositeThings, thing => thing.Name) %>

Код метода RenderTree, расширяющего HtmlHelper:

public static class TreeRenderHtmlHelper
{
  public static string RenderTree<T>(
     this HtmlHelper htmlHelper,
     IEnumerable<T> rootLocations,
     Func<T> locationRenderer)
       where T : IComposite<T>
    {
       return new TreeRenderer<T>(rootLocations, locationRenderer).Render();
    }
}
public class TreeRenderer<T> where T : IComposite<T>
{
   private readonly Func<T, string> locationRenderer;
    private readonly IEnumerable<T> rootLocations;
    private HtmlTextWriter writer;
    public TreeRenderer(
        IEnumerable<T> rootLocations,
        Func<T, string> locationRenderer)
    {
        this.rootLocations = rootLocations;
        this.locationRenderer = locationRenderer;
    }
    public string Render()
    {
        writer = new HtmlTextWriter(new StringWriter());
        RenderLocations(rootLocations);
        return writer.InnerWriter.ToString();
    }
    /// <summary>
    /// Recursively walks the location tree outputting it as hierarchical UL/LI elements
    /// </summary>
    /// <param name="locations"></param>
    private void RenderLocations(IEnumerable<T> locations)
    {
        if (locations == null) return;
        if (locations.Count() == 0) return;
        InUl(() => locations.ForEach(location => InLi(() =>
        {
            writer.Write(locationRenderer(location));
            RenderLocations(location.Children);
        })));
    }
    private void InUl(Action action)
    {
        writer.WriteLine();
        writer.RenderBeginTag(HtmlTextWriterTag.Ul);
        action();
        writer.RenderEndTag();
        writer.WriteLine();
    }
    private void InLi(Action action)
    {
        writer.RenderBeginTag(HtmlTextWriterTag.Li);
        action();
        writer.RenderEndTag();
        writer.WriteLine();
    }
}

Результат работы метода в HTML выглядит так:

<html>
<head>
    <title>Tree View</title>
    <link href="jquery.treeview.css" rel="stylesheet" type="text/css" />
    <script src="jquery-1.2.6.min.js" type="text/javascript"></script>
    <script src="jquery.treeview.js" type="text/javascript"></script>
    <script type="text/javascript">
        $(function() {
            $("#treeview ul").treeview();
        });
    </script>
</head>
<body style="font-family : Arial; ">
    <h1>
        Tree View
    </h1>
    <div id="treeview">
        <ul>
            <li>Root
                <ul>
                    <li>First Child
                        <ul>
                            <li>First Grandchild</li>
                            <li>Second Grandchild</li>
                        </ul>
                    </li>
                    <li>Second Child
                        <ul>
                            <li>Third Grandchild</li>
                            <li>Fourth Grandchild</li>
                        </ul>
                    </li>
                </ul>
            </li>
        </ul>
    </div>
</body>
</html>

В приведенном примере используется замечательный плагин для JQuery: jQuery.treeview для отображения свернутого дерева с кнопками для разворачивания.

О кризисе и рекламе

марта 17, 2009

Волна кризиса уже докатилась до СМИ, рекламных агентств и студий. Знакомые из нескольких деловых изданий уже вторую неделю говорят о снимающихся с размещения клиентах. И у нас пара потенциальных заказчиков со словами «кризис, кризис» решили «временно приостановить». В добрый путь, удачи вам и процветания вашему бизнесу.

Что происходит

Сперва «где-то там» грянул кризис. Банки сокращали объемы выдаваемых кредитов. Инвесторы выводили свои деньги. В результате крупные компании, чье развитие зависело от инвестиций и заемных средств, начали затягивать пояса.

Скажем, хотел банк такой-то заказать себе в офис новый интерьер, мебель и компьютеры, а теперь на это денег нет. В результате не получают заказ компании поменьше: архитекторы, поставщики оргтехники, поставщики мебели, курьеры, транспортныекомпании и т.п.

Компания поменьше не продала банку мебель, следовательно, не купила мебель у оптовика. Тот оптовик остался без какой-тосуммы денег, но с мебелью на складе. За аренду склада надо платить, а мебель стали покупать значительно меньше. И вот этот оптовый поставщик мебели решает, раз денег стало меньше, войти в режим экономии. И режет затраты. И не он один.

Компании начинают сокращать штаты и разные бюджеты, не только рекламные. Откладываются ремонты, переносятся мероприятия, задерживаются зарплаты, отменяются премии, замораживаются проекты, снимаются дотации на питание, перестают выдаваться полисы ДМС. В кулерах заканчивается вода, в принтерах и туалетах  — бумага.

Что делают рекламодатели

Что касается рекламных бюджетов, то здесь есть две заметные невооруженным глазом тенденции (наверное, для понту надо было бы использовать модное ныне слово «тренд», но я оставлю это балаболам из сетевых рекламных агентств).

Одни компании всячески урезают свои рекламные бюджеты. Почему же они так делают, ведь реклама приводит новых клиентов, приносит деньги в фирму? Все просто: эти руководители, на самом деле, не верят в свою рекламу. Они не считают, что их реклама приносит им деньги. И тратились на нее только потому, что Вася-конкурент тоже давал рекламу, а Миша-продажник откатывал 10%.

В 1998 году многие компании сократили свои рекламные бюджеты. С тех пор о них ничего не слышно.

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

Вот теперь смотрите, что получается: одни компании исчезают из поля зрения потенциальных клиентов, демонстрируя отрасли, как плохи у них дела. Другие компании, напротив, используют свой шанс и становятся гораздо заметнее.

Как вы думаете, кто из них переживет кризис? Те, о которых ничего не слышно, или те, которые стали более известными среди своих потенциальных клиентов?

Во время кризиса, когда конкуренты сокращают свое присутствие, каждый рубль, вложенный в правильную рекламу, делает вас гораздо заметнее на их фоне. В кризисе всегда можно найти позитивные моменты.

Неправильная реклама, наоборот, сожрет последнее. Например, нет никакого смысла делать «полноценный сайт за 100 баксов» по объявлению на столбе — он ничего не продаст, но только покажет, как все плохо в конторе. Нет никакого смысла заказывать «рекламный модуль за 50 баксов» у «дизайнеров» из соседней типографии.

Сейчас вам, как никогда раньше, нужна хорошая реклама.

Что будут делать студии и рекламные агентства

Тут тоже есть две тенденции. Сперва, конечно, множество контор запаникует и займется демпингом. Долго работать на грани себестоимости они не смогут и начнут закрываться.

С одной стороны, спрос на услуги студий и агентств будет сокращаться. Но, с другой стороны, путем естественного отбора сократится и предложение.

Куда пойдут те, кто осознает потребность в хорошей рекламе, профессионально оформленном фирменном стиле, грамотно сделанном сайте? Ясное дело, не в подвалы, в которых студенты второго курса за 100 баксов в месяц мучаются над «недорогими, но креативными логотипами» и «доступными, но эксклюзивными сайтами».

Они пойдут в компании, которые успели зарекомендовать себя, наработали известность, портфолио и рекомендации клиентов, а цены назначали без оглядки на конкурентов и возгласы «а чего так дорого». Кстати, к нам больше всего приходят именно по рекомендациям.

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

И, совершенно точно, работать придется напряженнее. Нам наша работа нравится, поэтому мы этого не боимся.

Каждый раз, когда вам будут говорить «кризис, кризис», показывайте эту статью! Мы хотим, чтобы наши коллеги продавали больше и дороже, а не устраивали губительные ценовые войны. Тогда мы сможем продавать еще больше и дороже. Удачи, сил и решительности использовать новые шансы.

 

источник

Алгоритм преобразует алгоритм!

января 2, 2009

При программировании на delphi или Паскале иногда попадаются задачи, которые трудно “втиснуть” в стандартные конструкции языка. А решение лежит совсем рядом – в теории конечных автоматов. Мы не будем залезать в дебри, а просто покажем как это делается.

Автор заранее просит у читателя прощения за то, что в тексте статьи используются блок-схемы. Это не модно сейчас, однако есть случаи, когда все-таки стоит их использовать. Рассуждения об алгоритмах – как раз такой особый случай.

Read the rest of this entry »

Доступ к MasterPage из страницы ASPX

августа 25, 2008

Часто приходится в своей работе пользоваться MasterPages и решил я поделиться тем, как можно обращаться из ContentPlaceHolder‘a к MasterPage.

Например, на MasterPage находится CheckBox, к которому мы хотим обратиться: снять пометку, или, наоборот – поставить. Вот его код в Site.master:

<asp:CheckBox ID=”chkVideo” runat=”server” CssClass=”chkText” Text=”только с видео” EnableViewState=”False” Checked=”True” />

В Site.master.cs нужно поместить следующий код:

public bool MyChkVideo
{
get
{
return chkVideo.Checked;
}
set
{
chkVideo.Checked = value;
}
}

А в aspx в страницу, сразу после

<%@ Page Language=”C#” MasterPageFile=”~/Site.master” AutoEventWireup=”true” CodeFile=”Search.aspx.cs” Inherits=”Search” %>

строчку

<%@ MasterType VirtualPath=”~/Site.master” %>

Теперь к элементу checkbox можно обратиться из MasterPage! В aspx.cs, через конструкции:

bool blnChkAuto = Master.MyChkAuto;
или Master.MyChkAuto = false;

Точно так же, можно обращаться к любым другим контролам на MasterPage.

Установка Wordpress не в корневую директорию

июня 17, 2008

Итак, я установил себе на хостинг Wordpress. Установка прошла на ура в директорию ./wordpress . Возник вопрос: как сделать перенаправление, что бы блог откликался на имя http://zaktus.net, а не http://zaktus.net/wordpress ?

Ответ был найден быстро в виде статьи, перевод которой, снабженный скриншотами , я здесь привожу:

Многие люди хотят, чтобы вызов Wordpress , осуществлялся из корня сайта (например: http://example.com), но не хотят захламлять корневую директорию файлами Wordpress-а. Wordpress позволяет этого добиться с помощью несложных манипуляцией.

Для этого необходимо:

  1. Создать директорию (например ./wordpress). Если Вы только начинаете устанавливать Wordpress, то туда можно сразу скопировать все файлы, в этом случае шаг 6 пропускаем.
  2. Открыть панель Настройки (кнопка переключения расположена справа-вверху).
    Панель
  3. В поле Адрес WordPress (URL) поменять на новое значение. Например, было http://example.com стало http://example.com/wordpressИзменение адреса Wordpress
  4. В поле Адрес блога (URL) указываем корневой адрес адрес сайта (http://examle.com).
  5. Сохраняем изменения нажав на кнопку “Сохранить изменения” (если после этого вы получите сообщение об ошибке, ничего страшного, это нормально для данного этапа).
  6. Переносим все файлы Wordpress-а в новое место (Адрес WordPress). Если Wordpress был сразу установлен не в корень этот шаг можно пропустить.
  7. Скопировать фпйлы index.php и .htaccess из директории WordPress в корень сайта (Адрес блога).
  8. Открыть файл index.php в текстовом редакторе.
  9. Внести следующие изменения и сохранить файл. Поменять строчку:
    <em><strong>require('./wp-blog-header.php');</strong></em>
    на следующее:
    <strong>require('./wordpress/wp-blog-header.php');</strong>
  10. Залогиниться по новому адресу: http://example.com/wordpress/wp-admin/.
  11. Теперь, надо обновить настройки постоянных ссылок (ЧПУ), для чего открывает соответствующий пункт Постоянные ссылки (ЧПУ) в меню панели Настройки. WordPress автоматически обновит файл .htaccess если у него есть парва. Если WordPress не сможет получить доступ на запись файла .htaccess, он покажет правила для реврайта, которые будет необходимо внести самостоятельно в файл .htaccess (расположенный там же, где файл indep.php.)

Удачи.