Мы смогли заставить программу просмотра отчетов работать и без проблем использовали ее в течение последних нескольких месяцев.
- У нас есть контроллер отчетов, который перечисляет ссылки на отчеты, которые мы хотим запустить
- Нажатие на одну из ссылок вызовет серверную часть Ajax и вернет частичную страницу, где мы можем заполнить все необходимые параметры.
- После того, как параметры заполнены, мы отправляем форму в «\ reports \ Name of Report».
- Вернувшись в контроллер отчетов, мы вызываем SQL, возвращаем наши данные и затем вызываем другое представление под названием «Полный отчет»
- Представление «Полный отчет» имеет только элемент управления Crystal Report Viewer, где он автоматически принимает данные отчета, которые мы передаем ему через ViewData, заполняет отчет, отображает его и отправляет пользователю
Кажется, все работает отлично.
UPDATE
Я добавил код и пояснения к шагам, которые я изначально перечислил выше. Ключевой элемент, который я пропустил, заключался в том, что в окончательном представлении есть код, который будет работать с Crystal Reports. Код позади минимален, но необходим. Чтобы Crystal Reports работал, вы получите следующие файлы:
- Файл макета. Rpt, в котором вы разрабатываете отчет
- Файл aspx, в котором содержится элемент управления Crystal Reports Report. Этот файл будет иметь некоторый код позади.
Сведения о том, как создать представление, которое будет работать с Crystal Reports:
- Создайте макет вашего отчета с помощью Crystal Reports Designer. Полученный файл будет файлом .rpt. Ради этого примера давайте назовем этот файл AllJobsSummaryReportLayout.rpt.
- При разработке отчета для «Поля базы данных» выберите одну из бизнес-сущностей или DTO, в которой хранятся результаты, возвращаемые из SQL.
- Если коротко, у нас в системе есть несколько объектов передачи данных (DTO), которые не содержат ничего, кроме скалярных значений и строк, в этих DTO нет интеллекта. Когда вызывается контроллер, он вызывает модель, модель для большинства этих отчетов возвращает список DTO, которые мы затем передаем в представление для визуализации. Эти DTO не знают, как запрашивать себя, отображать себя, они содержат только фактические значения, возвращаемые из SQL, которые затем выводит кто-то другой.
Как только файл макета Crystal Report будет создан, AllJobsSummaryReportLayout.rpt, мы создадим наш Контроллер. В Контроллере мы берем любые параметры, необходимые для запуска отчета, вызываем Модель, Модель возвращает наш список DTO, как показано в фрагменте ниже из Контроллера:
var reportViewData = model.AllJobsSummaryQuery(startDate, endDate);
if (0 != reportViewData.Count())
{
var report = new AllJobsSummaryReportLayout();
report.SetDataSource(reportViewData);
report.SetParameterValue("startDate", startDate);
report.SetParameterValue("endDate", endDate);
ViewData["ReportData"] = report;
returnView = "AllJobsSummaryView";
}
else
returnView = "noReportView";
return View(returnView);
Обратите внимание на пару пунктов здесь, мы создаем переменную 'report', которая является типом файла макета Crystal Report, AllJobsSummaryReportLayout.rpt, который мы создали выше.
После того, как мы создали переменную 'report', мы устанавливаем значения источника данных и все необходимые параметры и связываем элемент в ViewData.
Теперь давайте посмотрим на AllJobsSummaryView.aspx. Этот файл имеет форму для просмотра Crystal Reports и код файла:
<%@ Page Title="All Jobs Summary Report" Language="C#" AutoEventWireup="true" CodeBehind="AllJobsSummaryView.aspx.cs" Inherits="V.Views.Reports.AllJobsSummaryView"%>
<%@ Register Assembly="CrystalDecisions.Web, Version=10.5.3700.0, Culture=neutral, PublicKeyToken=692fbea5521e1304" Namespace="CrystalDecisions.Web" TagPrefix="CR" %>
<form id="form1" runat="server">
<div>
<a href="/Reports" id="Report"><< Return to Report Main
Page</a><br />
<CR:CrystalReportViewer ID="ReportViewer" runat="server" AutoDataBind="True" EnableDatabaseLogonPrompt="False"
EnableParameterPrompt="False" HasCrystalLogo="False" DisplayGroupTree="False"
HasDrillUpButton="False" HasToggleGroupTreeButton="False" HasViewList="False"
HasSearchButton="False" EnableDrillDown="False" EnableViewState="True"
Height="50px" ReportSourceID="CrystalReportSource1" Width="350px" />
<CR:CrystalReportSource ID="CrystalReportSource1" runat="server">
<Report FileName="AllJobsSummaryReportLayout.rpt">
</Report>
</CR:CrystalReportSource>
</div>
</form>
И код файла:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace V.Views.Reports
{
public partial class AllJobsSummaryView : ViewPage
{
protected void Page_Init(object sender, EventArgs e)
{
ReportViewer.ReportSource = ViewData["ReportData"];
}
protected void Page_Unload(object sender, EventArgs e)
{
((AllJobsSummaryReportLayout)ViewData["ReportData"]).Close();
((AllJobsSummaryReportLayout)ViewData["ReportData"]).Dispose();
}
}
}
Page_Unload является ключевым, без него у вас будет ошибка, сгенерированная Crystal Reports «Вы превысили максимальное количество отчетов, установленное вашим администратором.»
Этот метод работает в производственной среде уже более двух лет.