MCP
Показаны сообщения с ярлыком .net. Показать все сообщения
Показаны сообщения с ярлыком .net. Показать все сообщения

понедельник, 18 января 2010 г.

DefaultHttpHandler + PNG + FireFox

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

Проблема заключается в том, что в .NET 3.5 SP1 (специально уточняю версию, ибо подобный код имеет тенденцию изменяться) данный метод не знает тип MIME для png-файлов и вместо image/png отдаёт application/octet-stream.

Что самое интересное, в большинстве случаев тут ничего страшного нет. Практически все браузеры определят содержимое по контексту и содержимому файла. Но есть одно досадное исключение , и исключение это зовут FireFox. Если попробовать скачать файл в лоб, то он не посмотрит на то, что это картинка и предложит сохранить его.

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

вторник, 8 декабря 2009 г.

70-536

Несмотря на то, что данный экзамен я сдал ещё в пятницу, всё не доходили руки написать впечатления от него. Ибо писать собственно-то и нечего.

Экзамен весьма простой, как-то даже странно сравнивать его с 70-562, ибо многие вопросы можно отвечать не задумываясь, для других, достаточно вдумчиво почитать вопрос, чтобы отсечь неверные ответы. Хотя, конечно, бывают и сложные вопросы, у меня возникли проблемы где-то с пятью вопросами, сколько реально ошибок сделал — неизвестно, но не очень много. Ибо итоговый результат: 953 балла из 1000.

Тем, кто собрался что-то сдавать, рекомендую начать с него, чтобы оценить свои силы. Материалов для подготовки по всему интернету лежит достаточно, при этом, достаточно только базовых знаний. Например, у меня попался всего один вопрос с generic'ами, пара вопросов на стандартные типы, всё остальное в принципе, напрямую к .NET 2.0 не относится (а 3.5 и не пахнет).

В принципе, особое внимание рекомендую уделить (т.к. практически никто этим не занимается): Code Access Security, System Security, Installers, Services. Ну, можно немножко еще глянуть на глобализацию и локализацию . Ну и немножко вспомнить стандартные типы, потоки, и дебаггинг. Хотя там в общем-то можно и догадаться.

В общем, на этом всё, я теперь буду пробовать готовиться к Pro-экзамену 70-564. Ден Гладких утверждает что он простой и нелепый. 

пятница, 27 ноября 2009 г.

Сдача сертификационных экзаменов Microsoft в Ярославле

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

Зачем всё это нужно?

Думаю, каждый должен решить это сам. Например, я решил так, что если я могу сдать, то почему-бы и нет? Стоит это не очень дорого, на первый взгляд всё не очень сложно, да и стоит попробовать себя в этом. Собственно собирался сдавать я давно (года этак 4 назад начал собираться ), но сдаться решил только сейчас.

Собственно, из плюшек и бенефитов вы получаете только статус MCP, красивый логотипчик и сертификат, и в общем-то всё. Естественно, понты, это святое, и повесить красивую бумажку на стену, или показать её работодателю, это может быть важной причиной.  Но ещё раз повторюсь, реальных, физических подарков вы не получите. Возможно попадёте где-нибудь под акцию, получите книжку, или можете сдать другие экзамены со скидкой, но это в общем-то не очень существенно. Возможно, магазин MCP eStore окажется для вас неплохим вариантом (кружки, ручки, сумки, майки), но доставка в Россию стоит $100, так что лучше для такого искать другие магазины.

Какая бывает сертификация?

Расскажу только в контексте разработчиков, ибо тут всё коротко и просто. Для админов список гораздо шире. Собственно, открываем соответствующий сайт и всё видим. Если не брать в расчёт устаревшие экзамены то получаем:

  • MCP(Microsoft Certified Professional) это даже не статус, а просто факт того, что ты уже что-то сдал и получил доступ к сайту. Никаких бумажек и логотипов, но для сайтов, связанных с Microsoft этого уже достаточно (itcommunity.ru, MCP-клубы, партнёрская программа)
  • MCTS(Microsoft Certified Technology Specialist) базовый статус, который подтверждает знание какой-либо технологии. Если сдавать экзамены из разных областей, то можно набрать толпу таких статусов и получить кучу сертификатов. Полностью он будет выглядеть примерно так (мой текущий статус):
     
  • MCPD(Microsoft Certified Professional Developer) Собственно главный статус для разработчика. Опять же, можно получить несколько таких статусов, самый крутой: Enterprise Application Developer 3.5, но всё равно обидно, что кончились всякие MCAD и MCSD.

