среда, 18 мая 2011 г.

ASP.NET русских символы в URL параметрах

Добрый день, сегодня столкнулся с казалось бы простой проблемой...

Есть приложение в котором основная кодировка UTF-8. Нужно сформировать ссылку с набором параметров содержащих русские символы, возникает вопрос, как это сделать? Функция Server.URLEncode не помогает (она бы сработала если бы кодировка была не юникод).

Решение оказалось очень простым: HttpUtility.UrlEncodeUnicode.

Для расшифровки можно использовать Server.UrlDecode.

понедельник, 16 мая 2011 г.

Автоинструкторы Москвы

Моя знакомая решила отучиться в автошколе и получить права. Теорию рассказали отлично, а где не поняла взяла зубрежкой, а вот с автоинструктором не повезло(( Все занятия кроме двух последних катал её по площадке)) Понятно дела, когда пришло время сдавать, площадку она сдала, а вот сдать город у нее не получилось. Возвращаться к этому товарищу, мягко сказать не хотелось, поэтому полезли в инет искать автоинструктора из нашего района Москвы. Есть сайты с анкетами, вообщем нашли хорошего инструктора, а потом появилась идея сделать свой такой же сайт! Вуаля: автоинструктор. Найти сайт можно по словам автоинструктор акпп.

вторник, 3 мая 2011 г.

Что делать если надо из Twitter'a получить количество упоминаний о странице?

Столкнулся с проблемой, нужно на сайте прикрутить рейтинг продуктов, основанный на социальных сетях... Все сети Twitter, Facebook, ВКонтакте дают возможность установить у себя на сайте кнопку "Мне нравиться". В этом проблемы нет! А вот как прочитать информацию из всех этих социалок и на основе её выставить рейтинг?
Вот кусок кода на Javascript (для Twitter):

$.getJSON('http://api.facebook.com/restserver.php?method=links.getStats&callback=?&urls=' + pageuri + '&format=json', function (data) {
alert(data[0].share_count);
});


Вот кусок кода на Javascript (для ВКонтакте):

VK = {};

            VK.Share = {};

            VK.Share.count = function (index, count) {

                alert(count);

            };

            $.getJSON('http://vkontakte.ru/share.php?act=count&index=1&url=' + pageuri + '&format=json&callback=?');




Вот кусок кода на Javascript (для Facebook):

$.getJSON('http://urls.api.twitter.com/1/urls/count.json?url=' + pageuri + '&callback=?', function (data) {

                alert(data.count);

            });




Пост для Блогуна.

Пост для Блогун.

среда, 27 апреля 2011 г.

Навеяло Факусимой... в предверии дачного сезона


Пример сайта на Umbraco

Один из последних сайтов, которые я сейчас разрабатываю, пишу как раз на Umbraco. Сайт посвящен поиску автосервисов и тех. центров по городам. На данный момент город только один Москва. На сайте предполагается наличие каталога автосервисов с механизмом поиска, функция добавления автосервисов, рэйтинги и отзывы. Система обмена ссылками, рассылка писем, баннеры, новости с RSS каналом. В перспективе личный кабинет для постоянных пользователей и возможность интеграции с социальными сетями. Наверное пока все;-) Сайт автосервисы.


четверг, 14 апреля 2011 г.

Как использовать свои функции написанные на C# в XSLT?


Часто возникает необходимость использовать различные свои функции внутри XSLT кода.

Как же это сделать?

Очень просто!
1. Создаете новый проект, тип проекта dll-библиотека;
2. Создаете любой класс к примеру
namespace alfa.Umbraco
{
    public class Helper
    {

    }
}

3. Добавим статическую функцию:
namespace alfa.Umbraco
{
    public class Helper
    {
        public static string GetVersion()
        {
            return "1.0";
        }
    }
}

4. Компилируем библиотеку, в моем случае получился файл alfa.Umbraco.dll и копируем его в папку /bin/ на сервере где установлено Umbraco в моем случае эта папка: C:\inetpub\umbraco\bin\;
5. Далее находим файл xsltExtensions.config, он находится в папке /config/. И добавляем туда строку:
<?xml version="1.0" encoding="utf-8" ?>
<XsltExtensions>
  <!--
  This file is used to register 3rt party xslt extensions (methods you can execute from xslt, like umbraco.library:NiceUrl)
 <ext assembly="assemblyName" type="assemblyName.namespace.type" alias="custom">
  -->
 <ext assembly="alfa.Umbraco" type="alfa.Umbraco.Helper" alias="alfa.Helper"/>
</XsltExtensions>

6. Открываем наш XSLT файл в Umbraco и добавляем туда еще несколько строк. В секцию
<xsl:stylesheet ... > добавляем атрибут xmlns:alfa.Helper="urn:alfa.Helper", получается примерно вот такая конструкция:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE xsl:stylesheet [ <!ENTITY nbsp "&#x00A0;"> ]>
<xsl:stylesheet 
  version="1.0" 
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
  xmlns:msxml="urn:schemas-microsoft-com:xslt" 
  xmlns:umbraco.library="urn:umbraco.library" 
  xmlns:alfa.Helper="urn:alfa.Helper" 
xmlns:Exslt.ExsltCommon="urn:Exslt.ExsltCommon" 
xmlns:Exslt.ExsltDatesAndTimes="urn:Exslt.ExsltDatesAndTimes" 
xmlns:Exslt.ExsltMath="urn:Exslt.ExsltMath" 
xmlns:Exslt.ExsltRegularExpressions="urn:Exslt.ExsltRegularExpressions" 
xmlns:Exslt.ExsltStrings="urn:Exslt.ExsltStrings" 
xmlns:Exslt.ExsltSets="urn:Exslt.ExsltSets" 
  exclude-result-prefixes="alfa.Helper msxml umbraco.library Exslt.ExsltCommon Exslt.ExsltDatesAndTimes Exslt.ExsltMath Exslt.ExsltRegularExpressions Exslt.ExsltStrings Exslt.ExsltSets ">

