• Microsoft .NET
  • ASP.NET
  • Отображение случайно выбранного изображения на веб-странице ASP.NET

Отображение случайно выбранного изображения на веб-странице ASP.NET

ОГЛАВЛЕНИЕ

Как разработчикам веб-приложений, нам приходится тратить много усилий на определение и реализацию бизнес-логики, создание CRUD (англ. create read update delete) и разработку отчетов. Гораздо реже мы  переживаем за обслуживание относительно стиля и внешнего вида веб-сайта. Для разработчиков, работающих в средних и больших компаниях, это не представляет никакой проблемы, так как в компаниях, скорее всего, есть художники-оформители, чьей работой является создание блестящей верстки сайта и периодическое обновление ее, чтобы сайт был всегда свежим. В мелких компаниях разработчики веб-приложений, пишущие код к нему, нередко также ответственны за поддержание внешнего интерфейса. Одним из наиболее  легких и недорогих  способов поддержания свежести сайта является отображение различных изображений при каждом визите на страницу. Многие корпоративные веб-сайты используют данную технику на своих страницах. К примеру, страница может иметь изображение помещения с сотрудниками в правом верхнем углу. Вместо того чтобы показывать одно и то же статическое изображение, при каждом посещении страницы в углу отображается наугад выбранное изображение.

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


Показываем изображение, случайно выбранное из каталога

Простейшим способом отображения произвольного изображения будет: добавление элемента управления Image на вашу страницу (либо мастер-страницу (Master Page)), написание небольшого кода, который получит все изображения из файлов определенного каталога, используя класс Random для случайного отбора изображения из списка, а также назначения пути к данному случайно выбранному изображению свойства ImageUrl элемента управления Image. Это все можно уместить в 10 строках кода.

Чтобы продемонстрировать  технические способы, рассматриваемые в данной статье, я создал простое демо-приложение в ASP.NET 2.0, которое вы можете загрузить в конце данной статьи. Это приложение включает в себя мастер-страницу, названную ImagesFromDirectory.master, которая определяет страницу шириной в 800 пикселей. В верхних 250 пикселях вы увидите элемент управления ASP.NET Image, названный HeaderImage, который отображает наугад выбранное изображение. Каталог ~/Images/HeaderImages/ содержит пять изображений, которые будут откалиброваны под размер в 800x250 пикселей. Метод PickImageFromDirectory(directoryPath), показанный ниже, возвращает путь к наугад выбранному изображению. Данный метод вызывается из обработчика события мастер-страницы Page_Load, где возвращенное значение назначается свойству ImageUrl элемента управления Image.

Protected Sub Page_Load(ByVal sender As  Object, ByVal e As System.EventArgs) Handles Me.Load
   If Not Page.IsPostBack Then
      'Програмно выбираем случайное изображение из каталога ~/Images
      HeaderImage.ImageUrl = PickImageFromDirectory("~/Images/HeaderImages")
   End If
End Sub


'Возвращаем путь к выбранному изображению
Private Function PickImageFromDirectory(ByVal directoryPath As String) As String
   Dim dirInfo As New DirectoryInfo(Server.MapPath(directoryPath))
   Dim fileList() As FileInfo = dirInfo.GetFiles()
   Dim numberOfFiles As Integer = fileList.Length

   'Выбираем случайное изображение из списка
   Dim rnd As New Random
   Dim randomFileIndex As Integer = rnd.Next(numberOfFiles)

   Dim imageFileName As String = fileList(randomFileIndex).Name
   Dim fullImageFileName As String = Path.Combine(directoryPath, imageFileName)

   Return fullImageFileName
End Function

Код начинается с использования класса DirectoryInfo для получения списка всех файлов в указанном пути directoryPath (в данном случае ~/Images/HeaderImages). Для получения всех файлов из директории используется метод GetFiles(). (Вызов GetFiles() без каких-либо входных параметров возвращает все файлы в указанном каталоге, но вы можете вернуть только ряд файлов путем указания их в виде dirInfo.GetFiles("*.jpg").)