Теперь, собственно о том, какие варианты есть конкретно для .NET разработчика:

  • Базовый экзамен, который практически необходим 70-536 (TS: Microsoft .NET Framework – Application Development Foundation), требуется для получения любого другого статуса. Так что рекомендую начинать сдавать с него, если вы ещё не решили, в какую сторону пойдёте. Начинайте с него и не прогадаете.
  • Для того, чтобы получить MCTS нужно сдать по крайней мере 2 экзамена. Собственно, я двигаюсь в сторону .NET Framework 3.5, ASP.NET Applications, так что начал с 70-562 (TS: Microsoft .NET Framework 3.5, ASP.NET Application Development), хотя он должен быть вторым.
  • Чтобы получить MCPD, нужно сдать специальный "Pro" экзамен по выбранной специализации. Т.е. в моём случае: 70-564 (PRO: Designing and Developing ASP.NET Applications Using Microsoft .NET Framework 3.5)
  • Когда выйдет .NET Framework 4.0, дожен появиться специальные Upgrade экзамен, так что, как вы его сдадите, вы получите уже MCPD по 4.0, и не надо будет сдавать всё заново. Но за один экзамен всё-таки заплатить придётся. Так что можете ждать фреймворка 4.0 и не сдавать экзамены 

Собственно, это про экзамены. Ещё раз сайт, на котором можно всё поглядеть и почитать: www.microsoft.com/learning/

Как зарегистрироваться?

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

  • Интернет Центр ЯрГУ (я там сдавал экзамен). В первом корпусе. Тел. 79-77-31
  • КАМИ (вроде первый в Ярославле). Чайковского, 40A (рядом с Мелоди-клабом). Тел. 72-75-55
  • Академия МУБиНТ. Советская 80. Тел. 8-915-969-90-99. Это рядом с Шинным.

Так, что смотрите, где вам удобнее, и можете туда звонить, или идти на Прометрик. Уточню: сдаёте экзамен вы не Microsoft, а отдельной конторе, точнее организации, с кем прометрик заключил договор. Соответственно на них накладываются определённые требования, так что в разных организациях всё должно быть примерно одинаково и принципиальной не должно быть. Кстати, можно сдавать не только экзамены Microsoft, но и другие, но тут я ничего не могу подсказать.

Собственно, как регистрироваться через прометрик:

  1. Идём сюда, и набираем ваучеров для скидок (15-25%, действуют до конца года). Чтобы потом не возвращаться, можно взять сразу три ваучера (они придут на почту), и потом их использовать.
  2. Идём вбивать данные на сайт прометрика: register.prometric.com
  3. Там всё по шагам, так что сложностей не должно возникнуть. В конце нас попросят зарегистрировать и оплатить стоимость экзамена. Так что, если есть карточка, то платим (через paypal нельзя, только в лоб, так что решайте, доверять или нет). Без скидок экзамен стоит $50.
  4. Ждём указанного времени, и минут за 15 приходим сдаваться.
  5. Если не получается в указанное время, можно изменить расписание, или вообще отказаться (вроде за сутки до сдачи, но это лучше уточнить).

Уточнение: Я сдавал в интернет центре ЯрГУ, и меня попросили всё-таки им позвонить, причём до регистрации. Т.е. конечно, они меня примут в любое время дня и ночи, но лучше всё же договориться заранее. Кроме того, они сказали про какой-то сдвиг, так что возможно они скажут что лучше немного другое время указать.

Процесс сдачи

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

Собственно все вопросы выдаются прометриком и идут через специальную программу. Пользоваться можно только маркером и калькулятором встроенным в тест (если нужно что-нибудь посчитать). Сотрудников можно вызывать только в случае проблем с компьютером.

Вначале возможно будет небольшой опросник, текст соглашения, возможно, небольшой опросник о ваших предполагаемых знаниях, а потом сам тест. На него даётся 3 часа (на 50 вопросов), что весьма дофига. Я управился со всем за 2, и при этом много тупил. Т.е. при желании можно уложиться и в час (только надо ли?). К любым вопросам можно всегда возвращаться, можно помечать их для последующего просмотра, можно менять решение. Тут никаких ограничений нет. Это весьма удобно, сложные вопросы можно уже пересмотреть в конце экзамена, когда на всё уже ответил и время не давит.

Сами вопросы обычно предлагают выбрать один правильный из четырёх вариантов. Изредка бывает выбор двух-трех вариантов (всегда пишут нужное количество). Вопросы грамотные и сводятся к вариантам вида где мы пропустили запятую? С другой стороны, иногда раздражает, что бывают вопросы, на которые ты просто не помнишь правильный ответ, но знаешь, что из MSDN ты найдёшь его за минуту (с непрограммерскими экзаменами, ещё хуже, бывают задания, которые в жизни делаешь на автомате, и по пунктам уже объяснить не можешь, ибо спинным мозгом нажимаешь на кнопки, а приходится выбирать правильный вариант).

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

На этот листок вам ставят хитрую печать, после этого вы должны его посмотреть, запомнить и съесть. Ибо данные цифры и шкалы больше нигде и никогда не покажутся, это ваше личное дело, что вы знаете. И даже если набрали 701 балл при допустимых 700, этого вы никому не обязаны говорить. Говорите, что 1000, всё равно не проверят.


Далее, если вы в первый раз сдаёте, то вам через некоторое время придёт MCP ID, для регистрации на mcp.microsoft.com, там вы можете сотворить свои логотипы, получить PDF с сертификатом или заказать его ($10 за один + $1 за каждый последующий в одной посылке), на сертификате будет стоять личная подпись самого Стивена Балмера.  Официальный способ при этом подтвердить статус, это Transcript. Для доступа к нему нужен код доступа, который вы придумываете сами и всегда можете изменить, чтобы прекратить к нему доступ. Так что сертификаты, это в общем-то баловство, но красивое.

Подготовка

Ну и в конце, о том как готовиться. Тут я не помощник. Я почти не готовился, решил что свои-то 700 баллов наберу, и очень пожалел. При сдаче экзамена, сомневался практически в каждом вопросе, было ощущение, что я вообще первый раз вижу этот .NET, и вообще, кто здесь?  

Темы для подготовки есть в описании экзамена, а уж как вы будете готовиться: читать книжки, курить брейндампы, копать MSDN или смотреть доклады, решайте сами. Глубоких знаний не требуется, но требуются достаточно широкие (e.g. 70-562): Microsoft AJAX, Mobile Controls, Declarative Data Sources, Control Lifecycle, Deployment, Configuring, Security. 

Вообще, могу сказать, что на MesureUp вопросы близко к теме, а на BrainBench — вообще не в тему.

воскресенье, 22 ноября 2009 г.

Сжатие ViewState

ViewState — в ASP.NET весьма интересная и полезная технология, но у неё есть один существенный недостаток. ViewState может очень сильно увеличивать размер страницы, и кроме всего прочего все эти данные пойдут на сервер назад, что для пользователей с узким каналом может выливаться в "тормоза" приложения, хотя само-то оно будет быстрым.

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

Собственно, есть ситуация, проект близится к концу, нужно что-то с ViewState'ом делать. Для начала, стоит взять типичную страницу, забрать из неё ViewState (он хранится в hidden-поле __VIEWSTATE), убрать кодирование в base-64 (сам ViewState не должен быть зашифрован, естественно), и посмотреть на него. На данном этапе иногда можно выкинуть некоторые элементы, которые случайно попали туда. Например, в одном проекте часть рендера страницы выводилась через asp:Literal, который по умолчанию пихает всё свое содержимое во ViewState, что, например, для русского текста длинной в 100 байт превратится в 300 байт на клиенте.

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