<xsl:output method="xml" omit-xml-declaration="yes" />

<xsl:param name="currentPage"/>

<xsl:template match="/">
</xsl:template>

</xsl:stylesheet>

7. А теперь вызовем нашу функцию:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE xsl:stylesheet [ <!ENTITY nbsp "&#x00A0;"> ]>
<xsl:stylesheet 
  version="1.0" 
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
  xmlns:msxml="urn:schemas-microsoft-com:xslt" 
  xmlns:umbraco.library="urn:umbraco.library" 
  xmlns:alfa.Helper="urn:alfa.Helper" 
xmlns:Exslt.ExsltCommon="urn:Exslt.ExsltCommon" 
xmlns:Exslt.ExsltDatesAndTimes="urn:Exslt.ExsltDatesAndTimes" 
xmlns:Exslt.ExsltMath="urn:Exslt.ExsltMath" 
xmlns:Exslt.ExsltRegularExpressions="urn:Exslt.ExsltRegularExpressions" 
xmlns:Exslt.ExsltStrings="urn:Exslt.ExsltStrings" 
xmlns:Exslt.ExsltSets="urn:Exslt.ExsltSets" 
  exclude-result-prefixes="alfa.Helper msxml umbraco.library Exslt.ExsltCommon Exslt.ExsltDatesAndTimes Exslt.ExsltMath Exslt.ExsltRegularExpressions Exslt.ExsltStrings Exslt.ExsltSets ">

<xsl:output method="xml" omit-xml-declaration="yes" />

<xsl:param name="currentPage"/>

<xsl:template match="/">
<xsl:value-of select="alfa.Helper:GetVersion()"/>
</xsl:template> </xsl:stylesheet>


Готово!


Динамические XPath запросы или как составить запрос при помощи C#

Как то разрабатывал я каталог автосервисов и нужно было сделать фильтр, что бы можно было выбрать автосервис по округу, марке автомобиля, времени работы наличию тех или иных услуг. Я решил, что параметры должны передаваться через URL-адрес. Для того что бы это реализовать нужно сделать очень простую вещь (кажется что простую;-) обработать URL запрос и составить XPath выражения для того что бы вытащить нужные страницы.

Но оказалось, что составить XPath в XLST ой, как не просто! Тогда я решал написать свою функцию на C# и подключить её.

Сделал проект DLL'ка, там сделал один единственный класс, у класса статическую функцию, которая разбирала URL и состоаляла XPath запрос, и возвращала строку. Пример:

namespace alfa.Umbraco
{
    public class XPath
    {
        public static string GetRequestString()
        {
                HttpRequest Request = HttpContext.Current.Request;
                if (!string.IsNullOrWhiteSpace(Request.QueryString["a"]))
                    return string.Format(" IsMy = '{0}'", Request.QueryString["a"]);

            return " 1=1";           
        }
}
}

Подключил dll'ку к проекту. Добавляем код в XSLT и в итоге ничего не работает((( Вопрос почему?

Все очень просто! Дело в том, что результат функции трактуется как СРОКА, а <xsl:for-each select="XPATH"> ждет от Вас XPath строку!!!

Я потратил целый вечер, что бы победить эту проблему. И нашел решение! Давай те проделаем все по шагам.

1. Нужно создать библиотеку с функцией, которая нам поможет:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
using System.Xml.XPath;

namespace alfa.Umbraco
{
    public class XPath
    {
        public static string evalXpath(XPathNodeIterator nodes, string xpath)
        {
            string add = "";
            HttpRequest Request = HttpContext.Current.Request;
            if (!string.IsNullOrWhiteSpace(Request.QueryString["a"]))
                add = string.Format(" and string(isMy) = '{0}'", Request.QueryString["a"]);
            else
                add = " and 1=1";

            try
            {
                while (nodes.MoveNext())
                {
                    XPathNavigator n = nodes.Current as XPathNavigator;
                    return n.Evaluate(xpath + add).ToString();
                }
            }
            catch
            {
                return null;
            }
            return null;
        }
    }
}
Суть этой функции очень простая, в неё мы передаем документа, и xpath запрос (можем не передавать), в первой части функции мы входящий XPath запрос доделываем и проверяем соответствует ли наша сущность этому запросу, в результате возвращаем строку "True" или "False".

2. Подключаем эту эту библиотеку в Umbraco.
3. А XSLT будет выглядеть примерно следующим образом:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE xsl:stylesheet [ <!ENTITY nbsp "&#x00A0;"> ]>
<xsl:stylesheet
  version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:msxml="urn:schemas-microsoft-com:xslt"
  xmlns:umbraco.library="urn:umbraco.library"
  xmlns:alfa.XPath="urn:alfa.XPath"
xmlns:Exslt.ExsltCommon="urn:Exslt.ExsltCommon"
xmlns:Exslt.ExsltDatesAndTimes="urn:Exslt.ExsltDatesAndTimes"
xmlns:Exslt.ExsltMath="urn:Exslt.ExsltMath"
xmlns:Exslt.ExsltRegularExpressions="urn:Exslt.ExsltRegularExpressions"
xmlns:Exslt.ExsltStrings="urn:Exslt.ExsltStrings"
xmlns:Exslt.ExsltSets="urn:Exslt.ExsltSets"
  exclude-result-prefixes="alfa.XPath msxml umbraco.library Exslt.ExsltCommon Exslt.ExsltDatesAndTimes Exslt.ExsltMath Exslt.ExsltRegularExpressions Exslt.ExsltStrings Exslt.ExsltSets ">

<xsl:output method="xml" omit-xml-declaration="yes" />

<xsl:param name="currentPage"/>

<!-- Input the documenttype you want here -->
<xsl:variable name="level" select="1"/>
   
<xsl:template match="/">
 
<!-- The fun starts here -->
<ul class="menu">
  <xsl:for-each select="$currentPage/ancestor-or-self::* [@level=;level]/* [alfa.XPath:evalXpath(.) = 'True']">
  <li>
    <a href="{umbraco.library:NiceUrl(@id)}">
      <xsl:value-of select="@nodeName"/>
    </a>
  </li>
