суббота, ноября 28, 2009

Баг в MS Reporting

Не уверен, что это фича, потому как это больше похоже на баг. Если в MS отчёте назначить правило скрытия таблицы, то отчёт в просмотрщике не будет разбиваться на страницы - то есть Interactive height действовать не будет. Вроде бы, казалось, ничего страшного, но в случае построения отчёта по очень большому количеству данных, которые должны были отрендериться в большое количество страниц, рендерится огромнейший HTML, который отображается на клиенте очень долго и потом почти так же долго окно с отчётом закрывается. В нашем случае отчёт строился по ~1 000 000 записей, отображение HTML в IE занимало 10 минут.После того, как правило скрытия таблицы было убрано - отчёт разбился на странице и отобразился через несколько секунд.

вторник, ноября 24, 2009

Адвансированный экспорт

Заказчик проекта, который мы завершаем, вдруг захотел адвансированную функциональность, чтобы майкрософтовские отчёты, который открываются из ASP.NET приложения, экспортировались не так, как они выглядят на предварительном просмотре, а по-другому. Ломая голову над тем, как же это реализовать, в поле зрения попало несколько вариантов. Один из них - реализовать дополнительный Rendering Extension, про что сам Microsoft говорит, что лучше этого всячески избегать. Вариант был немного частично опробован и исключён из рассмотрения. Варианты с добавлением кнопок на пользовательский интерфейс были отметены сразу же, потому что внешний вид утверждён и дополнительную кнопку поверх Report Viewer лепить нельзя.
Через некоторое время мук творчества был разработан вот такой вариант решения:
1) на базе существующего отчёта, экспорт которого надо изменить, создаётся дополнительный отчёт, внешний вид которого соответвует тому виду, который заказчик хочет при экспорте;

2) на страницу, где расположен ReportViewer, добавляем
<iframe id="reportDownloader" src="../blank.html" width="10" height="10" style="display:none;"></iframe>

3) следующий javascript поможет нам перехватить вызов экспорта на клиенте

function HandleClientSideExportAlt()
{
  var formatDropDown = GetControl(this.m_formatsID);
  if (formatDropDown.selectedIndex == 0) return false;
  var selectedFormat = formatDropDown.value;
  var fullExportUrl = "/AdvancedExport.aspx?exportFormat=" + escape(selectedFormat);
  document.getElementById('reportDownloader').src = fullExportUrl;
  formatDropDown.selectedIndex = 0;
  this.m_exportController.SetViewerLinkActive(false);
  return true;
}

RSToolbar.prototype.HandleClientSideExport = HandleClientSideExportAlt;

4)в коде страничке AdvancedExport.aspx в теле метода Page_Load реализуем экспорт серверного отчёта:

String ExportFormat = String.IsNullOrEmpty(Request["exportFormat"]) ? "EXCEL" : Request["exportFormat"].ToUpper();

String exportFileName = String.Format("Report{0}.{1}",
DateTime.Now.ToString("ddMMyyhhmmss"),
ExportFormat.Contains("EXCEL") ? "xls" : "pdf");

using (ReportViewer rv = new ReportViewer())
{
  ServerReport serverReport = rv.ServerReport;

  serverReport.ReportServerUrl = ...
  serverReport.ReportPath = ... <- имя нового экспортируемого отчёта
  serverReport.SetParameters(...);

  Warning[] warnings;
  string[] streamids;
  string mimeType;
  string encoding;
  string extension;

  byte[] bytes = serverReport.Render(ExportFormat, null, out mimeType, out encoding, out extension, out streamids, out warnings);
  Response.Clear();
  Response.ContentType = mimeType;
  Response.AddHeader("content-length", bytes.Length.ToString());
  Response.AddHeader("Content-Disposition", string.Format("attachment;filename={0}", exportFileName));
  Response.BinaryWrite(bytes);
}

Для примера приведён вариант распознавания экспорта в Excel или PDF, но таким же образом можно реализовать и для других форматов.

четверг, ноября 19, 2009

А пока мы отошли...

Недавно писал одну утилитку, которой нужно было отслеживать заблокирован ли компьютер.  Нашёл очень простой способ это узнать: достаточно лишь подписаться на событие SessionSwitch класса SystemEvents, который находится в пространсве имён Microsoft.Win32.

SystemEvents.SessionSwitch += new SessionSwitchEventHandler(SystemEvents_SessionSwitch);
...
void SystemEvents_SessionSwitch(object sender, SessionSwitchEventArgs e)
{
        switch (e.Reason)
        {
                case SessionSwitchReason.SessionLock:
                //компьютер заблокирован
                case SessionSwitchReason.SessionUnlock:
                //компьютер разблокирован
        }
}

Понадобитсья может в довольно большом количестве случаев, например запускать скачивание, пока компьютер заблокирован или же какую-то ресурсоёмкую задачу.

вторник, ноября 10, 2009

Get practice!

Решил завести себе блог на английском языке, в котором буду стараться дублировать посты из этого блога, естественно, переведённые. Делаю это, чтобы вернуть свою квалификацию в английском языке, потому что за последний год без англоязычного общения потерял её (квалификацию) довольно сильно. И так, встречайте http://anothermadstory.blogspot.com/

среда, ноября 04, 2009

Мы запустились

И снова ура, товарищи! Персональный сайт фотографа Екатерины Кочиевой запущен в продакшн и доступен для просмотра по адресу www.ekaterinakochieva.ru.
О технической стороне первой версии сайта скажу, что это HTML, CSS и Java Script. Пока никакого серверного кода. Начали его переделку под ASP.NET. Обо всех багах мы знаем и очень стремимся их исправить.

Книжка-раскраска

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