Рассказ о “странном” баге и о том, как влияет верстка работу всего приложения.

При работе с ASP.NET Webforms мы постоянно сталкиваемся с формами. По умолчанию, это одна серверная форма <form id=”aspnetForm” runat=”sever”>, расположенная сразу же за тегом <body>. Но это, можно сказать, классический пример - такую заготовку делает нам Visual Studio при создании другого проекта. На практике же всё может сильно отличаться.

 

Следует отметить, что на странице вы не можете создать более одной серверной формы (с атрибутом runat=”server”). Такое уж ограничение архитектуры ASP.NET. Почему так - догадаться не сложно, но...

 

Но в жизни в проекте бывают ситуации, когда просто необходимо добавить ещё одну форму на страницу. Из достаточно распространённых примеров это: 

 

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

 

Решение данной задачи достаточно простое - добавление второй формы (<form>) на страницу, но уже без атрибута runat=”server”. Следует отметить, что с точки зрения html - несколько форм на одной странице являются абсолютно нормальным и работающем решением. Если только не наступать та те же грабли, на которые наступил я...

 

А допустил я достаточно “детскую” ошибку - т.к. было ограничение на одну серверную форму, то я добавил вторую, клиентскую, внутрь серверной. На первый взгляд всё работало хорошо, обе формы успешно отправлялись на сервер и отправляли все необходимые данные. Вот только работало это в браузерах Google Chrome, Safari и FireFox. Проблемы начались в Opera и Internet Explorer. Выглядело это, на мой взгляд, действительно потрясающе: 

 

Форма фидбека с UpdatePanel двумя TextBox и LinkButton на странице. Обработчик OnClick у кнопки успешно отрабатывал, за исключением того, что значения текстбоксов были пустыми. Дело было вечером и я подумал что проблема в UpdatePanel. Вот только странно было что в IE это тоже не работало. Под нож попала UpdatePanel, что не дало никакого положительного результата. “Странно” - подумал я и проверил это всё ещё раз в разных браузерах. Баг был на месте. Тут пришлось вплотную взяться дебаггером за эту страницу и через некоторое время, внимательно посмотрев на Request.Params причина была обнаружена - сабмитилась не та форма.

 

Дальнейшие танцы с бубном возникшие идеи результата не принесли я на помощь пришел Google:

 

 