</xsl:for-each>
</ul>

</xsl:template>

</xsl:stylesheet>

Готово!

понедельник, 11 апреля 2011 г.

Переход на новую строку в Rich Text Editor

Очень маленький топик.

Проблема: Каждый раз, когда я редактирую текст в Rich Text Editor в Umbraco и нажимаю "Enter", вставляется новый абзац, а я хочу просто перейти на новую строку.

Решение: Нажимайте "Shift+Enter".

Перевод интересных статей

Т.к. я и сам занимаюсь изучением Umbraco, у меня часто возникают вопросы, по тому, как сделать что-то...;-) И ответ по долгу приходится искать в интернете, форум Umbraco, мне далеко не всегда помогает.

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

пятница, 8 апреля 2011 г.

Создание сайта. Шаг 9. Закрепляем понятие модулей и макросов. Хлебные крошки.

Теперь, мы можем создавать простые сайты, состоящие из набора текстовых страниц с меню. Давай те попробуем создать еще один простой модуль, называемый "Хлебные крошки". Повторим действия из шестого шага.

Входим в систему управления, переходим в раздел "Developer", находи раздел "XSLT Files", нажимаем правую кнопку мыши, появляется всплывающее меню:


Выбираем "Create":


 Вводим в поле "Filename (without .xslt)" название файла "Хлебные крошки". В поле "Choose a template"выбираем шаблон "Breadcrumb". Разработчики системы управления, позаботились о том, что бы мы не писали стандартные куски кода, и добавили шаблоны! "Breadcrumb" этот шаблон создает скрипт, который выводит так называемые "Хлебные крошки".

Нажимаем "Create" в итоге появится  следующий скрипт:


<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE xsl:stylesheet [  <!ENTITY nbsp "&#x00A0;">]>
<xsl:stylesheet
  version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:msxml="urn:schemas-microsoft-com:xslt"
  xmlns:umbraco.library="urn:umbraco.library" xmlns:Exslt.ExsltCommon="urn:Exslt.ExsltCommon" xmlns:Exslt.ExsltDatesAndTimes="urn:Exslt.ExsltDatesAndTimes" xmlns:Exslt.ExsltMath="urn:Exslt.ExsltMath" xmlns:Exslt.ExsltRegularExpressions="urn:Exslt.ExsltRegularExpressions" xmlns:Exslt.ExsltStrings="urn:Exslt.ExsltStrings" xmlns:Exslt.ExsltSets="urn:Exslt.ExsltSets"
  exclude-result-prefixes="msxml umbraco.library Exslt.ExsltCommon Exslt.ExsltDatesAndTimes Exslt.ExsltMath Exslt.ExsltRegularExpressions Exslt.ExsltStrings Exslt.ExsltSets ">

  <xsl:output method="xml" omit-xml-declaration="yes"/>

  <xsl:param name="currentPage"/>

  <xsl:variable name="minLevel" select="1"/>

  <xsl:template match="/">

    <xsl:if test="$currentPage/@level &gt; $minLevel">
      <ul>
        <xsl:for-each select="$currentPage/ancestor::* [@level &gt; $minLevel and string(umbracoNaviHide) != '1']">
          <li>
            <a href="{umbraco.library:NiceUrl(@id)}">
              <xsl:value-of select="@nodeName"/>
            </a>
          </li>
        </xsl:for-each>
        <!-- print currentpage -->
        <li>
          <xsl:value-of select="$currentPage/@nodeName"/>
        </li>
      </ul>
    </xsl:if>
  </xsl:template>
</xsl:stylesheet>​

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

Готово! Теперь добавьте модуль в "Базовый шаблон".

Создание сайта. Шаг 8. CSS - подключаем каскадные таблицы стилей

Пришло время немного оформить наш сайт. Давай те добавим CSS-файл в наш сайт.

Делается это из системы управления, в разделе "Settings", найдите элемент "Stylesheets", на нем нажмите правую кнопку мыши, в контекстном меню нажмите "Create".



Создаем CSS-файл, вводим название, нажимаем "Create":


Получаем чистенький файл:


Давай те немного оформим наш сайт:

<!-- RESET -->
html, body, table, div, tr, td, img, p
{
  padding:0px;
  margin:0px;
}

table
{
  border-collapse:collapse; 
}
td
{
  vertical-align:top;
}
.clear
{
clear:both; 
}

<!-- BODY -->
h1
{
  font-size:16px;
}
.menu
{
  clear:both; 
  padding-left:0px; 
  margin-left:0px;
}
.menu li
{
  display:block;
  float:left;
  padding-left:20px;
}
.menu li a
{
 color:#000;
 text-decoration:underline;
}
.menu li a:hover
{
 text-decoration:none;
}

Теперь давай те подключим наш CSS файл к Базовому шаблону. Добавив в него в блок <head> строку:

<link type='text/css' rel='stylesheet' href='/css/main.css' />

И немного подправим, что бы получилось следующее:

<%@ Master Language="C#" MasterPageFile="~/umbraco/masterpages/default.master" AutoEventWireup="true" %>

<asp:Content ContentPlaceHolderID="ContentPlaceHolderDefault" runat="server">

  <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
  <html xmlns="http://www.w3.org/1999/xhtml" >
    <head>
      <title>
        <umbraco:Item runat="server" field="title"></umbraco:Item>
      </title>
      <meta name="keywords" content="<umbraco:Item field="keywords" runat="server"></umbraco:Item>"/>
      <meta name="description" content="<umbraco:Item field="description" runat="server"></umbraco:Item>"/>
      <link type='text/css' rel='stylesheet' href='/css/main.css' />
     
      <asp:ContentPlaceHolder Id="phBasePageHeader" runat="server">
      <!-- Insert default "phBasePageHeader" markup here -->
      </asp:ContentPlaceHolder>

    </head>
    <body>
     
      <umbraco:Macro Alias="Верхнееменю" runat="server"></umbraco:Macro>
      <div class="clear"></div>
      <asp:ContentPlaceHolder Id="phBasePageContext" runat="server">
        <!-- Insert default "phBasePageContext" markup here -->
      </asp:ContentPlaceHolder>


    </body>
  </html>

 
