Подтвердить что ты не робот

Просмотр отчетов SSRS на сайте ASP.net MVC

Есть ли способ разместить средство просмотра отчетов отчетов служб отчетов SQL Server в представлении MVC ASP.net? Если нет... что это лучший способ сделать это?

4b9b3361

Ответ 1

Нет, не в представлении MVC. Но вы можете иметь страницы веб-форм, в которых у них есть серверные элементы, смешанные с вашим сайтом MVC.

Хм, просто запустил "mix asp.net mvc и веб-формы", чтобы найти несколько примеров, и google спросил, я человек или нет:)

В любом случае, здесь ссылка - http://www.packtpub.com/article/mixing-asp.net-webforms-and-asp.net-mvc - там несколько. Я также сделал это на сайте MVC по той же причине - контроль отчета.

Ответ 2

Нет, элемент управления ReportViewer не будет работать, если вы разместите его в представлении MVC, поскольку для него требуется ViewState. Вам нужно будет создать веб-форму старой школы и вместо этого поставить ReportViewer.

Решением, которое я использовал в проекте, над которым я работал, было создание настраиваемого обработчика маршрутов, поэтому я все же мог использовать маршрутизацию URL. Обработчик маршрута принимает такие параметры, как имя отчета из коллекции RouteData, создает экземпляр моей веб-формы и передает параметры ему через общедоступные свойства. Веб-форма будет читать их в Page_Load и настроить элемент управления ReportViewer.

// Configure a route in Global.asax.cs that is handled by a ReportRouteHandler
routes.Add("ReportRoute", new Route("Reports/{reportName}",
                                    new ReportRouteHandler());

public class ReportRouteHandler : IRouteHandler {
    public IHttpHandler GetHttpHandler(RequestContext requestContext) {
        var reportName = requestContext.RouteData.Values["reportName"] as string;

        var webform = BuildManager
            .CreateInstanceFromVirtualPath("~/Path/To/ReportViewerWebForm.aspx",
                                           typeof(Page)) as ReportViewerWebForm;
        webform.ReportToShow = reportName;
        return webform;
    }
}

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

Обновить. Похоже, если вы используете ASP.NET 4.0, большая часть этого может быть выполнена автоматически

Ответ 4

Реализация элемента управления SSRS ReportViewer в MVC состоит из двух проблем:

  1. Как минимум, вам необходимо добавить правильные зависимости, обработчики и конфигурацию для элемента управления ReportViewer (независимо от типа проекта).
  2. Более сложное препятствие заключается в смешивании веб-форм и MVC. Нам нужен способ отрисовки и маршрутизации входящих запросов, чтобы они обрабатывались страницами, элементами управления и действиями WebForms.

Проблема 1 - Настройка ReportViewer

Если вы уже много сделали с настройкой элементов управления ReportViewer в прошлом, это может быть старая проблема, и вы можете перейти к разделу 2.

  1. Добавить пакет/ссылку. Элемент управления ReportViewer в Microsoft.ReportViewer.WebForms.dll. Вы можете включить в свой проект, добавив пакет Microsoft.ReportViewer.WebForms из nuget:

    Nuget - Microsoft.ReportViewer.WebForms

  2. Обработчики Web.config. В соответствии с этой статьей, посвященной настройкам Web.config для ReportViewer, и на этот вопрос SO вам необходимо добавить в файл web.config:

    <system.web>
      <httpHandlers>
        <add verb="*" path="Reserved.ReportViewerWebControl.axd" 
             type="Microsoft.Reporting.WebForms.HttpHandler,
                   Microsoft.ReportViewer.WebForms, Version=10.0.0.0, Culture=neutral,
                   PublicKeyToken=b03f5f7f11d50a3a" />
      </httpHandlers>
    </system.web>
    <system.webServer>
      <handlers>
        <remove name="ReportViewerWebControlHandler" />
        <add name="ReportViewerWebControlHandler" preCondition="integratedMode"
             verb="*" path="Reserved.ReportViewerWebControl.axd" 
             type="Microsoft.Reporting.WebForms.HttpHandler, 
                   Microsoft.ReportViewer.WebForms, Version=10.0.0.0, Culture=neutral,
                   PublicKeyToken=b03f5f7f11d50a3a"/>
      </handlers>
    </system.webServer>
    

    В ответ на этот вопрос о дубликатах ключей, как правило, легче всего удалить, а затем повторно добавить настройки веб-сервера.

  3. Исправьте испорченные запросы изображений - в ReportViewer обнаружен дефект с blank.gif изображениями global.asax.cs поэтому вы можете добавить следующее исправление в ваш global.asax.cs:

    protected void Application_BeginRequest(object sender, EventArgs e)
    {
        HttpRequest req = HttpContext.Current.Request;
        if (req.Url.PathAndQuery.StartsWith("/Reserved.ReportViewerWebControl.axd") &&
            !req.Url.ToString().ToLower().Contains("iteration") &&
            !String.IsNullOrEmpty(req.QueryString["ResourceStreamID"]) &&
            req.QueryString["ResourceStreamID"].ToLower().Equals("blank.gif"))
        {
            Context.RewritePath(String.Concat(req.Url.PathAndQuery, "&IterationId=0"));
        }
    }
    
  4. IgnoreRoute.axd - если его там еще нет, обязательно разрешите ScriptResources в вашем RouteConfig.cs:

    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
    
  5. Добавить ReportViewerPage.aspx - добавить страницу WebForm, которая будет содержать экземпляр элемента управления ReportViewer. Для работы этому <form runat="server" > управления необходимо найти элемент управления ScriptManager и поместить его в <form runat="server" >.
    Итак, ваша новая страница .aspx должна выглядеть примерно так:

    <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="ReportViewerPage.aspx.cs" Inherits="MVCAppWithReportViewer.ReportViewerPage" %>
    <%@ Register TagPrefix="rsweb" Namespace="Microsoft.Reporting.WebForms" Assembly="Microsoft.ReportViewer.WebForms, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" %>
    
    <!DOCTYPE html>
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head runat="server">
        <title>Report Viewer</title>
    </head>
    <body>
        <form id="form1" runat="server">
            <rsweb:ReportViewer ID="ReportViewer" runat="server" 
                                Height="100%" Width="100%" 
                                SizeToReportContent="True" ProcessingMode="Remote" />
            <asp:ScriptManager ID="ScriptManager1" runat="server" />
        </form>
    </body>
    </html>
    
  6. Подключите ReportViewer к Page_Load Предполагается, что у вас уже есть отчет SSRS, полностью развернутый на сервере отчетов, который доступен по адресу, подобному следующему:

    http://ReportServerName/Reports/Pages/Report.aspx?ItemPath= %2fCompany%2f ClientReport

    Тогда ваш код на новой странице WebForm должен выглядеть следующим образом:

    public partial class ReportViewerPage : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            if (!Page.IsPostBack)
            {
                // confirm report properties (also setable in attributes)
                ReportViewer.ProcessingMode = ProcessingMode.Remote;
    
                // config variables
                var reportServer = "ReportServerName";
                var reportPath = "/Company/";
                var reportName = "ClientReport";    
    
                // report setup
                var serverReport = new ServerReport();
                serverReport = ReportViewer.ServerReport;
                serverReport.ReportServerUrl = new Uri([email protected]"http://{reportServer}/ReportServer");
                serverReport.ReportPath = [email protected]"{reportPath}{reportName}";
    
                // report input
                var parameters = new List<ReportParameter>();
                parameters.Add(new ReportParameter("User_uid", "1"));
                serverReport.SetParameters(parameters);
    
                // run report
                serverReport.Refresh();
            }
        }
    }
    
  7. Просмотр отчета - на этом этапе вы сможете просматривать свой отчет самостоятельно, выбрав " Просмотр в браузере" или Ctrl + Shift + W

    View in Browser

