Имитируйте жизненный цикл страницы, чтобы получить HTML-код из слоя пользовательского интерфейса.

Asked
Viewd467

4

Я работаю с довольно большим веб-приложением .net.

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

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

Меня больше всего беспокоит этот метод, так как при просмотре пользовательского интерфейса мне приходится беспокоиться о тайм-аутах. В то время как фоновые потоки и тому подобное могут длиться столько, сколько они хотят, страницы aspx существуют только до тех пор, пока они не будут завершены.

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

Другая идея - создать объект страницы и заполнить его вручную в коде, вручную вызвать соответствующие методы, а затем извлечь из него данные. Проблема с этим методом, помимо того, что я не знаю, как это сделать, состоит в том, что я боюсь, что могу забыть вызвать метод, или что-то может работать неправильно, потому что на самом деле он не связан с реальным сеансом или веб-сервером.

Как лучше всего имитировать пользовательский интерфейс страницы в фоновом потоке?

  • @RickNZ: Это не в моем списке из-за уровня требуемых усилий, но если вы можете подумать о способе решения проблемы тайм-аута, которую вызовет веб-запрос, и проблема цикла, создающая страницу в фоновом потоке,потому что я весь уши.

    diadem23 ноября 2009, 14:16

2 ответов

6

Я знаю 3 возможных решения:

IHttpHandler

На этот вопрос есть полный ответ. Обычно вы записываете вывод Response.Filter, реализуя собственный читаемый поток и настраиваемый IHttpHandler.

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

WebClient

Единственная альтернатива, которую я вижу для этого с ASP.NET, - это использовать блокировку WebClient для запроса страницы, генерирующей HTML. Возьмите этот результат и затем превратите его в PDF. Прежде чем делать все это, вы, очевидно, можете проверить свой кеш, чтобы увидеть, там ли он уже.

 WebClient client = new WebClient();
string result = client.DownloadString("http://localhost/yoursite");
 

WatiN (или другие пакеты автоматизации браузера)

Еще одно возможное решение - WatiN , который обеспечивает большую гибкость при захвате HTML-кода браузера. Неудача в том, что ему нужно взаимодействовать с рабочим столом. Вот их пример:

 using (IE ie = new IE("http://www.google.com"))
{
    ie.TextField(Find.ByName("q")).TypeText("WatiN");
    ie.Button(Find.ByName("btnG")).Click();

    Assert.IsTrue(ie.ContainsText("WatiN"));
}
 
  • Спасибо.Webrequest - это решение, которым я изначально пользовался.Он безупречно работает на локальном компьютере.

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

    diadem23 ноября 2009, 14:19
3

Если «лучший способ получить точный снимок - это действительно сделать снимок пользовательского интерфейса» действительно верно, то вам необходимо провести рефакторинг вашего кода.

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

Затем, когда пришло время создавать PDF-файлы, у вас есть только одно место для вызова и никаких проблем с хакерским перехватом пользовательского интерфейса / несколькими потоками, с которыми нужно иметь дело.

  • +1, хотя в настоящее время это может быть невозможным решением, по крайней мере, над этим нужно работать.

    Jon Seigel17 ноября 2009, 15:54
  • Я до сих пор не понимаю, как создать модель представления, которая заменит необходимость в настраиваемом коде на страницах ascx - я имею в виду, скажем, я изменил таблицу стилей?Как я могу добавить этот каскад к каждому PDF-файлу?А как насчет повторителей ascx и т.п.?А как насчет javascript, который управляет DOM?

    diadem17 ноября 2009, 19:27
  • Хм ... Возможно, вам стоит подумать об адаптации шаблона "Модель-Представление-Модель представления".По сути, добавьте еще один уровень (ViewModel) для своей «пользовательской логики пользовательского интерфейса» и поместите туда эти решения.Затем свяжите свои средства визуализации ASPX и PDF с этой моделью и логикой.

    Randolpho17 ноября 2009, 16:57
  • Вы собираетесь приложить титанические усилия, сканируя PDF-файл, потому что вашим разработчикам недостает необходимой дисциплины?Я сочувствую тебе;это не идеальная ситуация.

    Randolpho17 ноября 2009, 16:54
  • Мы прошли эту итерацию впервые.Это превратилось в кошмар обслуживания.В конце концов, кто-то создаст особую логику в пользовательском интерфейсе, даже такую простую вещь, как «если элемент из Франции, покажите таблицу по-другому, закрасьте эту ячейку зеленым цветом, измените написание здесь», это не отразится на экспортепотому что выходы ascx и pdf должны совпадать, и в конечном итоге все выйдет из строя.Это особенно касается людей, которые просто хотят отредактировать страницу ascx и даже не думают об экспорте, потому что это не их работа.

    diadem17 ноября 2009, 16:29