</asp:Content>​

Теперь, давай те откроем наш XSLT файл "Верхнее меню" и в блок <ul> пропишем класс menu. Должно получиться следующее:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE xsl:stylesheet [ <!ENTITY nbsp "&#x00A0;"> ]>
<xsl:stylesheet 
  version="1.0" 
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
  xmlns:msxml="urn:schemas-microsoft-com:xslt" 
  xmlns:umbraco.library="urn:umbraco.library" xmlns:Exslt.ExsltCommon="urn:Exslt.ExsltCommon" xmlns:Exslt.ExsltDatesAndTimes="urn:Exslt.ExsltDatesAndTimes" xmlns:Exslt.ExsltMath="urn:Exslt.ExsltMath" xmlns:Exslt.ExsltRegularExpressions="urn:Exslt.ExsltRegularExpressions" xmlns:Exslt.ExsltStrings="urn:Exslt.ExsltStrings" xmlns:Exslt.ExsltSets="urn:Exslt.ExsltSets" 
  exclude-result-prefixes="msxml umbraco.library Exslt.ExsltCommon Exslt.ExsltDatesAndTimes Exslt.ExsltMath Exslt.ExsltRegularExpressions Exslt.ExsltStrings Exslt.ExsltSets ">

<xsl:output method="xml" omit-xml-declaration="yes" />

<xsl:param name="currentPage"/>

<!-- Input the documenttype you want here -->
<xsl:variable name="level" select="1"/>

<xsl:template match="/">

<!-- The fun starts here -->
<ul class="menu">
<xsl:for-each select="$currentPage/ancestor-or-self::* [@level=$level]/* [@isDoc and string(umbracoNaviHide) != '1']">
  <li>
    <a href="{umbraco.library:NiceUrl(@id)}">
      <xsl:value-of select="@nodeName"/>
    </a>
  </li>
</xsl:for-each>
</ul>

</xsl:template>

</xsl:stylesheet>​


Готово, зайдите на сайт и посмотрите, если форматирование изменилось, значит CSS-файл подключился.

Справка: структура документа (XML)

Весь публикуемый контент в Umbraco имеет XML формат и представляется в виде XML документа. Этот документ имеет следующий формат:

Первый элемент отображается как "Node". Этот элемент имеет ряд атрибутов, которые содержат базовую информацию о нем: идентификатор, дату создания и т.д.

Данные на странице, родительские свойства в типе документа определенны в "элементе Data", который находится в Node.

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

Документ имеет следующую структуру:
<node
        id="1037"
        version="1E7BF0C1-51DA-4740-BCCE-6096A8C3ECD5"
        parentID="-1"
        level="1"
        writerID="0"
        nodeType="1036"
        template="1035"
        sortOrder="0"
        createDate="2005-03-15T04:06:47.890"
        updateDate="2005-03-11T20:57:16.187"
        nodeName="It worked"
        urlName="itworked"
        writerName="umbraco_system"
        nodeTypeAlias="Textpage"
        path="-1,1037">
                <data version="1E7BF0C1-51DA-4740-BCCE-6096A8C3ECD5" alias="bodyText">
                <![CDATA[
                        Contratulations
                        <img
                                alt="crew"
                                align="right"
                                src="/media/426c7b76-5d12-4572-b953-a71a26bf143f-crew.jpg"
                                width="200"
                                height="150"/>
                        <br/>
                        - umbraco is installed and
                        <A href="/itworked/bugs/bububub.aspx">working</A>!
                ]]>
                </data>
                <data version="1E7BF0C1-51DA-4740-BCCE-6096A8C3ECD5" alias="resume">
                <![CDATA[
                ]]>
                </data>
        <data version="1E7BF0C1-51DA-4740-BCCE-6096A8C3ECD5" alias="umbracoNaviHide">
                0
        </data>
</node>

Значения атрибутов:
  • id - идентификатор документа (страницы);
  • version - идентификатор версии id для страницы;
  • parentID - идентификатор родительского элемента;
  • level - уровень вложенности;
  • template - идентификатор шаблона;
  • sortOrder - порядковый номер элемента;
  • createDate - дата создания;
  • updateDate: дата обновления (publishing time);
  • nodeName - название документа;
  • urlName - Umbraco использует это значение для url;
  • writerName - имя пользователя опубликовавшего статью;
  • nodeTypeAlias - Alias типа документа;
  • path - строка содержащая все родительские элементы, разделенные точкой с запятой.

Создание сайта. Шаг 7. XSLT - что это такое?

В прошлом посте, мы сделали модуль "Верхнее меню", но не разобрали, как же он работает?

Давай те по строчкам разберем листинг скрипта::

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE xsl:stylesheet [ <!ENTITY nbsp "&#x00A0;"> ]>
<xsl:stylesheet
  version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:msxml="urn:schemas-microsoft-com:xslt"
  xmlns:umbraco.library="urn:umbraco.library" xmlns:Exslt.ExsltCommon="urn:Exslt.ExsltCommon" xmlns:Exslt.ExsltDatesAndTimes="urn:Exslt.ExsltDatesAndTimes" xmlns:Exslt.ExsltMath="urn:Exslt.ExsltMath" xmlns:Exslt.ExsltRegularExpressions="urn:Exslt.ExsltRegularExpressions" xmlns:Exslt.ExsltStrings="urn:Exslt.ExsltStrings" xmlns:Exslt.ExsltSets="urn:Exslt.ExsltSets"
  exclude-result-prefixes="msxml umbraco.library Exslt.ExsltCommon Exslt.ExsltDatesAndTimes Exslt.ExsltMath Exslt.ExsltRegularExpressions Exslt.ExsltStrings Exslt.ExsltSets ">

<xsl:output method="xml" omit-xml-declaration="yes" />