Проблема 2 - Смешивание веб-форм и MVC

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

  • Маршруты MVC будут выглядеть примерно так: {controller}/{action}/{id} где механизм маршрутизации автоматически найдет Controller и Action с указанным именем, и входящие запросы будут обрабатываться этим методом. При любом запросе страницы, будь то загрузка страницы, отправка формы, нажатие кнопки, навигация по привязке или вызовы ajax, точный выполняемый метод всегда указывается в url {action}.

  • WebForms направляет к коду, находя физический адрес страницы .aspx, а затем использует ViewState & PostData для подключения и запуска событий на этой странице/элементе управления.

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

    ASP.NET WebForms - Postback

Это довольно большое ограничение на наши доступные решения. В элементе управления ReportViewer нет ничего особенного. Это просто сложный набор классов UserControl, которые реагируют на нажатия и другие входные события, отправляя обратно текущий адрес вместе с ViewState и информацией о событии. Поэтому любые предположения, которые были включены в маршрутизацию и навигацию ReportViewer, должны сохраняться в нашей оболочке MVC.

  1. Вариант 1 - Добавить маршрут для страницы .aspx

    Начиная с MVC 4. 0+ вы можете использовать URL-маршрутизацию с WebForms. Это хорошо сочетается с MVC, добавляя Map Page Route (обратите внимание на часть страницы), чтобы сопоставить маршрут с физическим файлом. Поэтому добавьте следующее в ваш RouteConfig.cs:

    routes.MapPageRoute(
        routeName: "ReportViewer",
        routeUrl: "ReportViewer/{reportName}",
        physicalFile: "~/ReportViewerPage.aspx"
    );
    

    Отчет будет запущен при ~/Reports/reportName по адресу ~/Reports/reportName. Это, вероятно, будет вызываться изнутри действия контроллера, возможно, с некоторыми введенными пользователем параметрами или строками соединения web.config. Существует множество способов управления состоянием в ASP.NET и передачи значений на страницы веб-форм ASP.NET. Один из вариантов - сохранить информацию в сеансе и перенаправить, например, в свой контроллер:

    HttpContext.Session[reportSetup.ReportName] = new ReportSetup() {ReportName = "ClientReport"}; //reportSetup;}
    return RedirectToRoute("ReportViewer", new { reportName = reportSetup.ReportName});
    

    Затем на странице .aspx вы можете получить reportName из значений RouteData и любых параметров установки из сеанса:

    // get report name from route
    string reportName = Page.RouteData.Values["reportName"].ToString();
    
    // get model from session and clear
    ReportSetup setup = (ReportSetup)HttpContext.Current.Session[reportName];
    

    Плюсы:

    • Кажется, что большая часть маршрутизации работает по умолчанию, и элементы управления AJAX работают нормально, поэтому вы можете установить AyncRendering=True

    Минусы:

    • Трудно использовать веб-форму ASP с макетом Razor MVC, поэтому рендеринг выведет пользователей из потока остальной части приложения.
    • Кроме того, значения отчета должны быть представлены как часть URL или передаваться косвенно через сеанс (в отличие от гидратации непосредственно на объект).
  2. Вариант 2. .ascx в PartialView на своей странице

    Адаптировано из Как я могу использовать элемент управления ReportViewer с Razor? , вы можете использовать .ascx управления .ascx в PartialViews, если они наследуются от System.Web.Mvc.ViewUserControl.

    Создайте новый пользовательский элемент управления Web Forms с именем ReportViewerControl.ascx который выглядит следующим образом:

    <%@ Control Language="C#" AutoEventWireup="true" CodeBehind="ReportViewerControl.ascx.cs" Inherits="MVCAppWithReportViewer.ReportViewerControl" %>
    <%@ Register TagPrefix="rsweb" Namespace="Microsoft.Reporting.WebForms" Assembly="Microsoft.ReportViewer.WebForms, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" %>
    
    <form id="form1" runat="server">
        <rsweb:ReportViewer ID="ReportViewer" runat="server" 
                            Height="100%" Width="100%"  
                            SizeToReportContent="True" ProcessingMode="Remote"
                            AsyncRendering="False" />
        <asp:ScriptManager ID="ScriptManager1" runat="server" 
                           EnablePartialRendering="false"  />
    </form>
    

    Примечание. Необходимо установить AsyncRendering="False" и EnablePartialRendering="false"

    В приведенном ниже коде вам необходимо заменить тип наследования от System.Web.UI.UserControl на System.Web.Mvc.ViewUserControl.

    А в Page_Init вам нужно установить для Context.Handler Page чтобы события регистрировались правильно.

    Поэтому ReportViewerControl.ascx.cs должен выглядеть так:

    public partial class ReportViewerControl : System.Web.Mvc.ViewUserControl
    {
        protected void Page_Init(object sender, EventArgs e)
        {
            // Required for report events to be handled properly.
            Context.Handler = Page;
        }
    
        protected void Page_Load(object sender, EventArgs e)
        {
            if (!Page.IsPostBack)
            {
                /* ... report setup ... */ 
                serverReport.Refresh();
            }
        }
    }
    

    Чтобы отобразить отчет, добавьте следующее в представление вашего контроллера:

    @Html.Partial("ReportViewerControl", Model)
    

    А затем в событии Page_Load ReportViewerControl.ascx.cs вы можете получить переданную модель из свойства ViewUserControl.Model например:

    ReportSetup setup = (ReportSetup)Model;
    

    Плюсы:

    • Можно встроить в мастер _layout.cshtml и использовать в обычных представлениях
    • Может пройти модель напрямую

    Минусы:

    • AsyncRendering должно быть установлено значение false, поэтому такие взаимодействия, как разбиение на страницы и сортировка, вызывают полное обновление страницы и иногда являются неудачными. Брайан Хартман имеет блог только для ReportViewer и рассказывает об AsyncRendering и обо всем, что с ним связано.

