Add the Report Designer Component to an ASP. NET MVC Application | Reporting Tools

Add the Report Designer Component to an ASP. NET MVC Application

Umamageswari Elumalai
Bold Reports

--

In this blog, we will see how to create an ASP.NET MVC reporting web application to render the Report Designer control. The ASP.NET MVC Report Designer is a web-based WYSIWYG reporting tool for creating and editing RDL and RDLC reports. The Bold Reports Report Designer component comes with a wide range of report items to help you transform data into meaningful metrics and quickly build business reports.

Prerequisites

To get started with an ASP.NET MVC 5 application, ensure the following software is installed on your machine.

  • .NET Framework 4.5 or above
  • ASP.NET MVC 5

Steps to create an ASP.NET MVC Reporting application

  1. Open Visual Studio 2022 and click Create a new project.
Create a new project
Create a new project

2. Choose ASP.NET Web Application (.NET Framework) and click Next.

Create .Net Web Application
Create .Net Web Application

3. Change the project name and then click Create.

4. Select MVC, check the Web API checkbox, and click Create. A default ASP.NET MVC application is created.

Choose MVC Web API
Choose MVC Web API

5. In the solution explorer tab, right-click the project or solution and choose to manage NuGet packages and in the browser tab.

6. Search for the Bold Reports web package and install it in your MVC application. Similarly, install the BoldReports.Mvc5, and BoldReports.JavaScript packages.

The purpose of each package is listed in the following table:

Packages and Purposes
Packages and Purposes

The following table provides details about the dependent packages and their uses.

Dependent packages and their uses
Dependent packages and their uses

7. Open the ~/Views/Web.config file and add or register the BoldReports.Mvc namespace under the namespaces tag.

<namespaces>
<add namespace="BoldReports.Mvc"/>
</namespaces>

8. Open the Web.config file from the root directory. Set the Unobtrusive.JavaScriptEnabled to false, as shown in the following code.

<configuration>
<appSettings>
……
……
<add key="UnobtrusiveJavaScriptEnabled" value="false" />
</appSettings>
……
……
</configuration>

If you want to use ‘UnobtrusiveJavaScriptEnabled,’ then use the ej.unobtrusive.min.js script with your application. You can get the script from the installed location, as shown in the following image.

Script File
Script File

9. While installing the BoldReports.JavaScripts NuGet package, the CodeMirror scripts, and the scripts required to render the Report Designer control will be added to the scripts folder. The CSS files are added to the content folder. Add the listed references in the same order as follows. You can replace the following code in the \Views\Shared\_Layout.cshtml page.

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>@ViewBag.Title - My ASP.NET Application</title>
@Styles.Render("~/Content/css")
@Styles.Render("~/Content/bold-reports/material/bold.reports.all.min.css")
@Styles.Render("~/Content/bold-reports/material/bold.reportdesigner.min.css")
@Styles.Render("~/Scripts/CodeMirror/lib/codemirror.css")
@Styles.Render("~/Scripts/CodeMirror/addon/hint/show-hint.css")
@Scripts.Render("~/bundles/modernizr")
<!--Render the gauge item. Add these scripts only if your report contains the gauge report item.-->
@Scripts.Render("~/Scripts/bold-reports/common/ej2-base.min.js")
@Scripts.Render("~/Scripts/bold-reports/common/ej2-data.min.js")
@Scripts.Render("~/Scripts/bold-reports/common/ej2-pdf-export.min.js")
@Scripts.Render("~/Scripts/bold-reports/common/ej2-svg-base.min.js")
@Scripts.Render("~/Scripts/bold-reports/data-visualization/ej2-circulargauge.min.js")
@Scripts.Render("~/Scripts/bold-reports/data-visualization/ej2-lineargauge.min.js")
@Scripts.Render("~/Scripts/bold-reports/data-visualization/ej2-maps.min.js")
</head>
<body>
<div style="height: 600px;width: 100%;">
@RenderBody()
</div>
@Scripts.Render("~/bundles/jquery")
@Scripts.Render("~/Scripts/jsrender.min.js")
@Scripts.Render("~/bundles/bootstrap")
@Scripts.Render("~/Scripts/CodeMirror/lib/codemirror.js")
@Scripts.Render("~/Scripts/CodeMirror/addon/hint/show-hint.js")
@Scripts.Render("~/Scripts/CodeMirror/addon/hint/sql-hint.js")
@Scripts.Render("~/Scripts/CodeMirror/mode/sql/sql.js")
@Scripts.Render("~/Scripts/CodeMirror/mode/vb/vb.js")
@Scripts.Render("~/Scripts/bold-reports/common/bold.reports.common.min.js")
@Scripts.Render("~/Scripts/bold-reports/common/bold.reports.widgets.min.js")
@Scripts.Render("~/Scripts/bold-reports/common/bold.report-designer-widgets.min.js")
<!--Renders the chart item. Add this script only if your report contains the chart report item.-->
@Scripts.Render("~/Scripts/bold-reports/data-visualization/ej.chart.min.js")
<!-- Report Designer component script-->
@Scripts.Render("~/Scripts/bold-reports/bold.report-viewer.min.js")
@Scripts.Render("~/Scripts/bold-reports/bold.report-designer.min.js")
@RenderSection("scripts", required: false)
</body>
</html>