Обрадовало меня сразу две вещи:

 

  • такая проблема была не только у меня;
  • причина всего этого безобразия стала ясна уже только при беглом просмотре результатов выдачи гугла - 3-я ссылка вела на сайт W3C, на которой черным по белому было написано: “the FORM element can’t be nested”. (http://www.w3.org/MarkUp/html3/forms.html)

 

 

После этого проблема была быстро решена способом, описанным в начале поста, но мне захотелось ещё немного копнуть внутрь.

 

Тут же был создан небольшой html файл (forms1.html)  и был дан валидатору http://validator.w3.org/. К моему удивлению, валидатор был уверен в том, что html код является полностью валидным. После смены doctype с Transitional на Strict (forms2.html) страница уже оказывалась невалидной. И тут всё окончательно прояснилось и стало на свои места.

 

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

 

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

 

Исходники форм: https://github.com/e0ne/BlogSamples/tree/master/NestedForms

 


Чем дольше пользуюсь NuGet, тем больше интересных вещей с его нахожу. Одной из таких библиотек является elmah. Простота установки, особенно с использованием NuGet, и широкие возможности настройки подойдут к практически любому проекту. Я сам для этого раньше предпочитал использовать Logging модуль из Microsoft Enterprice Library, но сейчас понял что есть более гибкие и современные решения.

Elmah создан специально для того, чтобы логировать ошибки в ASP.NET приложениях.

Среди его функций есть такие:

  • логирование ошибок в различные БД (MS Sql, Oracle, PostgreSQL, SQLite и др.);
  • экспорт логов в формат CSV для последующего анализа;
  • создание RSS-фида для получения информации о новых ошибках;
  • отправление сообщений о новых исключениях прямо в ваш twitter!

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

Если вы всё ещё по каким-то причинам не используете NuGet, то для вас установка будет происходить следующим способом:

  • скачать сборку Elmah.dll (всего 156KB);
  • добавить в ваш веб-проект reference на elmah;
  • последний и самый сложный пункт - внести необходимые изменения в web.config.

Так как elmah работает как обычный web handler, то проблем с ним быть никаких не должно.

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

Для того, чтобы посмотреть последние логи, необходимо открыть следующий URL: http://localhost:8090/elmah.axd. В качестве тестового приложения я создал новый Web Application и посмотрел на логи:

На удивление обнаружил, что в логах уже есть одна 404-я (Not Found) ошибка. Посмотрев на детали исключения сразу становится понятно, что не найден файл favicon.ico.

Для примера, я поместил на страницу кнопку, обработчик OnClick которой бросает исключение:

throw new NotImplementedException();

Посмотрим теперь на нашм логи:

У нас появилась запись с кодом 500 (Server Error) и типом NotImplemented.

В деталях каждой записи кроме времени и текста ошибки хранится полный callstack, все параметры, которые пришли в запросе (Request.Params) и, на мой взгляд самое интересное - ссылка с именем “Original ASP.NET error page”. Перейдя по ней можно посмотреть как выглядела страница, когда произошла ошибка. Таким образом можно увидеть что показывалось пользователю, когда это случилось.

Последняя фича, о которой я хотел бы сказать - это возможность настройки фильтрации исключений. Это позволит вам логировать только те исключения, которые вам необходимы.

На этом мой короткий обзор закончен. Более детально об elmah можно прочитать на официальной странице (http://code.google.com/p/elmah/). Моей целью не было написать полный и подробный обзор-руководство по этой очень удобной и полезной библиотекой. Цель этого поста - всего-лишь познакомить с elmah тех читателей, которые еще не слышали о ней.

P.S. Для самых ленивых выложил тестовый проект на GitHub: https://github.com/e0ne/BlogSamples/tree/master/ElmahSampleProject


Со времен ASP.NET 1.1, по умолчанию, у всех страниц свойство ValidateRequest было равно true. Это означает, что при вводе в поле ввода определенные спецсимволы (пример: <,>,&,#)  и отправки формы на сервер мы успешно получим HttpRequestValidationException.

Непонятное, на первый взгляд, поведение объясняется достаточно просто - защита от XSS атак. XSS (cross site scripting) - один из типов атак на веб-сайт, целью которой является вставка (инъекция)  чужого javascript-кода на атакуемый сайт. Результатами такой атаки могут быть от показа пользователю ненужных ему сообщений, до кражи cookie и перенаправления на другой сайт, который может содержать вредоносный код. Пример такой ситуации можно посмотреть в XssSample.aspx.

Но так как в определённых ситуациях должна быть возможность ввести любой символ, то приходится отключать request validation. Для предотвращения XSS-атаки при отображении пользователю введенного текста необходимо экранировать специальные символы с помощью метода Server.HtmlEncode(). Пример кода находится в AntiXssSample.aspx.

На первый взгляд, кажется что всё просто и понятно. Но есть некоторые нюансы:

  • необходимо помнить о том, что request validation отключен и нужно экранировать весь введенный пользователем текст во все поля (помним правило: никогда(!) не доверять данным, которые ввёл пользователь);
  • если используется Server.HtmlEncode(), то помним, что есть ещё “обратный” метод Server.HtmlDecode();
  • можно не отключать request validation и экранировать все введенные данные на стороне клиента с помощью javascript, но при этом не забывать о валидации (проверки) данных на сервере.

В целом, при правильном подходе никаких проблем с отключением request validation не должно быть, но всегда необходимо помнить о безопасности.

Ещё стоит отметить то, что механихм request validation немного поменялся в ASP.NET 4. Теперь он, по умолчанию, проверяет не только запросы к aspx страницам, но и все остальные запросы к серверу. Отключить это можно в web.config таким способом:

<httpRuntime requestValidationMode="2.0" />

Ссылки по теме:

Ссылка на пример: https://github.com/e0ne/BlogSamples


1. Введение
2. Обзор framework'а
3. Жизненный цикл страницы
4. Полезные объекты и функции

1. Введение

В предыдущем посте из этой серии (ASP.NET Ajax. Часть 1: что внутри?) я рассказал что такое AJAX и как Microsoft помогает нам его использовать. Сегодня я более подробно расскажу о его клиентской части. Частично из-за того, что эту информацию не так просто найти в MSDN, как хотелось бы, частично  из-за того, что в последнее время Microsoft уделяет этой части всё меньше внимания, агитируя использовать jQuery, многие разработчики даже на догадываются какой мощных инструмент находится у них в руках.

2. Обзор framework'а

По умолчанию, эти скрипты грузятся на страницу, на которой есть ScriptManager по ссылке вида ScriptResource.axd?d=scriptIdentificator. Сами же скрипты находятся в ресурсах сборки System.Web.Extensions (если у кого-то всё-ещё установлена VS2005, то эти скрипты можно найти в папке c:\Program Files\Microsoft ASP.NET\ASP.NET 2.0 AJAX Extensions\v1.0.61025\MicrosoftAjaxLibrary\System.Web.Extensions\). Также можно загружать эти скрипты с помощью CDN. Подробнее об этом способе можно почитать тут.
Сам скирт немного отличается для WebForms и ASP.NET MVC, но ядро у них общее.
Все функции/объекты разделены на пространства имён (namespaces) по аналогии с серверной частью. Перечислять я их не буду, так как на MSDN (http://msdn.microsoft.com/en-us/library/bb397536.aspx, http://msdn.microsoft.com/en-us/library/dd410060.aspx) всё хорошо описано.

3. Жизненный цикл страницы

Кроме стандартных для DOM модели событий, ASP.NET Ajax предоставляет нам  доступ как к событиям всего приложения (init, load, unload и др.), так и события, связанные с запросами на сервер (beginRequest, endRequest и др.). Как всегда, за полной информацией лучше обратиться в первоисточник, а именно - http://msdn.microsoft.com/en-us/library/bb386417.aspx.

4.Полезные объекты и функции

MS Ajax Library предоставляет нам как новые типы/функции, так и расширения для стандартных - Array, Number, Date, String и др., о которых можно почитать в MSDN Magazine (http://msdn.microsoft.com/en-us/magazine/cc163300.aspx).
Одними из наиболее частоиспользуемых являются функции $get() и $find():
- $get()  - оптимизированный по производительности аналог document.getElementById, который ищет элемент по его ID и в качестве второго параметра может принимать parent-элемент, в котором нам необходимо найти нужный элемент DOM-модели.
- $find() - функция, которая очень похожа на $get(), но возвращает не DOM-элемент, а экзепмляр Ajax Client Control.
Более детальное описания использования этих функций: http://mattberseth.com/blog/2007/08/the_everuseful_get_and_find_as.html


HTML Decode/Encode.

Если кто-то слышал об такой атаке на веб-сайты, как XSS Injection, то он(она) знает что для предотвращение такой атаки необходимо использовать функции HtmlEncode/HtmlDecode. XSS Injection (Cross-site injection) - один из способов атак веб-приложений, главной идеей которого является вставка(инъекция) чужого javascript-кода на атакуемый веб-сайт. Как минимум, это может привести к краже печенек cookies и получении прав администратора сайта. ...

1.1. ASP.NET

Это происходит, примерно, так:
Допустим, у нас есть форма для отправки комментарием, где пользователь вводит свой еmail и текст коммеентария. Самый простой обработчик кнопки добавить окмментарий будет выглядить так:

protected void OnAddCommentClick(object sender, EventArgs e)
{
 var pageId = this.GetPageId();
 var email = this.txtEmail.Text;
 var comment = this.txtComment.Text;
 CommentsService.AddComment(pageId, email, comment);
}

С первой точки зрения этот код не содержит никаких ошибок, компилируется и корректно сохраняет данные в БД. Но, если в тексте  комментария будет любой HTML или JavaScript-код, то при отображении этого комментария на страницу без предварительной обработки мы увидем, что HTML и JavaScript-код без особых проблем обрабатываются браузером.
Таким образом, мы сделали наш сайт уязвимым и нарушили одно из базовых правил проектирования ПО: “Не доверять данным, которые пришли извне нашей системы”. От себя еще добавлю: вдвойне недоверять данным, которые были введенны пользователем. Чтобы исправить это ошибку, необходимо всего-лишь вызвать метод HttpServerUtility.HtmlEncode(), перед сохранением данных в базу:


 var email = Server.HtmlEncode(this.txtEmail.Text);
 var comment = Server.HtmlEncode(this.txtComment.Text);

После чего, строка вида “<script>alert(‘hello!’);</script>” будет сохранена в базу в таком виде:

 &lt;script&gt;alert(‘hello!’);&lt;/script&gt;

Теперь все хорошо: любой введенный пользователем текст не ламает нашу верстку и не вызывает выполнения стороннего javascript (пример 2).
Но все не так просто, как кажется. Теперь, если такой код вставить в обработчике OnAddPage(), где администратор сайта будет добавлять страницы, то вместо красивого текста пользователи увидят набор непонятных символов. Поэтому, при отображении содержимого страницы мы вызываем метод HttpServerUtility.HtmlDecode(), который переведет сохраненный в базе данных текст в такой вид, чтобы браузер его корректно обрабатывал.

Таким образом, мы избавили наш сайт от XSS Injection дали возможность пользователям воодить разнообразные данные без вреда для сайта.

Примечание. Во всех примерах выше свойство странице EnableRequestValidation было установлено в false для возможноти ввода символов “<“ и “>”.
Примечание для ASP.NET 4.0/ASP.NET MVC 2.0. В ASP.NET 4.0/ASP.NET MVC 2.0 появилась конструкция <%: ... %>, которая делает за нас HTML Decode/Encode.

1.2. JavaScript

Если нам необходимо реализовать данную функциональность на клиенте с помощью javascript, то нам на помощь приходит jQuery:

function htmlEncode(html) {
 return $('<div/>').text(html).html();
}
function htmlDecode(text) {
 return $('<div/>').html(text).text();
}

1.3 Python/Django

В фреймворке Django HTML Decode работает по умолчанию, и для его отключение в шаблоне (template) добавить блок {% autoescape off %} и в нем поместить все элементы, для которых нам не нужен HTML Decode, после чего закрыть блок с помощью {% endautoescape %}.

2. URL Decode/Encode.

В отличии от HTML Encode/Decode незаэкранированный url больших проблем не вызывает, за исключением двух моментов: url становится не таким простым и понятным для пользователя и это не очень хорошо влияет на SEO.

2.1 ASP.NET

Рассмотрим такую ситуацию: у нас есть сайт с функцией поиска по нем. Стандартная форма поиска содержит поле для вводи и кнопу "Поиск". В простейшем случае при нажатии на кнопку “Поиск” у нас есть такой обработчик:


protected void OnSerachClick(object sender, EventArgs e)
{
 var searchText = this.txtSearch.Text;
 car url = String.Format(“{0}?q={1}”, VirtualPathUtility.ToAbsoluteUrl(“~/Search.aspx”), searchText);
 Response.Redirect(url);
}

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

/Search.aspx?q=some%20keywords

Конечно, такой url правильно обрабатывается браузером, но не всем пользователям будет понятно что он значит. Происходит это из-за того, что браузер автоматически заменяет символ пробела и ряд других символов на  их шестнадцатиричное значение вида %XX, где XX - код символа в шестнадцатиричной системе.
Сделано это было давно, кода браузеры были маленкими еще не умели отображать нелатинские символы в строке ввода адреса и для правильного отображения разнообразных символов.
И тут нам на помощь приходят методы HttpServerUtility.UrlEncode() и HttpServerUtility.UrlDecode() которые предназначены для переобразования параметров строки запроса в понятный для пользователей вид. Отдельно отчему, что эти методы предназначены для обработки исключительно параметров url, а для переобразования адреса к необходимому ресурсу существует метод HttpServerUtility.UrlPathEncode(), работа которого больше похожа на работу метода HttpServerUtility.HtmlEncode(), но учитывает все особенности построения url. Этот метод не имеет метода для обратного переобразования, но при правильном подходе к проектированию приложенич это не понадобится.

2.2. JavaScript

Аналог URL Encode в javascript - функция encodeURI()


В декабре прошлого года я написал пост по названием “Программирование на .NET: С чего начать?” на тему того, чтобы почитать начинающим разработчикам на платформе .NET. С того момента прошло достаточное количество времени и могло появиться желание или необходимость, начать писать веб-приложения на основе технологиеи ASP.NET. Не важно, будет это ASP.NET Webforms или ASP.NET MVC - в любом случаем, знание одной технологии не мешает познакомиться с другой. Далее я приведу список книг/блогов, которые рекомендую для знакомства с веб-разработкой на основе .NET Framework.

  • Начну с книги Дино Эспозито “Introducing Microsoft ASP.Net 2.0” - отличное введение в ASP.NET 2.0. Несмотря на то, что этот замечательный автор уже написал книгу по ASP.NET 3.5, эта книга не теряет соей актуальности и служит отличным введением в мир веб-разработки на основе технологий от Microsoft.
  • Книга “Programming Microsoft ASP.NET 3.5" является хорошим продлолжением предыдущей и не нуждается в комментариях. Добавлю лишь одно: некоторые считают что эти две книги все-равно что книга Дж. Рихтера CLR via C#.
  • Marco Bellinaso, “ASP.NET 2.0 Website Programming: Problem - Design - Solution” - книга, которая почетное место на моей книжной полке. Книга описывает процесс создания сайта под названием BeerHouse Project от начала и до конца. Если что-то непонятно, то всегда можно посмотреть исходники этого проекта. Отличная книга для начинающих, чтобы познакомиться с процессом создания сайта от начала и до конца.
  • Следующая книга от сразу двух авторов Matthew MacDonald и Adam Freeman имеет название “Pro ASP.NET 4 in C# 2010”. Я читал более старое название про ASP.NET 2.0. В книге достаточно подробно описывается технология ASP.NET, но читать ее нужно когда базовые знания уже есть.

Технология ASP.NET MVC более молодая и выбор книг значительно меньше. Большинство из них написаны про первую версию этого фреймворки и из-за значительных изменений настоятельно рекомендую читать книги по актуальной на сегодняшний день версии 2.0.
Это такие книги, как:

  • "Pro ASP.NET MVC 2 Framework" от Steven Sanderson - очень подробно и понятно написаны как основы, так и достаточно продвинутые вещи о ASP.NET MVC.
  • "ASP.NET MVC 2 in Action" ) от сразу пяти авторов. Если коротко, то я еще не встречал ни одной книги из этой серии, которая бы меня не заинтересовали и после прочтения которой я бы пожалел о потраченном времени.
  • Еще есть книга “ASP.NET MVC Framework” по ASP.NET MVC 2.0 от русских авторов Гайдара Магданурова и Владимира Юнева. Т.к. книгу только пролистал на балке, то никаких комметариев о ней писать не буду за исключением того, что она вполне годиться для введения в данную технологию.

С книгами закончили, теперь пройдемся по списку веб-ресурсов, RSS которых я регулярно читаю:

  • Сайт http://www.asp.net/ от Microsoft. Название говорит само за себя. Отличный ресурс с форумами, блогами, вики, ссылками на различные opensource приложения. Отдельно хочу выделить раздел с обучающим видео. Это лучше увидеть самому! Единственным их недостатком является то, что они могут ввести в ошибочное заблуждение, что разработка любого сайта - очень и очень простое занятие. В остальном - обязательно смотреть начинающим веб-разработчикам.
  • http://weblogs.asp.net/scottgu/ - блог Скота Гатри. Его должность решил не переводить, а процитировать с его блога:
    "My name is Scott Guthrie, and I am a Corporate Vice President in the Microsoft Developer Division. I run the development teams that build the following products/technologies: CLR and the core .NET Base Class Libraries, ASP.NET, Silverlight, WPF, IIS 7.0, Visual Studio Tools for ASP.NET, WPF, Silverlight and Mobile". Отличные технические посты о самых новых технологиях! Очень часто после публикации очередного поста проходит не одна неделя/месяц до того, как очередная технология/приложение станет доступным для разработчиков.
  • http://dev.net.ua/ и http://msug.vn.ua/ - сайты харьковской и винницкой .NET User Group - не только об asp.net, но и о других технологиях Microsoft.
  • http://www.nikhilk.net/ - Nikhil Kothari's Weblog - блог разработчика из Microsoft, посвященный веб-технологиям.
  • И последнее: MSDN - без него сложно представить жизь разработчика.

Продолжение следует. В следующем посте из серии для начинающих (веб)разработчиков я расскажу о том, что необходимо знать любому разработчику на платформе ASP.NET.


В связи с тем, что я повсеместно пытаюсь избавиться от ASP.NET AJAX Control Toolkit (ACT) и перейти на использование jQuery, то от использования Hover Extender от ACT пришлось отказаться. Сразу же было найдено большое количество разнообразных плагинов для jQuery, но большинство из них имели недостаточную реализацию, из-за чегоостановился на jQuery plugin EZPZ Tooltip.

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

  • "Чистый" HTML - не нужно добавлять специальные атрибуты для элементов, плагин завязывается на отдельный HTML элемент.
  • Конфигурация через наименование (Convention over configuration) - поведение элементов зависит от из ID.
  • Гибкие настройки - с помощью CSS можно настроить как внешний вид контрола, так и его позиционирование.
  • Возможность замены стандартных эффектов путем перехвата соответствующих событий на jQuery.
  • Удобство и простота работы.
  • Маленький размер - 4.5K в сжатов виде.

Более подробно о всем этом можно почитать на странице проекта, а я хочу рассказать как можно его использовать в связке с ASP.NET на примере простого UserControl.

Для инициализации контрола нужно выполнить небольшой javascript:

$("#example-target-1").ezpz_tooltip();
или
$("#target").ezpz_tooltip({contentId:"content"}); - В случае если у наших HTML-элементов будут "нестандартные" для этого контрола ID.

Так как, ASP.NET сам генерирует нам ClientID элементов (я не учитываю специфику ASP.NET 4.0, где можно отключать автоматическую генерацию ClientID), то приходится использовать 2-й вариант таки образом:

 

При этом у нас:

  •  TargetControlId - ID элемента, при наведении на который будет отображаться наш hover (tooltip).
  • ContainerClientId - ID элемента который будет показываться в качестве hover (tooltip).

 Разметка нашего user control выглядит так:

 

Нам остаётся только разместить наш UserControl на странице и подключить необходимые стили и скрипты. Можно ещё сделать WebControl, но это уже зависит от конкретной задачи. В моём случае UserControl был предпочтительнее.

HoverControl.zip (31.35 kb)


DevConf 2010

Published 5/16/2010 by e0ne in Python | Web Development

DevConf 2010 уже завтра. До поезда в Москву осталось чуть более 3-х часов. Посмотрел финальную програму и немного расстроился: даже не смотря на то, что едем мы вдвоём, из-за плотного расспеисания и немкольких паралельных потоков врядли получится попасть на все интересующие доклады :(. Надеюсь что организаторы запишут и выложут видео.


Почему-то, всегда забываю синтаксис вызова script service/method. Руки так и тянуться написать:

var result = ScriptServiceExample.AsmxService.Hello;
или
var result = ScriptServiceExample.AsmxService.Hello();

И каждый раз, после написания такого когда приходится лезть в MSDN/Google чтобы понять почему же оно не работает. После прочтения документации становится понятно "как" нужно писать вызов метода, но вопрос "почему" ответ, как правило, находится не сразу. Чтобы понять почему же всё работает именно так, достаточно посмотреть JavaScript код, который генерируется службой. Посмотреть это можно зайдя по адресу http://localhost:65456/AsmxService.asmx/js и сохранив себе js-файл следующего содержания:

Type.registerNamespace('ScriptServiceExample');
ScriptServiceExample.AsmxService=function() {
ScriptServiceExample.AsmxService.initializeBase(this);
// ...
Hello:function(succeededCallback, failedCallback, userContext) {
return this._invoke(this._get_path(), 'Hello',false,{},succeededCallback,failedCallback,userContext); }}
// ...

С WFC AJAX-enabled службами всё работает также.

 

ScriptServiceExample.rar (7.44 kb)


ASP.NET + Mono + Apache

Published 9/22/2009 by e0ne in Mono | Web Development

Всё больше и больше можлно услышать о Mono. Как изестно, основное его идеей является реализация действительно кроссплатформенной среды .NET. Таким образом, чеще всего Mono испльзуют в операционной системе, отличной от MS Windows. А если не Windows, то Linux или какой-то из Unix. И всё было бы хорошо, если б не 2 момента (в данном случае я не акцентрирую внимание на степень готовности реализации Mono: аналог WinForms и замена Internet Information Services (IIS).На за мену WinForms приходят GTK, QTи другие библиотеки. А вот с заменой IIS все не тах хорошо: либо Apache с соответствующими модуляли, либо "родной" для Mono веб-сервер XSP2. А так как Apache наиболее популярен, то будем пользоваться им.

Все примеры я буду приводить для Ubuntu linux, но для других nix-подобных ОС все будет делаться таким же способом, за исключением установки пакетов.

Для начала нам все же надо установить Mono и IDE для нее. В качестве IDE  будем использовать MonoDevelop. Устанавливаем всё необходимое:

apt-get install mono-2.0-runtime mono-2.0-gac mono-2.0-service mono-2.0-devel mono-xsp2 mono-xsp2-base 

После чего можно запустить MonoDevelop, созать простое ASP.NET приложение и запустить. В результате получаем что-то похожее на это:

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

Для наала, устанавливаем необходимы пакеты:

sudo apt-get install apache2 mono-apache-server2 libapache2-mod-mono

 

Говорим веб-серверу о необходимости загрузки нового модуля:

sudo a2enmod mod_mono

И создаём новый конфиг (/etc/mono-server2/monotest.webapp) для нашего приложения:

  <apps>
      <web-application>
         <name>Mono test</name>
         <vpath>/mono</vpath>
         <path>/var/www/</path>
        <vhost>localhost</vhost>
      </web-application>
</apps>


Последние что нас осталось сделать - это подправить конфигурационный файл Apache'а для нашего сайта (/etc/mono-server2/mono-server2-hosts.conf). Добавляем в него такие строки:

Alias /mono "/var/www"
AddMonoApplications default "/mono:/var/www"
    <Directory /var/www>
       SetHandler mono
          <IfModule mod_dir.c>
             DirectoryIndex Default.aspx
          </IfModule>
    </Directory>

Перезагружаем Apache командой:

sudo /etc/init.d/apache2 restart

И смотрим в браузере что у нас получилось: