Pull to refresh

Comments 42

Как-то такой подход совсем выбивается из моего представления о задаче. Могу сделать следующие замечания/дополнения:
1) Бросается в глаза ваша функция GetImgFormat. Почему сразу не передавать ImageFormat? Для чего нужен промежуточный ещё какой-то формат. Конвертить из одного перечисления в другое как-то громоздко смотрится.

2) Формирование изображения я бы перенес в сам Handler, а в сессии где-нить сохранял текст, который нужно нарисовать на капче.

3) В принципе передавать от одного контрола к другому такие данные, как картинка - я бы не стал. Что-то бы придумал аналогичное пункту 2.

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

Наверное, ещё что-то можно написать, но это основное, что пришло в голову.
1.ImageFormat - это не перечисление. Оно к тому же содержит определение типов изображений, которые не могут быть записаны в поток контекста страницы. Обозначив свое перечисление я определил только те типы изображений, которые действительно имеет смысл использовать при формировании динамических изображений.
2. Дело в том, что хэндлер ничего не должен знать об изображении. Его работа вывести Bitmap на страницу. Что там на битмапе капча ли или круговая диаграмма, а может быть и просто фото товара - это ему все равно.
3. Контролы не передают данные, страница только передает в контрол необходимый битмап и на этом этапе программист должен быть уверен, что ничего больше делать не нужно.
4. Передача хендлеру битмапа выглядит как-то более в контексте ООП, как мне кажется. Тем более, у битмап есть поддержка записи в MemoryStream. Но, как я уже написал выше использование Cache и вообще весь этот момент имеет смысл оптимизировать, так что с вашим вариантом я в чем то согласен.
Да, спать хотелось вчера, по некоторым вещам просто не доглядел. Так что извини, ничего личного и просто покритиковать целью не ставил :)

Если выполнять конкретно вашу задачу (просто вывести клиенту какой-то битмап), чтобы было все очень универсально, то никаких вопросов. В остальных же случаях я предпочел бы все же вынести логику рисования в сам Handler.

Касательно Cache, чем он вам тут не нравится? :) Вроде вполне нормально под нужды подходит.
Понятно :)
Способ с Cache кушает память. Если использовать мой контрол для генерации графиков на сильнозагруженном сайте, то могут быть проблемы с производительностью. Я первоначально вообще передавал через объявленный делегат указатель на методы, которые возвращают Bitmap. Правда не до конца уверен, что такой метод кушает меньше памяти.
Проблема с памятью у вас только из-за того, что вы его не хотите генерить картинку в Handler. Где бы вы ни хранили этот Bitmap - он все равно будет занимать место.

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

По поводу того, что один хэндлер - меньше кода.. Не знаю. Для того, чтобы вывести картинку, элемента в каталоге из БД, например, вам прийдется использоваться свой контрол для этого. А если с отдельными кодами, то можно вообще только HTML разметкой обойтись, даже не используя asp:Image. Так что с повторным кодом тут ещё вопрос.
Да понимаю. У меня именно по этому был вариант с передачей хендлеру не Bitmap, а указателя на метод-генератор Bitmap. Как вы такой метод оцените?
Еще суть моего метода в том, что Bitmap может быть уже готов и храниться где угодно, например в БД. Bitmap может получаться и из многих других источников. Все равно вывод будет одним. С вашим же подходом придется писать каждый раз новый хендлер. Мало того, программист в разметке все время будет этот хендлер использовать, то есть он для него не будет скрыт.
Хочу пояснить, что я полностью согласен с вашей позицией, просто привожу свои аргументы в защиту моего метода. Считаю, что следует рассматривать несколько вариантов, а не признавать один лучшим, а другой худшим.
Не знаю. Указатели на метод это уж совсем может кого-то запутать. Я в общем-то как-то смотрел несколько больших движков форумов или CMS, точно не помню. В общем-то там не стеснялись делать хэндлеры, для чего только нужно :)

Для вывода из базы данных такой способ точно не подходит, так как при обновлении страницы будет генериться картинка с новым Guid. Никакого кеширования тут не получится сделать. Или передавать не просто прийдется, а идентификатор картинки в БД.