10. In the _Layout.cshtml page, use the reporting script manager in the body element that places the Report Designer control initialization script in the webpage. To initialize the scripts properly, the script manager should be included at the end of the body element. Open the index.cshtml page from the Home folder, and replace it with the code.

<body>    
....
....
<!-- Bold Reporting ScriptManager -->
@Html.Bold().ScriptManager()
</body>

The main reason for referencing the script manager in the _Layout file is that it can be referenced by all the View files present within your application.

11. The ASP.NET MVC Report Designer requires a Web API service to render the Report Designer control:

a. Right-click the Controller folder and select Add.

b. Select a New item from the context menu.

c. In the Add New Item dialog, select the Web API controller class.

d. Name it cs and then click Add.

e. Replace the following code within the ReportDesigneController.cs file.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using BoldReports.Web;
using BoldReports.Web.ReportViewer;
using BoldReports.Web.ReportDesigner;
using System.IO;
using System.Reflection;
using System.Web;

namespace ReportDesignerSample.Api
{
public class ReportingAPIController : ApiController, IReportDesignerController
{
/// <summary>
/// Get the path of a specific file
/// </summary>
/// <param name="itemName">Name of the file to get the full path</param>
/// <param name="key">The unique key for report designer</param>
/// <returns>Returns the full path of file</returns>
[NonAction]
private string GetFilePath(string itemName, string key)
{
string dirPath = Path.Combine(HttpContext.Current.Server.MapPath("~/") + "Cache", key);

if (!Directory.Exists(dirPath))
{
Directory.CreateDirectory(dirPath);
}

return Path.Combine(dirPath, itemName);
}

/// <summary>
/// Action (HttpGet) method for getting a resource of images in the report.
/// </summary>
/// <param name="key">The unique key for request identification.</param>
/// <param name="image">The name of requested image.</param>
/// <returns>Returns the image as HttpResponseMessage content.</returns>
[System.Web.Http.ActionName("GetImage")]
[AcceptVerbs("GET")]
public object GetImage(string key, string image)
{
return ReportDesignerHelper.GetImage(key, image, this);
}

/// <summary>
/// Action (HttpPost) method for posting the request for designer actions.
/// </summary>
/// <param name="jsonData">A collection of keys and values to process the designer request.</param>
/// <returns>Json result for the current request.</returns>
public object PostDesignerAction(Dictionary<string, object> jsonData)
{
//Processes the designer request and returns the result.
return ReportDesignerHelper.ProcessDesigner(jsonData, this, null);
}

/// <summary>
/// Sets the resource into a storage location.
/// </summary>
/// <param name="key">The unique key for request identification.</param>
/// <param name="itemId">The unique key to get the required resource.</param>
/// <param name="itemData">Contains the resource data.</param>
/// <param name="errorMessage">Returns the error message, if the write action is failed.</param>
/// <returns>Returns true, if resource is successfully written into storage location.</returns>
[NonAction]
public bool SetData(string key, string itemId, ItemInfo itemData, out string errorMessage)
{
errorMessage = string.Empty;

if (itemData.Data != null)
{
File.WriteAllBytes(this.GetFilePath(itemId, key), itemData.Data);
}
else if (itemData.PostedFile != null)
{
var fileName = itemId;
if (string.IsNullOrEmpty(itemId))
{
fileName = Path.GetFileName(itemData.PostedFile.FileName);
}
itemData.PostedFile.SaveAs(this.GetFilePath(fileName, key));
}
return true;
}

/// <summary>
/// Gets the resource from the storage location.
/// </summary>
/// <param name="key">The unique key for requesting identification.</param>
/// <param name="itemId">The unique key to get the required resource.</param>
/// <returns>Returns the resource data and error message.</returns>
[NonAction]
public ResourceInfo GetData(string key, string itemId)
{
var resource = new ResourceInfo();
try
{
var filePath = this.GetFilePath(itemId, key);
if (itemId.Equals(Path.GetFileName(filePath), StringComparison.InvariantCultureIgnoreCase) && File.Exists(filePath))
{
resource.Data = File.ReadAllBytes(filePath);
}
else
{
resource.ErrorMessage = "File not found from the specified path";
}
}
catch (Exception ex)
{
resource.ErrorMessage = ex.Message;
}
return resource;
}
/// <summary>
/// Action (HttpPost) method for posted or uploaded file actions.
/// </summary>
public void UploadReportAction()
{
//Processes the designer file upload requests.
ReportDesignerHelper.ProcessDesigner(null, this, System.Web.HttpContext.Current.Request.Files[0]);
}

/// <summary>
/// Sends a GET request and returns the requested resource for a report.
/// </summary>
/// <param name="key">The unique key to get the desired resource.</param>
/// <param name="resourcetype">The type of the requested resource.</param>
/// <param name="isPrint">If set to <see langword="true"/>, then the resource is generated for printing.</param>
/// <returns> Resource object for the given key</returns>
[System.Web.Http.ActionName("GetResource")]
[AcceptVerbs("GET")]
public object GetResource(string key, string resourcetype, bool isPrint)
{
//Returns the report resource for the requested key.
return ReportHelper.GetResource(key, resourcetype, isPrint);
}

/// <summary>
/// Report Initialization method that is triggered when the reportbeginsn being processed.
/// </summary>
/// <param name="reportOptions">The ReportViewer options.</param>
[NonAction]
public void OnInitReportOptions(ReportViewerOptions reportOption)
{
var resourcesPath = System.Web.Hosting.HostingEnvironment.MapPath("~/Scripts");
reportOption.ReportModel.ExportResources.Scripts = new List<string>
{
resourcesPath + @"\bold-reports\common\bold.reports.common.min.js",
resourcesPath + @"\bold-reports\common\bold.reports.widgets.min.js",
//Gauge component scripts
resourcesPath + @"\bold-reports\common\ej2-base.min.js",
resourcesPath + @"\bold-reports\common\ej2-data.min.js",
resourcesPath + @"\bold-reports\common\ej2-pdf-export.min.js",
resourcesPath + @"\bold-reports\common\ej2-svg-base.min.js",
resourcesPath + @"\bold-reports\data-visualization\ej2-lineargauge.min.js",
resourcesPath + @"\bold-reports\data-visualization\ej2-circulargauge.min.js",
//Map component script
resourcesPath + @"\bold-reports\data-visualization\ej2-maps.min.js",
//Report Viewer script
resourcesPath + @"\bold-reports\data-visualization\ej.chart.min.js",
resourcesPath + @"\bold-reports\bold.report-viewer.min.js"
};

reportOption.ReportModel.ExportResources.DependentScripts = new List<string>
{
resourcesPath + @"\jquery-1.7.1.min.js"
};
}

/// <summary>
/// Report loaded method triggered when report and subreport begin to be loaded.
/// </summary>
/// <param name="reportOptions">The ReportViewer options.</param>
[NonAction]
public void OnReportLoaded(ReportViewerOptions reportOption)
{
//You can update report options here.
}

/// <summary>
/// Action (HttpPost) method for posting the request for report process.
/// </summary>
/// <param name="jsonData">The JSON data posted for processing report.</param>
/// <returns>The object data.</returns>
public object PostReportAction(Dictionary<string, object> jsonData)
{
//Processes the report request and returns the result.
return ReportHelper.ProcessReport(jsonData, this as IReportController);
}
}
}