Вначале, нам необходимо переопределить PageStatePersister, собственно, тот класс, который и отвечает за хранение. В ASP.NET существуют две реализации, которые хранят ViewState в hidden-поле (по умолчанию) или в сессии. Нам нужен свой, который будет сжимать содержимое:


protected override PageStatePersister PageStatePersister
{
    get
    {
        return _persister ?? (_persister = new CompressionPageStatePersister(this));
    }
}

Для этого перекрываем property PageStatePersister у страницы (Page), и возвращаем инстанс нашего класса:


public class CompressionPageStatePersister : PageStatePersister
{
    public CompressionPageStatePersister(Page page) : base(page) { }
    public override void Load()
    {
        string requestViewStateString = base.Page.Request.Form["__CVIEWSTATE"];
        if (!string.IsNullOrEmpty(requestViewStateString))
        {
            Pair pair = (Pair)
                ViewStateCompressor.ViewStateDecompress(
                    Convert.FromBase64String(
                        requestViewStateString));
            base.ViewState = pair.First;
            base.ControlState = pair.Second;
        }
    }

    public override void Save()
    {
        Control control = base.Page.FindControl("__CVIEWSTATE");
        if ((base.ViewState != null) || (base.ControlState != null))
        {
            string s = Convert.ToBase64String(
                ViewStateCompressor.ViewStateCompress(
                    new Pair(base.ViewState, base.ControlState)));
            ScriptManager.RegisterHiddenField(base.Page, "__CVIEWSTATE", s);
        }
    }
}

Как видно, реализация простейшая, перекрываются методы Save и Load, которые сохраняют и загружают ControlState (неотключаемая часть, необходимая для работы контролов) и ViewState. Всё это сохраняается в собственное hidden-поле __CVIEWSTATE, т.к. к обычному у нас нет доступа (но если интересно, то с использованием Reflection, нужно взять private field у класса Page с именем _clientState, и записать значение туда).

Да, и в base-64 кодировать обязательно, ибо особенности стандарта HTTP таковы, что даже если вы попробуете другую кодировку, в реальности будет передано гораздо больше байт.

Ну, и собственно про сжатие, точнее про ViewStateCompressor, это небольшой класс, который сериализует данные и сжимает с помощью GZip:


public static byte[] ViewStateCompress(object viewStateToCompress)
{
    ObjectStateFormatter formatter = new ObjectStateFormatter();
    MemoryStream output0 = new MemoryStream();
    DeflaterOutputStream ds = new DeflaterOutputStream(output0, new Deflater(6, true));
    formatter.Serialize(ds, viewStateToCompress);
    ds.Close();
    return output0.ToArray();
}

public static object ViewStateDecompress(byte[] data)
{
    ObjectStateFormatter formatter = new ObjectStateFormatter();
    InflaterInputStream ds = new InflaterInputStream(new MemoryStream(data), new Inflater(true));
    object value = formatter.Deserialize(ds);
    ds.Close();
    return value;
}