По поводу лучше не лучше. Я думаю, что может возникнуть ситуация, когда понадобится именно ваш подход. Поэтому тут никаких вопросов :)
Сразу же оговорюсь, что занимаюсь корпоративными Web-разработками на .net. Соответственно, для нашей компании важным является стабильность, производительность и хорошая поддерживаемость кода. Если болеет сотрудник, который разработал контрол, то его вполне может доработать любой другой. Я это к тому, что буду комментировать с этой точки зрения.
1. По-моему, стоит все-таки пользоваться классом ImageFormat, несмотря на Ваше возражение. Лишний класс лишь вносит путаницу в код, который позже придется поддерживать.
2 и 3. Из моего опыта могу сказать, что этот механизм, который Вы предложили в данном примере, не лучший. Удобнее все-таки делать несколько Handler-ов. Один отвечает за фотографии, которые тянет из БД (к примеру), второй за капчи, которые генерятся, третий - за круговые диаграммы, данные для которых тоже берутся из БД.
Все это довольно различающиеся механизмы, которые, если их обобщить, вносят опять же путаницу.
4. Интересно, зачем использовать MemoryStream, если можно
Bitmap bitmap = ...
bitmap.Save(Response.OutputStream, ImageFormat.Gif);
5. Пора вводить Code Conventions для .NET блога :)
Спасибо за развернутый комментарий. Ниже попробую ответить на часть вопросов:
1. Использовать этот класс не так-то просто, хотя бы потому что передать его значение через строку запроса невозможно, в отличии от моего перечисления, котрое просто конвертится в числовое значение.
2,3. Несколько хендлеров - это несколько одинаковых строк кода. Ничего не могу сказать про вашу ситуацию, скорее всего это оправдано, но сам я придерживаюсь того мнения, что код должен быть оптимизирован к повторному использованию. С другой стороны, ваш вариант тоже имеет право на жизнь, считаю, что все зависит от ситуации. Впрочем, цель у статьи была несколько другая :)
4. Попробуйте сделать bitmap.Save(Response.OutputStream, ImageFormat.Png) (именно Png) уверен вас ждет открытие ;)
5. Что такое Code Conventions?
1. Возможно. ImageFormat.Png.Guid
2,3. Создается базовый класс(что-то вроде ImageHandlerBase), в трех обработчиках лишь перегружается один-два метода.
4. Спасибо, действительно не знал про это :)
5. Договоренность об оформлении кода. Я думаю, если протестовать никто не будет, то можно вместе договориться о том, в каком виде отображать код. Подсветка, названия переменных, и прочее.

Не всем надо, но многие, смотря на хороший красивый код, будут немного приучаться :)
В именах переменных, думаю, будет сложно всем придти к общему стилю.
Вот у вас, например, везде имена локальных переменных кроме метода GetRandomPassword начинаются с подчеркивания. С чем это связано?
А насчет подсветки вряд ли будут расхождения. После форматирования стало гораздо приятнее читаться.
Подчеркивание локальных переменных - это наследство моего прошлого. В принципе, подчеркивание служит для того, чтобы отделить глобальные переменные, поля и свойства от локальных, объявленных в теле метода. Сейчас же, это для меня просто привычка от которой трудно избавится.
Я делаю с точностью до наоборот. Все приватный поля называю с подчеркивания. :)
Неплохой, к стати, сайт с описанием стандартов и откуда они пошли.
О! Отличный сайтик, спасибо...
Кстати, может быть сделать на основе каких-нибудь правил свои собственные Хабраправила кода С#? Организоваться группой заинтересованных и создать документ-рекомендацию? Есть желание? Потом этот документ предложить для оценки другим группам к примеру на gotdotnet...
Мне удобнее к глобальным обращаться через this. читается быстрее за счет того, что this ключевое слово.
Я думаю, что достаточно использовать правила MS для .NET . Если есть желание все это оформить, то могу заняться.
На готдотнете вроде бы есть уже. На RSDN точно. Там впервые прочитал, теперь пользуюемся на работе стандартными MS с дополнениями и улучшениями.
1. Guid передадите, потом надо приводить опять к Png. Морока. Опять же надо проверять не передаются ли какие-то другие неразрешенные типы, вроде Exif. Вот у вам и будет еще одна функция наподобие моей. Ваш подход понятен, но для меня пока не очевидны плюсы.
2,3. Ясно. Думаю, в вашем контексте это действительно лучшее решение.
5. Подсветка есть уже. Я так понял вы говорите еще и про оформление кода, типа переменные с маленькой буквы, свойства с большой...? Есть на эту тему пару документов, читал. Но сам я все никак не могу побороть свои привычки и писать на каком-то предложенном варианте... Увы.
1. public ImageFormat(Guid guid)
2. Если будет в коде метод
bool IsImageFormatAllowed(ImageFormat imageFormat)
{
 return (imageFormat == ImageFormat.Gif)||(imageFormat == ImageFormat.Jpeg)
}