<xsl:param name="currentPage"/>

<!-- Input the documenttype you want here -->
<xsl:variable name="level" select="1"/>

<xsl:template match="/">

<!-- The fun starts here -->
<ul>
<xsl:for-each select="$currentPage/ancestor-or-self::* [@level=$level]/* [@isDoc and string(umbracoNaviHide) != '1']">
  <li>
    <a href="{umbraco.library:NiceUrl(@id)}">
      <xsl:value-of select="@nodeName"/>
    </a>
  </li>
</xsl:for-each>
</ul>

</xsl:template>

</xsl:stylesheet>​

Строка 01:
<?xml version="1.0" encoding="UTF-8"?>
Стандартный заголовок XML-файла.

Строка 02:
<!DOCTYPE xsl:stylesheet [ <!ENTITY nbsp "&#x00A0;"> ]>
Здесь мы задаем, как будет отображаться специальная комбинация символов &nbsp; (пробел).


Строка 03-09:
<xsl:stylesheet 
version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
xmlns:msxml="urn:schemas-microsoft-com:xslt" 
xmlns:umbraco.library="urn:umbraco.library"
xmlns:Exslt.ExsltCommon="urn:Exslt.ExsltCommon" xmlns:Exslt.ExsltDatesAndTimes="urn:Exslt.ExsltDatesAndTimes" xmlns:Exslt.ExsltMath="urn:Exslt.ExsltMath" xmlns:Exslt.ExsltRegularExpressions="urn:Exslt.ExsltRegularExpressions" xmlns:Exslt.ExsltStrings="urn:Exslt.ExsltStrings"
xmlns:Exslt.ExsltSets="urn:Exslt.ExsltSets" 
exclude-result-prefixes="msxml umbraco.library Exslt.ExsltCommon Exslt.ExsltDatesAndTimes Exslt.ExsltMath Exslt.ExsltRegularExpressions Exslt.ExsltStrings Exslt.ExsltSets "> 
Список подключаемых библиотек, функции которых мы можем использовать в этом примере мы используем ф-цию umbraco.library:NiceUrl(...).


Строка 10:
<xsl:output method="xml" omit-xml-declaration="yes" /> 
Определяем метод вывода информации, в нашем случае XML (HTML).


Строка 12:
<xsl:param name="currentPage"/>
Единственный наш параметр currentPage, его инициализирует Umbraco и присваивает ему значение объект текущая страница. Грубо говоря, каждая наша страница представляется, как XML файл определенной структуры.


Строка 15:
<xsl:variable name="level" select="1"/>
Задаем параметр, который указывает страницы какого уровня мы выводим.


Строка 16:
<xsl:template match="/">
Начало корневого Template, отсюда начинает выполняться наш скрипт.


Строка 20, 28:
<ul>....</ul>
Часть верстки (не нумерованный список) в которую мы будем добавлять пункты меню.