Дальнейшее чтение:

Ответ 5

Это немного просто и потребует немного исправления, чтобы передать что-то приличное для представления в MVC

public ActionResult Index()
{
    /*Credentials of a user that has access to SSRS*/
    string userid = "UserId";
    string password = "MyPassword";
    string domain = "MyDomain";

    string reportURL="http://ServerName/ReportServer?/ReportsFolder/ReportName&Parameter=UserName&rs:Command=Render&rs:Format=PDF";

    NetworkCredential nwc = new NetworkCredential(userid, password, domain);

    WebClient client = new WebClient();
    client.Credentials = nwc;

    Byte[] pageData = client.DownloadData(reportURL);

    Response.ContentType = "application/pdf";
    Response.AddHeader("Content-Disposition", "attachment; filename=" + DateTime.Now);
    Response.BinaryWrite(pageData);
    Response.Flush();
    Response.End();

    //return View();
    }

Ответ 6

Простым решением является добавление iframe к вашему представлению MVC, который открывает отчет, который вы хотите, из веб-службы служб отчетов. IFrame будет полностью работать с компонентами от служб отчетности. Параметры, используемые для url в iframe, также могут управляться динамически (например, с помощью ajax), если вы хотите переместить компоненты в свой MVC-просмотр.

Хотя это работает, вам все равно придется войти в службу веб-отчетов (iframe откроет диалоговое окно входа в систему). Для IE это "автоматически" выполняется с использованием учетных данных входа в Windows.

Ответ 7

Я использую эту ссылку ниже в качестве ссылки и она работает в нашей среде Prod

https://github.com/GaoxinHuang/SSRSDemo