Давно пользуюсь Outlook для чтения корпоративной почты. Для личной переписки вполне хватает веб интерфейса Gmail + оповещение о новых письмах в браузере. Т.е. о получении новых личных писем я узнаю быстро.
Но в Outlook есть определенная проблема с показом оповещений. Почему то тут все намного сложнее. Если письмо попадает в Входящие, то в трее появляется значок конверта и всплывает небольшое окно с информацией о письме. Т.е. сразу видно, что тебе письмо, от кого оно и что в нем.
Если же сделать правила и сортировать письма по папкам, то оповещения не показываются и что бы проверить почту нужно или время от времени открывать Outlook или постоянно держать его открытым на втором мониторе.
Почему разработчики Outlook реализовали такое поведения не знаю, но достает это реально. Раньше все мои попытки, что либо настроить терпели неудачу. Все что удавалось это показывать оповещения о новых письмах, обработанных правилами в модальном окне, что не совсем удобно. И вот я наконец нашел решение, оказалось, что все таки нужно донастроить правила.
Допустим у нас есть набор готовых правил сортировки писем.
Открываем Outlook, выбираем в меню Сервис -> Правила и оповещения
Выбираем вкладку "Правила для электронной почты"
Выбираем правило и в меню "Изменить параметры правила"
Пропускаем "Какие сообщения следует отбирать?" и жмем "Далее"
В разделе "Что следует сделать с сообщениями?" находим действие "вывести оповещение на рабочий стол", у меня это в самом низу списка
Жмем "Готово"
В результате при получения сообщений, которые обрабатываются этим правилом, мы получим маленькое всплывающее окно с информацией о письме. Это позволит реагировать на письма быстрее.
Недавно был на конференции Microsoft посвященной VS2010 там порекламировали перевод руководства по проектированию архитектуры приложений.
Ребята из PATTERNS & PRACTICES выпустили новую версию, а наши перевели его на русский. Начал его читать и всем советую.
Цель данного руководства – помочь разработчикам и архитекторам решений создавать эффективные высококачественные приложения на платформе Microsoft и .NET Framework в более сжатые сроки и с меньшими рисками благодаря использованию проверенных и снискавших доверие архитектурных принципов и шаблонов проектирования.
В руководстве предлагается обзор основных принципов и шаблонов, которые обеспечивают прочную базу для создания хорошей архитектуры и дизайна приложения. В дополнение к этой базе даются общеприменимые рекомендации по разделению функциональности приложения на слои, компоненты и сервисы. Далее приводятся советы по определению и реализации ключевых характеристик дизайна, основных атрибутов качества (таких как производительность, безопасность и масштабируемость) и сквозной функциональности (такой как кэширование и протоколирование). В завершение руководство предлагает рекомендации по архитектуре и дизайну наиболее общих типов приложений, таких как Веб-приложения, насыщенные Интернет-приложения (RIA), насыщенные клиентские приложения, сервисы и мобильные приложения.
Руководство разделено на части соответственно основным аспектам архитектуры и дизайна. Оно скомпоновано таким образом, чтобы могло использоваться и как справочник, и как учебное пособие.
С появлением ASP.NET 2.0 и VS 2005 у разработчиков веб приложений появился новый тип проектов Website, который позволял изменять динамически не только дизайн страниц, но и c# код. Этой возможностью многие стали пользоваться, но все это удобство достигается за счет того, что каждая страница и контрол компилируются по отдельности. При довольно большом размере проекта, компиляция занимает очень много времени. К тому же модель Website по умолчанию не добавляет namespace для страниц, что ведет к путанице и даже странным ошибкам компиляции.
У нас на проекте решили преобразовать существующий огромный Website в Web Application Projects. На первый взгляд казалось, что достаточно будет запустить визард конвертации, немного протестировать и все будет в порядке.
Открываю проект и ищу что то типа "Convert to web application", но не нахожу. Оказывается все намного сложнее.
Работая с WCF редко приходится задумываться "А в каком виде сообщения передаются между клиентом и сервером". В общем случае, достаточно настроить web.config, что бы изменить протокол передачи данных.
Иногда для диагностических целей или для того что бы показать кому то пример сообщения, нужно эти сообщения увидеть. Для реализации этой задачи есть два способа.
1. Воспользоваться приемами трассировки.
2. Реализовать заказное поведение оконечной точки.
Трассировка и протоколирование сообщений в WCF
Трассировка используется для вывода информации о потоке выполнения и отдельных действий различных компонентов распределенного приложения. Механизм же протоколирования сообщений предназначен для сохранения содержимого сообщений, которыми обмениваются клиент и служба.
Протоколирование сообщений основано на классах из пространства имен System.Diagnostics и по умолчанию выключено. Что бы его включить, необходимо сначала добавить прослушиватель трассировки (например, XmlWriterTraceListener) для обработки информации от источника трассировки System.ServiceModel.MessageLogging.
Мы добавили источник System.ServiceModel.MessageLogging, с помощью которого выводятся сообщения для протоколирования. Обрабатываем же получаемую от него информацию прослушивателем XmlWriterTraceListener.
Теперь в файл messages.svclog пишутся логи сообщений. Для чтения и анализа этого файла можно воспользоваться программой Service Trace Viewer. Она может использоваться для импорта протоколов сообщений, сформированных одним или несколькими компонентами распределенного приложения. Эта программа входит в пакет Windows SDK.
Реализация заказного поведения для трассировки.
Заказные поведения позволяют вставить код в стратегически важные места. на этапе инициализации исполняющей среды, а также в контейнер обработки сообщений.
Реализация заказного поведения состоит из трех шагов:
Шаг 1. Создать класс, который реализует интерфейс Inspector, Selector, Formater или Invocer. В нашем случае это IClientMessageInspector
internal class LogMessageInspector : IClientMessageInspector
{
public object BeforeSendRequest(ref Message request, IClientChannel channel)
{
Console.WriteLine("---request---");
Console.WriteLine(request.ToString());
Console.WriteLine("---end---");
return request;
}
Шаг 2. создать класс, который реализует один из интерфейсов поведения: IServiceBehavior, IEndpointBehavior, IOperationBehavior или IContractBehavior. У нас это IEndpointBehavior.
public class LogEndpointBehavior : IEndpointBehavior
{
public void Validate(ServiceEndpoint endpoint)
{
}
public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
{
}
public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
{
}
Шаг 3. Сконфигурировать клиент или службу, так чтобы они использовали созданное поведение. Это можно сделать в коде, в конфигурационом файле или с помощью атрибутов.
Я сделал это в коде клиента, при создании экземляра прокси.
ChannelFactory<IFilms> factory = new ChannelFactory<IFilms>("poxWcfService");
//Add logging of message to console
factory.Endpoint.Behaviors.Add(new LogEndpointBehavior());
IFilms client = factory.CreateChannel();
Собственно все, можно запускать консольный клиент и смотреть, а что же и в каком виде мы передаем на сервис.
Месяц назад попробовал поставить дома Wondows 7 64bit, в качестве антивируса решил попробовать Security Essentials от Микрософта, благо он тоже зарелизился да и бесплатный.
Одновременно сменил интернет провайдера и роутер. Провайдером стал Триолан, скорость 100Мбит всего за 90 грн. Роутер поставил гигабитный Linksys WRT320N
В результате HD рипы 1080p, по 8 гиг качаются всего за 15 минут из интернета, в общем счастье наступило.
Но, через некоторое время стала временами отваливаться сеть, запускаю диагностику сети, выполняется сброс сетевого адаптера и сеть поднимается. Долго думал, кто виноват, сетевая, роутер или провайдер.
Похоже виноватым оказался антивирус от Микрософт - Security Essentials. Как то копировал 40 гигабайтный файл на внешний винчестер, но он что то очень медленно читался, начал искать виноватого, оказалось антивирус съел всю память, пытаясь проанализировать этот файл.
Снес антивирус от Микрософта, поставил nod32 и о чудо сеть больше не падает и память не кончается.
Вот такой антивирус написан Микрософт, что и сеть от него падает и файлы большие не скопировать.
WCF позволяет реализовать обработку ошибок при помощи контрактов ошибок. Подробней об этой методике можно почитать на RSDN http://www.rsdn.ru/article/dotnet/FaultsWCF.xml или в книге “Основы WCF ” Стива Резника, глава 10 - Обработка исключений. Но там рассматривается только обработка исключений при SOAP коммуникациях, для REST нужна дополнительная реализация.
Ниже я покажу, как можно реализовать обработку ошибок для REST сервиса, который реализует две точки доступа POX и JSON.
Давайте создадим WCF службу ReliableService с единственным сервисом Films, который реализует каталог домашних фильмов. Сервис будет содержать 5 методов:
·Counts – количество фильмов в каталоге
·GetFilm – вернуть описания фильма по ID
·GetFilmNames – вернуть последние добавленные фильмы
·GetFilmsByGenre – вернуть фильмы по жанру
·AddFilm – добавить фильм в каталог
Создаем новый проект WCFServiceApplication, удаляем существующий сервис из проекта и из web.config. И добавим новый сервис Films. Добавим в интерфейс этого сервиса 5 методов, которые можно вызывать через REST.
Итак, мы имеем RESTсервис, который может возвращать ответ в виде XML или JSON. Теперь давайте посмотрим, что будет если во время работы серсива произойдет ошибка. К примеру если метод GetFilm вызвать без параметра
The server encountered an error processing the request. The exception message is 'Value cannot be null. Parameter name: key'. See server logs for more details. The exception stack trace is:
Пользователю лучше не видеть наших внутренних ошибок, давайте для начала отключим показ деталей ошибок в конфигурации, для этого нужно установить
The server encountered an error processing the request. See server logs for more details.
Лучше, но не информативно. Разработчик, который будет использовать наш сервис, не сможет понять, в чем ошибка и будет просить нас проверить наши логии. Давайте попробуем реализовать контракты ошибок, как это описано в ссылках, которые я приводил выше. Неплохо бы разделить ошибки, в которых виноват клиент и в которых виноват сервер. Для этого будем возвращать типизированные контракты ошибок FaultContract.
Для начала нужно в интерфейсе каждому методу добавить пару атрибутов:
[OperationContract]
[WebGet]
[FaultContract(typeof(ClientError))]
[FaultContract(typeof(ServerError))]
FilmEntity GetFilm(string filmID);
Во вторых реализовать два класса ClientError и ServerError, они будут содержать подробное описание ошибки, к примеру, дата ошибки и сообщения об ошибке для разработчика и конечного пользователя. Т.е. разработчик клиента для нашего сервиса может не придумывать сообщения для пользователя, а использовать готовое сообщение.
[DataContract]
publicabstractclassCatalogError
{
[DataMember(Order = 1, IsRequired = true)]
publicDateTime Date { get; set; }
[DataMember(Order = 2, IsRequired = true)]
publicstring SystemMessage { get; set; }
[DataMember(Order = 3, IsRequired = true)]
publicstring CustomerMessage { get; set; }
}
[DataContract]
publicclassClientError : CatalogError
{
public ClientError(string systemMessage, string customerMessage)
public ServerError(string systemMessage, string customerMessage)
{
Date = DateTime.Now;
SystemMessage = systemMessage;
CustomerMessage = customerMessage;
}
}
Осталось научить наш сервис возвращать ошибки в таком виде. Для этого нужно создать класс реализующий IErrorHandler, атрибут ErrorHandlerBehavior и добавить атрибут в реализацию сервиса.
publicclassCatalogErrorHandler : IErrorHandler
{
privateconststring InternalErrorCustomerMessage = "We are having technical issuse at the moment, please try again.";
Если бы мы работали по SOAP, этого было бы достаточно, но для REST это не работает.
Для того что бы и для REST подхода заработала архитектура контрактов ошибок WCF, нам нужно сделать обработчики ошибок, которые сериализуют ошибку в нужный нам формат. Для того что бы служба знала как возвращать ошибки для различных точек доступа, также создадим расширения поведения точек доступа.
Для начал сделаем два дополнительных обработчика ошибок PoxErrorHandler и JsonErrorHandler:
Не забудем использовать эти расширители в точках доступа
<endpointBehaviors>
<behaviorname="poxBehavior">
<webHttp/>
<faultingPox/>
behavior>
<behaviorname="jsonBehavior">
<enableWebScript/>
<faultingJson/>
behavior>
endpointBehaviors>
Дело сделано, теперь в случае ошибки наши REST точки доступа будут возвращать контракты ошибок в нужном формате. Например для POX вызовем метод GetFilm без параметров