Небольшие пояснения:

  • Для сжатия используется библиотека #zipLib (родная медленнее и хуже жмёт, использовать не стоит)
  • Степень сжатия (6) — это по умолчанию, наилучший компромисс качества и скорости
  • Не пишутся заголовки GZip, так как они нам не нужны, т.е. другими словами использоуется не GZip, а Deflate — алгоритм сжатия без дополнительной информации
  • В качестве сериализатора используется ObjectStateFormatter, который и используется в качестве стандартного (точнее там используется LosFormatter, но итогом работы служит строка в base-64, а мы сами потом трансформируем уже запакованные данные
  • В данном случае мы теряем встроенную возможность шифрования ViewState, но её при необходимости легко реализовать, да и расшифровать ViewState будет уже сложнее

Как видно, всё просто: два класса для удобства и один override, и результат — размер данных на клиенте в 2-5 раз меньше, и не на магистральных каналах страницы начинают работать гораздо быстрее.

Да, и постарайтесь не сохранять во ViewState собственные объекты, ибо ObjectStateFormatter достаточно эффективно сериализует базовые типы, но если он не понял про тип, то начинает использовать недостаточно эффективный, но универсальный BinaryFormatter. Если будет время, я постараюсь расписать, как в некоторых случаях можно подменить сериализацию для своих типов, чтобы уменьшить размер ViewState (который из-за этого может тоже весьма значительно сократиться).

среда, 28 октября 2009 г.

Использование DefaultHttpHandler для отдачи файлов пользователю

Тут на конкурсе задали вопрос: чем отличаются Http Handlers и Http Modules. Ответов полно, дублировать их желания нет.  Всегда можно открыть MSDN и почитать про это.

Вкратце, Handler, это обработчик запроса, например, когда обращаемся на /default.aspx, в web.config ищется подходящий обработчик и ему запрос отдаётся на растерзание. Естественно, если вы поглядите в web.config для вашего приложения, вы там скорее всего такого не найдёте. Но если вспомнить иеархию конфигруационных файлов в .NET, то становится ясно, что нужно искать в базовом web.config файле. У меня он находится тут: C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\CONFIG\web.config.

Этот зверь в 30Кб, полностью описывает стандартные настройки приложения, которые можно заменить в своём. Там как раз и есть обработчик aspx-файлов:

<add path="*.aspx" verb="*" type="System.Web.UI.PageHandlerFactory" validate="true">

Собственно он и говорит рабочему процессу, что все подобные запросы должна обрабатывать фабрика с названием PageHandler (фабрика, это небольшой класс, который позволяет уже самостоятельно выбрать нужный Handler, в зависимости от более тонких условий). Также там можно найти другие интересные строчки:

<add path="*.config" verb="*" type="System.Web.HttpForbiddenHandler" validate="true"/>
...
<add path="*.soap" verb="*" type="System.Runtime.Remoting.Channels.Http.HttpRemotingHandlerFactory, System.Runtime.Remoting, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" validate="false"/>

Например, эти говорят что *.config файлы нельзя показывать (например тот же web.config), а *.soap нужно для Remoting. Естественно, все эти правила можно заменить в своём приложении, да и при этом не забыть, что сам IIS по умолчанию не все расширения отдаёт ASP.NET, и надо добавить соответствующий фильтр в  настройках вашего приложения (ну или глобальный, на все файлы).

Про Http Handler's почему-то не получилось коротко, но это я случайно.   Дальше я расскажу более интересную вещь. А пока немножко про Http Modules.

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


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

Я часто встречал реализацию в виде /getfile.ashx?id=123 — где собственный хендлер как-то пытается отдать файлы. Идея хорошая, но не очень красивая, к тому же приходится рисовать собственный хендлер, отдающий файлы, что как-то неправильно.

Небольшое отсупление, по возможности старайтесь передавать имя файла в запросе, а не через Content-Disposition, иначе будут  проблемы с русскими именами файлов, да и периодические глюки, когда у клиента имя какое-то не такое. Для этого всего-лишь нужно делать запросы вида /getfile.ashx?id=123/requiredFileName немного подправить разбор входящих параметров, а дальше браузер сам придумает как обозвать файл.

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

  • Необходим .NET Framework 3.5 SP1, потому что в предыдущих реализация данного хендлера более примитивная.
  • Файлы должны быть физически доступны из приложения, т.е. пользователь должен иметь теоретическую возможность их скачать (правда имя может быть любое и лежать они могут как хотят. Для запрета прямой скачки, делаем соответствующие правила в web.config)

Теперь, собственно, осталось придумать по какому пути пользователи будут обращаться к файлам и навесить на этот путь свой простенький хендлер, отнаследованный от DefaultHttpHandler. Можете использовать различные url-rewriting решения, или написать своё. Если вам приходится вешаться на aspx файлы, то можете в фабрике возвращать следующий Handler:

PageParser.GetCompiledPageInstance(url, null, context)

Т.е. практически вручную запустить обработку страницы (с некоторым оговорками, но не о них сейчас речь).

Далее, в своём хендлере делаем следующее:

  • В методе BeginRequest  определяем "настоящий" путь к файлу по запросу. Например, запрос, /123/myfile.jpg меняем на /files/storedFile_123.dat
  • вызываем у контекста (вам его передадут) метод: context.RewritePath с полученным путём.
  • Дальше, чтобы не отдавать запрос IIS (а для оптимизации DefaultHttphandler попробует это сделать), что-нибудь пишем в Response, например context.Response.Write(' '). 
  • Вызываем базовый метод BeginRequest

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

  • Записывает в заголовки Content-Location с настоящим именем файла, т.е. хоть и не страшно, но мы светим то, как у нас хранятся файлы, т.е. неаккуратненько как-то
  • Если он не знает расширения файла, то в целях безопасности может его и не отдать (Свойства сервера, типы MIME — тут указаны расширения, которые IIS знает)

Ещё можно обрабатывать ошибки, писать логи и статистику, но это уже тонкости и детали, главное, что достаточно быстро (гораздо быстрее чем читать этот пост ).


Вышесказанное относится к IIS 6.0, в седьмом, возможно всё будет ещё проще, но я с ним мало работал, и в основном в классическом режиме, так что не буду ничего утверждать заранее.

вторник, 27 октября 2009 г.

GAC

Не выдержал и решил написать ответ на вопрос про GAC для конкурса Гайдара про платформу.

Переписывать MSDN и Рихтера не буду, для разнообразия скажу своё мнение про GAC, чтобы ответ отличался от остальных.   Собственно расскажу, не про то, чем хорош GAC, а чем он плох.

Для начала в двух словах про него — это глобальный кеш сборок, и любое приложение, которое использует опредёленную сборку сначала посмотрит на её наличие в GACе, а только потом будет искать в других местах. Т.е. можно считать GAC банальным хранилищем DLLек, как Windows\System32, но с одним важным отличием. Сборки хранятся не по имении библиотеки, а по имени, Strong Name ключу, версии, культуре и платформе (x86, x64). Т.е. можно хранить разные версии сборок и даже умудряться их использовать в одном приложении (хотя лучше постараться не делать так). Т.е. GAC полезная функциональность, но есть несколько НО.

Самое главное, теряется возможность xcopy deployment, необходимо использовать gacutil или делать приличный Installer. Но если подумать, то что нужно класть в GAC? Нужно туда размещать библиотеку, которую будут использовать несколько приложений на компьютере, иначе особого смысла в этом нет. Другими словами, это должен быть конкретный shared-компонент. А кому нужен shared-компонент? Только разработчикам. Для обычных пользователей это в большинстве случаев не нужно. А разработчики очень не любят сложные процессы установки библиотек. Им бы в проект скопировать что надо, и не думать потом о библиотеках. В противном случае получается, что у разработчика может всё работать, ибо сторонняя сборка в GACe, а у клиента уже всё будет падать, ибо разработчик забыл её приложить к приложению.

Например, мой epic fail был с библиотекой Microsoft.mshtml.dll, которая оказалось что ставится со студией, и напрямую в приложении не используется, а используется через третьи библиотеки. В результате, у меня приложение работало на всех компьютерах, а половина клиентов ругалась. Конечно, я уже умный, и подобных вещей стараюсь не допускать, но вот пример как легко можно сломать приложение использованием GACа.

Собственно, если мы планируем использовать сборку в GACе, то у нас сразу усложняется разработка. Необходимо писать скрипты для билда, которые будут выковыривать сборку из GAC, компилировать новую версию и вставлять обратно. Вроде не сложно, но программисты ленивые, и обязательно что-нибудь схалтурят, и при деплое получим проблемы.  Ещё нужно обязательно использовать Strong Name, что на этапе разработки иногда плохо, ибо придётся раздавать ключ всем разработчикам (проблема в секурности), также сразу включается версионирование, которое менять нужно вручную. Иначе получатся две абсолютно разных сборки с версией 1.0.0.0, одна из которых в GAC, а вторая нужна приложению, и это вызовет замечательные проблемы, которые будет очень весело отлаживать.


Собственно, что я хотел сказать:

  • Использовать GAC нужно, когда есть проблемы с версионированием. Это позволит их решить. Например, приложение А использует библиотеки B и С. B использует библиотеку D версии 1.0.0.0, а C использует D версии 1.2.0.0. Как это это необходимо решать. Тут нужен GAC, ибо два файла с одним именем к приложению подцеплять плохо.
  • Использовать GAC нужно, когда есть много приложений, использующих одну сборку. Как вариант — хостинг многих приложений с общим компонентом. И то, может быть проще не использовать GAC, ибо места на диске не так уж и много сэкономится, а если случайно выкинут сборку из GAC, то можно получить проблемы.
  • Хороший пример того, что нужно класть в GAC — системные библиотеки .NET Framework
  • Во всех остальных случаях — не стоит. (Моё личное мнение).

.NET Remoting по протоколу SOAP. Возможно ли?

Тут @gaidar устроил конкурс и задаёт всякие разные вопросы.  В принципе, отвечать на них не планировал, ибо умные ответы писать долго и получится переписывание книжек/MSDN, а глупые можно и в Твиттере

Но, тут задали вопрос про Remoting, а это же моя любимая тема.

Собственно, Remoting может использовать любой канал, хоть голубиную почту, с сообщениями, закодированными морзянкой, этим он и отличается в лучшую сторону, но вопрос именно в том, что можно ли из подобного SOAP/Remoting сделать настоящий Web Service? Ответ сложный, с одной стороны — да, ибо можно использовать SOAP, с другой стороны, эти сообещия будут весьма страшными и заточенными под remoting-клиента, а не обычного Web-Service клиента. Собственно, проблема в том, что для веб-сервисов нужны  WSDL и XSD описания методов, а Remoting хоть и делает WSDL, но делает его для себя, и особо не смотрит на стандартные неймспейсы и типы.

Так что ответ: В принципе да. Но если вы хотите, чтобы клиентами были не только те же .NET приложения, то вам же придётся приложить множество усилий, чтобы использовать только базовые типы, не использовать CAO и эвенты, т.е. сильно урезать функционал Remoting, чтобы свести его к веб-сервисам. А оно вам надо? Гораздо проще тупо и использовать веб-сервисы для тех целей, когда они нужны, это проще и понятнее, а Remoting не использовать вовсе, не нравится он мне. 

четверг, 3 сентября 2009 г.

Немножко про Reflection

Недавно проверял скорость работы Reflection в плане того, насколько оно медленное. Расписывать все случаи не буду, также не буду утверждать что все замеры корректные, просто немного данных для информации, чтобы вы знали, что ожидать от Reflection:

  • Вызов метода через рефлекшен отличается в зависимости от того, является ли метод public или private
  • Для public вызов метода где-то в 100-150 (!) раз медленнее, чем обычный вызов
  • Для private вызов медленнее где-то раз в 400-500 (!). Выводы делайте сами.
  • Время на вызовы GetMethodInfo относительно невелико, при этом, похоже это всё кешируется. Так что особо оптимизировать вызовы тут смысла нет
  • Если вы точно знаете сигнатуру метода, который берёте через рефлекшен (в качестве варианта, пнуть какой-нибудь приватный метод, или при использовании какого-либо варианта плагинов), то можно воспользоваться Delegate.CreateDelegate с указанием нужного типа, получить правильный делегат и его вызов будет таким же быстрым (возможно даже чуть быстрее, есть подозрение на использование call вместо callvirt), как и прямой вызов
  • Если точно не знаете сигнатуру, то можно использовать Delegate.DynamicInvoke но производительность будет примерно такая же, как и у чистого рефлекшена
  • Если хотите использовать Expression для генерации, в частности LambdaExpression то совет тот же. Используйте чётко типизированный .Compile() и получите почти идеальную производительность (где-то 1.5, но компиляция не очень шустрая). С учётом того, что экспрешены — достаточно могучий механизм, подобное стоит использовать. Есть интересные задачи, где они могут сильно облегчить жизнь, или даже сделать что-то особенное.

Ну вот, в общем и всё. Пока для меня остаётся открытым вопрос: "Как использовать преимущества делегатов без возможности указания нужного типа напрямую", чтобы получить хорошую производительность для рефлешкена. Смотрю в сторону DynamicMethod, но это уж больно серьёзная артиллерия (хотя производительность замечательная).