Строка 21, 27:
<xsl:for-each select="$currentPage/ancestor-or-self::* [@level=$level]/* [@isDoc and string(umbracoNaviHide) != '1']">
.....
</xsl:for-each>
Собственно сам цикл, который делает xpath запрос:
$currentPage/ancestor-or-self::* [@level=$level]/* [@isDoc and string(umbracoNaviHide) != '1']
И получает все дочерние страницы уровня $level. А параметр string(umbracoNaviHide) != '1' говорит, что страница должна быть опубликована.


Строка 22-26:
<li> 
    <a href="{umbraco.library:NiceUrl(@id)}"> 
      <xsl:value-of select="@nodeName"/> 
    </a> 
</li> 
Выводим пункт меню. Функция umbraco.library:NiceUrl(@id) - по ID страницы возвращает "красивый" URL адрес это страницы.
<xsl:value-of select="@nodeName"/>
- Выводит название Нашей страницы со вкладки "Propertie", этот параметр можно заменить скажем на "nameField".

Создание сайта. Шаг 6. Добавление на сайт меню

Добавьте несколько страниц на сайт.

Теперь пришло время добавить на сайт меню, для ориентации на сайте.

Мы должны написать свой модуль. Есть несколько способов для этого. Написать модуль на C# и подключить его или воспользоваться стандартным механизмом Umbraco и написать функционал с применением XSLT.

Входим в систему управления, переходим в раздел "Developer", находи раздел "XSLT Files", нажимаем правую кнопку мыши, появляется всплывающее меню:


Выбираем "Create":


 Вводим в поле "Filename (without .xslt)" название файла "Верхнее меню". В поле "Choose a template"выбираем шаблон "List Sub Pages By Level". Разработчики системы управления, позаботились о том, что бы мы не писали стандартные куски кода, и добавили шаблоны! "List Sub Pages By Level" этот шаблон создает скрипт, который выводит список страниц по уровню вложенности.

Нажимаем "Create" в итоге появится  следующий скрипт:


Для того что бы наш скрипт заработал, надо подправить единственный параметр

<xsl:variable name="level" select="1"/>

Значение 1 соответствует уровню страниц, второго уровня (нумерация идет с нуля), то есть я предполагаю, что все страницы у нас будут наследоваться от главной:



Нажимаем кнопку "Сохранить".
После добавления нашего скрипта, создалась еще одна сущность "Macros" (Макрос):


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

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

Для этого переходим в раздел "Settings", выбираем раздел "Templates", выбираем "Базовый шаблон". На панели управления нажимаем кнопку (4):


И добавляем наш макрос "Верхнее меню", в итоге код нашего шаблона будет выглядеть следующем образом:


<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE xsl:stylesheet [ <!ENTITY nbsp "&#x00A0;"> ]>
<xsl:stylesheet
  version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:msxml="urn:schemas-microsoft-com:xslt"
  xmlns:umbraco.library="urn:umbraco.library" xmlns:Exslt.ExsltCommon="urn:Exslt.ExsltCommon" xmlns:Exslt.ExsltDatesAndTimes="urn:Exslt.ExsltDatesAndTimes" xmlns:Exslt.ExsltMath="urn:Exslt.ExsltMath" xmlns:Exslt.ExsltRegularExpressions="urn:Exslt.ExsltRegularExpressions" xmlns:Exslt.ExsltStrings="urn:Exslt.ExsltStrings" xmlns:Exslt.ExsltSets="urn:Exslt.ExsltSets"
  exclude-result-prefixes="msxml umbraco.library Exslt.ExsltCommon Exslt.ExsltDatesAndTimes Exslt.ExsltMath Exslt.ExsltRegularExpressions Exslt.ExsltStrings Exslt.ExsltSets ">

<xsl:output method="xml" omit-xml-declaration="yes" />

<xsl:param name="currentPage"/>

<!-- Input the documenttype you want here -->
<xsl:variable name="level" select="1"/>

<xsl:template match="/">

<!-- The fun starts here -->
<ul>
<xsl:for-each select="$currentPage/ancestor-or-self::* [@level=$level]/* [@isDoc and string(umbracoNaviHide) != '1']">
  <li>
    <a href="{umbraco.library:NiceUrl(@id)}">
      <xsl:value-of select="@nodeName"/>
    </a>
  </li>
</xsl:for-each>
</ul>

</xsl:template>

</xsl:stylesheet>​

Нажмите кнопку "Сохранить" (1).

Теперь перейдите на сайт и попробуйте воспользоваться меню.

четверг, 7 апреля 2011 г.

Создание сайта. Шаг 5. Добавление страниц

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

Давай те добавим нашу первую страницу. Для этого войдите в систему управления. И вы сразу окажетесь в разделе "Content":


Сейчас мы видим два элемента. Первый "Content" - это корень нашего сайта. Второй "Recycle Bin" - корзина, где оказываются все удаленные страницы (сущности).

Для добавления новой страницы нажмите правую унопку мыши на элементе "Content", появится всплывающее меню:



Нажимаем "Create", появляется диалог создания новой страницы:


Обратите внимание, на то, что иконка и описание страницы отображается, то, которое вы указали во время создания типа страницы (документа).

Вводим в поле "Name" название "Главная страница" и нажимаем "Create".


Появилась страница, она появилась, как дочерняя у элемента "Content". Справа в свойствах страницы есть несколько страниц, две из них создали мы - это "SEO" и "Содержание". Еще одна закладка "Properties" создается автоматически по умолчанию и присутствует у всех страниц.

Давай те заполним все поля на закладках "SEO" и "Содержимое". Затем нажмите на вторую кнопку на панели управления "Save and publish" (Сохранить и опубликовать). Затем нажмите третью кнопку "Preview" (предварительный закрытый просмотр). Появился результат нашей работы. Страница на которой отображается введенная информация. В раузере включите просмотр содержимого страницы, что бы посмотреть заполнились ли поля: Title, Keywords и Description. У меня содержимое выглядит вот так:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
  <html xmlns="http://www.w3.org/1999/xhtml" >
    <head>
      <title>
        Наш первый сайт на Umbraco 
      </title>
      <meta name="keywords" content="сайт, umbraco, опыт"/>
      <meta name="description" content="Наш первый сайт на Umbraco - первый опыт"/>
          
      <!-- Insert default "phBasePageHeader" markup here -->
      
    </head>
    <body>
    <h1>Главная страница</h1>
    <p>Содержимое Главной страницы нашего сайта! Бла, бла, бла....</p>

    </body>
  </html>

Готово! Теперь на сайте мы сможем создавать сколько угодно новых страниц. Попробуйте к странице добавить дочерние страницы.

Создание сайта. Шаг 4. Учимся создавать шаблоны (Часть 2)

Продолжим создание шаблонов.

Входим в систему управления, переходим к шаблонам. Выбираем шаблон “Текстовая страница”, в “Master Template” выбираем “Базовая страница” и удаляем блок <asp:Content></asp:Content>.

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


Появится диалоговое окно:


Выберите область phBasePageContext и нажмите кнопку "Insert".

В этой области мы будем размещать все наше содержимое страницы.

Давайте добавим тег <h1> куда будем выводить поле "nameField", и ниже добавим поле "contextField", напомню, что поля можно добавить использую кнопку (2) на панели управления, наш шаблон должен выглядеть примерно вот так:


Основной наш шаблон готов, теперь пришло время добавить первую страницу на наш сайт.

вторник, 5 апреля 2011 г.

Создание сайта. Шаг 4. Учимся создавать шаблоны (Часть 1)

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

Для этого существуют шаблоны. Шаблон – это html верстка, со специальной разметкой областей, в которые в дальнейшем будут вставляться данные из соответствующих полей типа страницы.

Когда мы с Вами создавали наши типы станиц, мы ставили галочку ”Create matching template” и для каждого нашего типа создавался свой собственный шаблон.

В Umbraco можно наследовать шаблоны (делать их вложенными), но об этом чуть позже.

Шаблоны в Umbraco хранятся в разделе “Settings”.


В разделе "Templates":


Забегая немного в перед: верстку я буду стараться использовать самую простую! Поэтому графическое оформление у нашего сайта будет минимальное, но картинки, JavaScript и CSS мы все таки использовать будем.

Давай те выберем шаблон “Базовая страница”.



В свойствах шаблона есть следующие поля:

  • Name – Название шаблона (любое)
  • Alias – Псевдоним шаблона (внутреннее название шаблона, любой)
  • Master Template – главный шаблон, от которого будет наследоваться текущей, более подробно с этой настройкой разберемся позже.
  • Большая текстовая область – непосредственно код шаблона, в ИЕ 7 у меня подсветка синтаксиса НЕ РАБОТАЕТ!

В теле шаблона сразу есть некоторый текст. Для тех кто знаком с ASP.NET и технологией MasterPage, никаких вопрос возникнуть не должно! А вот для тех, кто не знаком могут прочитать про MasterPage страницы, но в принципе это не обязательно, главное сказать, что вся верстка должна находится в нутрии тегов <asp:Content></asp:Content>.

Кстати блоков  <asp:Content>...</asp:Content> может быть несколько, об этом тоже позже.

Давай те добавим наш первый html код:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
    <title> </title>
    <meta name="keywords" content=""/>
    <meta name="description" content=""/>
</head>
<body>

</body>
</html>


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

Для этого поставьте курсор между тегами <title></title> и на панели инструментов нажмите очень удобную кнопку (2):




Появится вспомогательное диалоговое окно:


Выберите из выпадающего списка “Choose field” нужное нам поле, нам нужно поле Title. Помимо созданных нами полей есть еще несколько системных, по названию можно догадаться о их назначении.


И нажимаем “Insert”.

Наш шаблон будет выглядеть вот так:



Проделайте тоже для поля Keywords и Description. В итоге Ваш шаблон должен выглядеть так:



Т.к. мы хотим этот шаблон использовать как основу для всех остальных шаблонов, так же как и тип страницы “Базовая страница”, мы должны указать место куда будет загружаться содержимое дочерних шаблонов.

Может возникнуть вопрос, а зачем нам делать вложенные шаблоны, вложенные типы и т.д. А ответ очень простой, для экономии нашего с вами и времени и упрощения дальнейшей работы. У нас на сайте в будущем будет несколько типов страниц (текстовая, новости, каталог, фотогалерея) и у каждой из них будет Title, Keywords и Description. Все эти поля будут иметь разные значения, но выводится, будут в одном и том же месте, по одному и тому де принципу. Поэтому, мы их вынесем один раз в Базовый тип и базовый шаблон и забудем о них;-)

Поставьте курсор после тега <body>. В панели управления есть кнопка (5), нажмите её для вставки специальной области. Появится диалоговое окно:



Введите название области в поле “Name” - phBasePageContext и нажмите кнопку “Insert”.

И добавьте еще одну область с названием phBasePageHeader перед закрытием тега </head>. Если первая секция будет использоваться для вставки контекста, вторая для подключения различных файлов.

И нажмите кнопку “Cохранить”(1):



понедельник, 4 апреля 2011 г.

Создание сайта. Шаг 3. Тип "Текстовая страница"

В этом маленьком топике, мы сделаем тип “Текстовая страница”, используя в качестве основного тип “Базовая страница”.

1. Входим в систему управления http://адрес_вашено_сайта/umbraco/;
2. Переходи в раздел “Settings”;


3. Выбираем в левом дереве раздел “Document Types”;


4. Нажимаем правую кнопку мыши и в выпадающем меню выбираем “Create”;




5. В появившемся диалоговом окне в поле “Master DocumentType” указываем родителя “Базовая Страница”. Вводим название ”Текстовая страница”. Устанавливаем флаг ”Create matching template (Создать шаблон для нашего Типа документа). И нажимаем ”Create”.



6. Для того что бы мы могли, к станицам этого типа добавлять дочерние страницы (пока такого же типа). В настройках страницы переходим на закладку ”Structure”и устанавливаем флажок на нашем же типе! Это даст нам возможность создавать дочерние страницы у страниц этого типа.

7. И последнее что нам осталось сделать, это добавить поле “Содержимое”. Добавьте вкладку “Содержимое”, а на нее добавьте поле “Содержимое”, в поле “Alias” введите “contextField”, а в поле “Type” выберите “Richtext editor”. В это поле можно будет вводит форматированный текст, добавлять изображения, вставлять ссылки и таблицы.

Добавьте еще поле "Название страницы", в поле "Alias" введите "nameField", тип текстовое поле.
Ура, мы это сделали! Теперь у нас есть тип “Текстовая страница”.

На следующем шаге, создадим первый шаблон.



пятница, 1 апреля 2011 г.

С 1 апреля!!!

Не знаю что написать сегодня! Вроде никакого геморроя нет сегодня, тьфу,тьфу,тьфу!

Создание сайта. Шаг 2. Document Type


Document Type – тип документа описывает поля, которые должна содержать страница (документ). Поля можно редактировать для каждой станицы этого типа из  системы управления. Document Type могут наследоваться от других типов.

Давай те разберемся на практике.

Для нашего сайта, нам понадобится сделать несколько Document Type. Первый тип Базовая страница, от которого в дальнейшем будут наследоваться и создавать различные страницы. Поэтому создадим три поля: Title, Keywords, Description. Эти поля сможет заполнять администратор сайта для каждой страницы.

Переходим в раздел Settings:


Выбираем в левом дереве раздел Document Types:


Нажимаем правую кнопку мыши и в выпадающем меню выбираем Create:


Появится диалоговое окно, в котором можно указать родителя (Master DocumentType). В нашем случае оставляем пустым. Указать название (Name) типа документа, давай те введем Базовая страница. И флаг Create matching template (Создать шаблон для нашего Типа документа). Мы этот флажок оставляем. И нажимаем Create. В итоге вы увидите следующее:


Ваш Тип документа выбран, а в правой панели, его настройки. Они разделены на несколько закладок. Первая закладка Info.


  • Name – название Типа документа;
  • Alias – псевдоним, используется внутри Umbraco, но указать его НУЖНО;
  • Icon – иконка для этого типа;
  • Description – описание, это описание видят конечные пользователи вашего сайта, когда создают страницы этого типа;
  • Allow templates – разрешенные шаблоны, те шаблоны, которые используют наш тип;
  • Default template – шаблон по умолчанию.

Наша задача сейчас заполнить только одно поле Alias. Введите туда например basePageDocType. И нажмите кнопку Сохранить (дискета на панели инструментов).

Закладка Structure содержит список Типов документов, которые может будет добавить как дочерний элемент (страницу) в дереве сайта. Об этом чуть позже.

Пропустим закладку и перейдем на закладку Tab:


На ней мы можем создать закладки, для пользователя во время редактирования содержимого страниц сайта. Те поля, которые мы хотим добавить: Title, Description, Keywords уместно расположить на отдельной закладке SEO. Давай те создадим такую закладку:


Далее переходим на закладку Generic properties. На этой закладке мы и будем добавлять поля:


Нажимаем на панель Click here to add a new property, появляется очередное окно с полями:


Сначала добавим поле Title

  • Name – название поля, которое будет отображается при его заполнении в системе управления. Вводим: Title (заголовок окна);
  • Alias – псевдоним, он нам понадобится в дальнейшем, водим: title;
  • Type – элемент управления, который будет использоваться для ввода данных в это поле из системы управления, мы указываем TextString –  обычное текстовое поле;
  • Tab – закладка на которой будет размещено поле;
  • Mandatory – обязательное поле или нет. В нашем случае поле обязательное;
  • Validation – Регулярно выражение, которое будет использоваться, для проверки правильности ввода.
  • Description – описание поля.


И нажимаем кнопку Сохранить (дискета в панели инструментов).

По аналогии добавьте остальные два поля (Keywords, Description), но для них Type установите Textbox multiple. Это текстовое поле, но с возможностью вводить несколько строк. Т.к. эти поля могут содержать достаточно много текстовой информации.

В итоге у Вас должно получиться следующее:


Базовый тип страницы ГОТОВ!

В следующем шаге создадим Текстовый тип страницы.









среда, 30 марта 2011 г.

Создание сайта. Шаг 1. Система управления.


Для входа в систему управления сайтом введите http://адрес_вашено_сайта/umbraco/
Вы увидите форму для ввода логина и пароля:




Введите логин и пароль указанный вами во время установки. И вы попадете в систему управления:




Описывать интерфейс я не буду, разберем его по ходу дела.
Сейчас вы находитесь в разделе Content. Здесь Вы как раз можете видеть структуру сайта. Сейчас никаких элементов кроме корневого и корзины нет.

Создание сайта на Umbraco


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

А конечная наша цель написать хороший интернет-магазин с широкими возможностями.

Установка


Установить CMS очень просто:

  1. Нужно скачать последнюю версию Umbraco можно по адресу umbraco.codeplex.com.
  2. В IIS создаем новый сайт. Внимание: Именно сайт, а не приложение. Присваиваем ему имя и распаковываем туда архив.
  3. Можно создать базу в MS SQL Server – но для разработки это не обязательно, достаточно будет и embedded СУБД VistaDB.
  4. Когда все подготовительные работы закончены, включаем браузер и переходим на наш только что созданный сайт.
  5. Установка включает в себя несколько простых шагов – принятие лицензии, настройка подключения к БД, создание структуры БД, установка пароля администратора, проверка разрешений файловой системы (чтение / запись в нужные каталоги). На последнем этапе Umbraco предложит установить Runway Foundation – набор базовых элементов для построения сайта (текстовые страницы, навигация, FAQ, etc). Но нам на данный момент это не нужно. 
  6. Установка завершена! Ура!

Можно еще упростить процесс используя Microsoft Web Platform Installer (http://www.microsoft.com/web/Downloads/platform.aspx). Найдите Umbraco CMS в списке Content management или просто кликните Install на www.microsoft.com/web/gallery/Umbraco%20CMS.aspx.

Немного об Umbraco

Umbraco – это open source CMS написанная на C# ASP.NET, работает на сервере IIS и может использовать разные БД  (SQL Server, MySql, VistaDB). Я использую MS SQL Server.

Umbraco - это достаточно серьезная вещь, вот некоторые крупные проекты, которые ее используют – Peugeout.com, Heinz.com, Wired.co.uk, Hasselblad.com, sandisk.com, Denmark MSDN Community — msdncommunity.dk.

Какими достоинствами обладает эта система управления:

  1. Удобная и интуитивно понятная система управления. Причем понятная как программисту, так и конечному пользователю.
  2. Возможность создать различных пользователей с различными ролями.
  3. В системе управления встроена среда для разработки. Фактически все программирование, за исключением сложных и специфических модулей, логика которых не укладывается в общую концепцию, можно разрабатывать непосредственно из CMS.
  4. Большинство функционала можно реализовать при помощи XML/XSLT в качестве backend. Когда я начинал её изучать, применение XSLT мне казалось сложным не непонятным – вообщем жирный минус, но в последствие мое мнение изменилось. Плюс, я выучил XSLT и научился их применять.
  5. Umbraco представляет достаточно хороший API c возможностью расширения собственными функциями.
  6. Еще из одних плюсов удобный механизм распространения своих модулей в пакетах.
  7. Возможность использовать для разработки расширений IronPython – для тех, кто не хочет изучать C# / VB.net.
  8. Возможность на одной CMS создавать несколько сайтов.
  9. Многоязычность.
  10. Еще один из плюсов – это достаточно большое сообщество людей и готовых проектов, к сожалению в большинстве своем англоязычное).
  11. Это open-source. Umbraco использует смешанную лицензию – MIT / Umbraco UI License. Вторая, по сути – тот же MIT при сохранении логотипов и бренда Umbraco. Есть так же и коммерческая лицензия – которая включает поддержку, ряд платных дополнений и разрешает ребрендинг CMS.


суббота, 12 марта 2011 г.

Введение

Umbraco CMSВ этом блоге я хочу рассказать Вам о своем знакомстве с Umbraco CMS. И опыте её использования.

Мне много приходилось разрабатывать различные веб-сайты. Первые я начал делать в одной веб-студии, где и получил первый опыт веб-разработки. Там мы использовали “самописную” систему управления. За 2 года в этой студии я сделал порядко 70 сайтов на ней. Но самое интересное, что у каждого программиста была своя собственная версия CMS со своими “фишками”, объединял их только общий корпоративный дизайн;-)

В дальнейшем я перепробовал много систем управления, бесплатных, таких как Joomla и Wordpress и платных, таких как Bitrix, естественно были попытки отказаться от готовых CMS и написать свою “самую лучшую”, в которой были бы собраны все достоинства и нет недостатков (Слава Богу – это быстро прошло).

Последняя система управления, которую я нашел для своих и коммерческих проектов и на которой решил остановится Umbraco.CMS.