Метод GetFiles() возвращает массив объектов FileInfo. Чтобы выбрать произвольно  один из них, нам просто нужно выбрать наугад индекс из данного массива. Это достижимо путем создания экземпляра класса Random и вызова его метода Next(upperBound) для получения случайного числа, меньшего, чем upperBound. Теперь мы можем определить название выбранного файла для конкатенации его с имеющимся путем directoryPath.

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


А вот что было отображено после того, как я обновил страницу.



Показ случайного изображения при помощи элемента управления ContentRotator

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

На сайте MSDN компании Microsoft существует статья, которая демонстрирует бесплатный общедоступный элемент управления ContentRotator. Данный элемент легок в использовании: просто укажите, какие изображения должны быть отображены элементом упрвления. Данные изображения можно указать посредством XML-файла, программно добавленного в элемент управления, либо физически, при помощи декларативного синтаксиса элемента. Каждый элемент с содержимым может опционально  обладать весовым фактором, который указывает вероятность его отображения на странице относительно других изображений.

Если ваша информация изображения находится в базе данных, вы можете программно добавить набор изображений в коллекцию Items элемента управления ContentRotator . Поскольку в моем демо-приложении не используется база данных, мы вложим информацию в XML-файл:

<?xml version="1.0" encoding="utf-8"  ?> 
<contents>
  <content impressions="16">
    &lt;img src="Images/HeaderImages/1000IslandLake.jpg" border="0" alt="1,000 Island Lake" width="100%" height="100%" /&gt;
  </content>
  <content>
    &lt;img src="Images/HeaderImages/HalfDome.jpg" border="0" alt="Half Dome" width="100%" height="100%" /&gt;
  </content>
  <content impressions="4">
    &lt;img src="Images/HeaderImages/HumphreyMountain.jpg" border="0" alt="Mt. Humphrey" width="100%" height="100%" /&gt;
  </content>
  <content impressions="2">
    &lt;img src="Images/HeaderImages/MarieLake.jpg" border="0" alt="Marie Lake" width="100%" height="100%" /&gt;
  </content>
  <content impressions="1">
    &lt;img src="Images/HeaderImages/PiuteCreek.jpg" border="0" alt="Piute Creek" width="100%" height="100%" /&gt;
  </content>
</contents>

Во-первых, учтите структуру XML-кода: корневой элемент назван <contents> и каждый потомок назван <content>. Каждый <content> может включать в себя атрибут impressions, который означает "вес" изображения. Если не указано значение impressions (как в случае со вторым элементом <content>), тогда используется значение 1. Разметка, расположенная между тегами <content>, является содержимым, которое будет обработано относительно выбранного элемента. Поскольку это XML-файл , весь текст в пределах <content> должен быть избегнут. Вот почему символы < and > для элемента img были заменены на &lt; и &gt;, соответственно.

Алгоритм определял, какое изображение необходимо было отобразить в соответствии с указанной вероятностью. Статья "Создание серверного элемента управления ContentRotator в ASP.NET" описывает данный алгоритм следующим образом:

"Алгоритм используется для отображения наугад выбранного изображения в зависимости от вероятности, установленной для него и оформленной в виде линии. Длина вероятности каждого изображения является частью длины общей линии, то есть сумма всех вероятностей будет равна длине линии. Далее, выбирается наугад  любое число, которое должно быть меньше, чем значение длины линии и соответственно выбранному значению будет отображено то изображение, чья линия вероятности содержит данное значение. [Следующее изображение демонстрирует алгоритм в графической форме]".


Поскольку одно изображение обладает значением вероятности, равным сумме всех других значений вероятности, то оно будет отображено в два раза чаще.