* This source code was highlighted with Source Code Highlighter.

то код будет более читаемым, нежели с использованием DynamicImageFormat.

Извините за оффтоп, но у меня почему-то не получается вставить ни одной ссылки в комментарий.
1. Это вы на конструктор намекаете? Попробуйте, потом расскажите что получится. У меня результатом был новый экземпляр, отличный от Png.
2. Просто, представте себе концепцию, в которой заранее определены доступные типы изображений. В вашем случае как узнать программисту, что Exif использовать нельзя? Только через первый exception?
3. Я уже готов с вами согласится :). Столько упорства, благодарю за беседу.
1. Попробовал. Вы тоже молодец, что попробовали. :)
== Не работает, однако отлично работает Equals. Не надо так быстро сдаваться, проблемы лучше решать :)
2. Представил. Вы делаете UI, ваш коллега - обработчик. Есть общая спецификация(документация), там указано, что и как и почему
3. Мне тоже очень приятно беседовать с небезразличными.
На самом деле не хочу убеждать никого, в споре нет победивших. Тем более, лучше, когда есть много точек зрения. Лишь конструктивно критикую :)
Это карма пока ещё маленькая :) Как вырастет больше скольки-то — появится такая возможность.
Поддерживаю идею Code Conventions. Хоть материала на эту тему уже много, да и каждый все равно может немного отступать от него. Но все же лучше писать в едином стиле. Мне нравится, как написано большинство примеров MSDN.
Полностью за стиль MSDN.
UFO just landed and posted this here
UFO just landed and posted this here
>> img.ImageUrl = String.Format("DynamicImageHandler.ashx?bitmap={0}&format={1}", _bitmapGuid, (int)DynamicImageFormat);

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

Это к какой-то задаче писалось? А то непонятно, зачем передавать в контрол картинку и потом кэшировать её, почему нельзя получать картинку в самом обработчике?
Насчет второго погорячился, не увидел последний пример с пассвордом.
Про путь - это вы удачно заметили, спасибо. Конечно, путь к хэндлеру должен быть таким какой определяет структура проекта или сайта.
От этой проблемы можно избавиться. Для этого нужно код обработчика скомпилировать в сборку и прописать сопоставление адреса (скажем, image.axd) в web.config. Тогда обработчик будет вызываться в любом подкаталоге приложения.
Кстати, проблему динамической генерации изображений рассматривал Дино Эспозито в апрельском номере MSDN Magazine за 2004 год. Вот тут http://msdn.microsoft.com/en-us/magazine/cc163988.aspx можно прочитать эту статью.
Я в недоумении. Раньше с удовольствие пользовался. Теперь немогу и вот почему: во-первых, перестало работать форматирование табуляции C# кода, во-вторых, код подсвечивается очень избыточно, в тэги font оборачивается едва ли не каждый символ... Такой вот багрепорт. Собирался об этом написать, но пока не собрался.
Привет!
Я починил этот баг.
Проверь пожалуйста.
Отлично!
Отформатировал всю статью.
еще было бы хорошо указывать с на каком .net сделано. у меня стоит 2.0, тут 3.5
Вы это, по-моему, в комментариях к каждой статье в блоге .NET пишете :) Если спутал с кем-то другим, то извините.

А что в этой статье используется из фич 3.5? Компилировать не пробовал примеры, но, на первый взгляд, должно без проблем работать в 2.0.
попутали, я первый раз в этом блоге прокомментировал.
вообще, я конечно не проверял зависимости, просто охото скачать-открыть-заценить без лишних телодвижений.
Просто я если пишу в 2008 студии, то сам проект вы не откроете, хоть я даже полностью буду писать под 2.0.
Попробуйте или добавить в пустой проект файлы из приведенного сорса, или уж ручками как-то копипастом.

Мне кажется, неправильно будет писать, что проект под 3.5 только потому, что он создан в 2008 студии.
Написал такой большой коммент с кусками кода, канул в небытие. Значит не судьба.
Что там хоть было? В двух словах?
Мое решение.



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

Выход: всегда копировать в буфер, если писали что-то большое. Если не опубликовалось, то обновить страницу и запостить заново. Обидно, что хорошие мысли уходят в небытие в просторах интернета :)
Sign up to leave a comment.

Articles