IReportDesignerController interface

The IReportDesignerController interface contains the required actions and helper methods declaration to process the designer file and data actions:

  • The PostDesignerAction method is used to post requests for designer action.
  • The SetData method writes the resource file information and data into a storage location.
  • The GetData method reads the resource file information and data from a storage location.
  • The UploadReportAction invokes the action method for posting the file actions.
  • The GetResource method is used to get the resource.
  • The OnInitReportOptions method is initialized when the report is about to be processed.
  • The OnReportLoaded method is initialized when the report and subreport start loading.
  • The PostReportAction invokes the action method for posting the request in the reporting process.

ReportDesignerHelper class

The class ReportDesignerHelper contains helper methods that help to process Post or Get requests from the web Report Designer control and return the response to the web Report Designer control. It has the following methods.

Methods and their descriptions for ReportDesignerHelper
Methods and their descriptions for ReportDesignerHelper

ReportHelper class

ReportHelper contains helper methods that help process Post or Get requests for report preview actions and return the response to the Report Designer.

Methods and their descriptions for ReportHelper
Methods and their descriptions for ReportHelper

Routing information

Routing is the process of directing an HTTP request to a controller. The functionality of this processing is implemented in System.Web.Routing.

Action parameter

The action parameter names the action method on the controller and is used to map the method in the controller.
To include an action name in the URI, open the WebApiConfig.cs file from the APP_Start folder and change the route template in the Register method, as shown in the following code sample.

public static class WebApiConfig
{

public static void Register(HttpConfiguration config)
{
// Web API configuration and services.
// Web API routes
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}

Report designer service URL

To open and save reports in the application, set the Web API controller name to the ServiceUrl property of the Report Designer. You can replace the following code on your Report Designer page.

@(Html.Bold().ReportDesigner("designer").ServiceUrl(Url.Content("~/api/ReportingAPI")))

Run the ASP.NET MVC Reporting application

Run the sample application. You can see the Report Designer on the page, as displayed in the following screenshot.

ASP.NET MVC Report Designer
ASP.NET MVC Report Designer

Conclusion

I hope this blog provided a clear idea of how to add the Report Designer component to an ASP.NET MVC application. To explore more, look through Bold Reports demo samples and documentation site.

If you have any questions, please post them in the comments section. You can also contact us through our contact page, or if you already have an account, you can log in to ask your support question.

Bold Reports now offers a 15-day free trial without any credit card information required. We welcome you to start a free trial and experience Bold Reports for yourself. Try it and let us know what you think!

Catch us on our official Twitter, Facebook, LinkedIn, Pinterest, and Instagram pages for info about upcoming releases.

Originally published at https://boldreports.com on September 23, 2022.

--

--