Чтобы завершить реализацию данного подхода, все что нам необходимо - это добавить элемент управления ContentRotator на ASP.NET-страницу либо мастер-страницу (Master Page), где мы хотели бы отобразить наугад выбранное изображение , а также установить свойство ContentFile в значении пути к XML-файлу. В демо-приложении, доступном в конце данной статьи, я создал мастер-страницу (ImagesFromContentRotator.master), использующую ту же самую верстку, что  и ImagesFromDirectory.master. Вместо использования элемента управления Image, я добавил элемент ContentRotator в секцию заголовка. Для того чтобы использовать элемент ContentRotator в вашем приложении, вы должны совершить следующие шаги:

  1. Добавьте файл skmContentRotator.dll в директорию вашего приложения либо в директориию Bin .
  2. В самом верху ASP.NET-страницы или мастер-страницы где вы хотели бы использовать элемент ContentRotator, добавьте следующую директиву @Register: <%@ Register TagPrefix="skm" Namespace="skmContentRotator" Assembly="skmContentRotator" %>.
  3. Добавьте элемент ContentRotator на страницу путем включения следующей разметки: <skm:ContentRotator id="ContentRotator1" runat="server" />.

В качестве альтернативы вы можете обойти шаги 2 и 3 путем добавления элемента ContentRotator в Toolbox, затем просто  переместив его из Toolbox в вашу веб-страницу либо мастер-страницу.

Результат обработки ImagesFromContentRotator.master будет идентичен результату, полученному на ImagesFromDirectory.master за исключением того, что ContentRotator будет выводить изображения согласно вероятности, указанной для каждого из них.


Делаем путь к изображению абсолютным

Одним из недостатков такого использования разметки является то, что атрибут src элемента img является относительным. То есть он не начинается с / , так что путь к изображению является относительным по отношению к пути  текущей ASP.NET-странице. К примеру, в XML-файле с содержимым один путь к изображению установлен в "Images/HeaderImages/1000IslandLake.jpg". Если ASP.NET-страница, использующая данную мастер-страницу, находится в корневом каталоге приложения, то все будет работать отлично. Но что произойдет, если позже мы создадим подкаталог, названный, к примеру, /sales, и затем мы добавим в него ASP.NET-страницу, использующую мастер-страницу ImagesFromContentRotator.master? Если она решит отобразить то же самое изображение озер, оно будет искать его в файле /sales/Images/HeaderImages/1000IslandLake.jpg, который не существует!

Если мы используем серверный элемент управления Image, то мы можем использовать символ ~ в свойстве ImageUrl следующим образом: "~/Image/HeaderImages/1000Islandlake.jpg". Во время выполнения символ ~ будет автоматически заменен на соответствующее значение пути к корневому каталогу. Элемент управления ContentRotator порождает статический результат, но вызывает событие после того, как оно выберет изображения для вывода. Мы можем создать обработчик для этого события и корректно настроить путь к изображению. Для того чтобы выполнить это, начните с обновления пути к каждому изображению в атрибуте src, чтобы они начинались "~/". К примеру, измените путь к изображению с "Images/HeaderImages/1000IslandLake.jpg" на "~/Images/HeaderImages/1000IslandLake.jpg". Символ ~ был выбран для того, чтобы синтаксис имитировал то, что в элементе управления Image. Вы могли бы использовать какой-нибудь символ, который не был использован в разметке (например $.)

Далее, создайте обработчик для события ContentCreated элемента ContentRotator класса code-behind мастер-страницы. В данном обработчике мы просто заменим все экземпляры символа ~ с путем к веб-приложению (доступным в Request.ApplicationPath):

Protected Sub ContentRotator1_ContentCreated(ByVal sender As Object, ByVal e As skmContentRotator.ContentCreatedEventArgs) Handles ContentRotator1.ContentCreated
   'Устанавливаем пути к изображениям
   e.ContentItem.Content = e.ContentItem.Content.Replace("~", Request.ApplicationPath)
End Sub

В дополнение к событию ContentCreated, элемент управления ContentRotator может также выводить динамическое содержимое при помощи пользовательских элементов управления (User Controls).

Scott Mitchell

Исходный код примеров