In this article, we will create an API for receiving FastReport reports from the server. First of all, let's define what the API is. Literally, this abbreviation stands for software interface of the application. This means that the application has an interface that provides access to its functions. In the context of web applications, an API is a web service with a set of methods interacting with the backend (application or database). In other words, the system is a black box for us, and only web methods allow us to work with it.
So, we determined that Web Api is a web service with a set of web methods. These can be four basic CRUD functions supported by the HTTP protocol. They are implemented by requests: GET - read, POST - create, PUT - change, DELETE - delete.
Let's create this web application in this article. And FastReport.Core, specially designed for the .Net Core framework, will generate reports for us.
Create an ASP .Net Core Web application. In the second step of the wizard to create a new project, you can select the type of web application - Web API:
First of all, we need to connect libraries using the Nuget package manager.
To install the FastReport.Core and FastReport.Web packages, you need to select a local repository. But, it will have to be configured. Next to the drop-down list of storage selection there is a gear icon. Click it and see the settings window:
Select Local package source and change the path to the source. Then, click the Update button. Now, in the package manager, we are available to install FastReport.Core and FastReport.Web.
In our demo, we will see how to download reports from the server, how to view them in a browser, and how to pass a parameter to a report. So, that the main entity with which we will work is a report. Let's add the Reports class to the data model, which will have two fields: Id - report identifier, ReportName - report name.
Models Reports.cs
1 2 3 4 5 6 7 |
public class Reports { // Report ID public int Id { get; set; } // Report File Name public string ReportName { get; set; } } |
In the Controllers package, by default there is one ValuesController.cs class. We use it.
In the using section we will need libraries:
1 2 3 4 5 6 7 8 9 10 11 12 |
using System; using System.Collections.Generic; using System.Linq; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Hosting; using WebApiCore.Models; using System.IO; using System.Data; using FastReport.Utils; using FastReport; using FastReport.Export.Html; using FastReport.Export.Pdf; |
The URL for receiving the report may contain additional parameters: the format of the report file, the sign of the inline displaying, the parameter passed to the report. Add a class with the required fields to the controller:
1 2 3 4 5 6 7 8 9 |
public class ReportQuery { // Format of resulting report: png, pdf, html public string Format { get; set; } // Enable Inline preview in browser (generates "inline" or "attachment") public bool Inline { get; set; } // Value of "Parameter" variable in report public string Parameter { get; set; } } |
We need two report templates that we will demonstrate and a database for them. We use the reports from the delivery: Master-Detail.frx and Barcodes.frx. The nwind.xml database for the first report is also taken from the delivery of FR. We will place these three files in the App_Data folder, which will be created in the wwwroot directory.
The controller class may have a Route attribute that performs the routing role. This means that this class will only accept requests from the specified path. I will make explanations of the code using comments, as well as text inserts between methods.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
[Route("api/[controller]")] public class ValuesController : Controller { private readonly IHostingEnvironment _hostingEnvironment; // Use the web hosting environment interface to get the root path public ValuesController(IHostingEnvironment hostingEnvironment) { _hostingEnvironment = hostingEnvironment; } // Create a collection of data of type Reports. Add two reports. Reports[] reportItems = new Reports[] { new Reports { Id = 1, ReportName = "Master-Detail.frx" }, new Reports { Id = 2, ReportName = "Barcode.frx" } }; |
The default method for getting data in the controller is Get. Often it has an overloaded version, as in our case. Action methods usually have an associated attribute. The attribute may have a parameter.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 |
[HttpGet] public IEnumerable<Reports> Get() { return reportItems; // Returns a list of reports. } // Attribute has required id parameter [HttpGet("{id}")] public IActionResult Get(int id, [FromQuery] ReportQuery query) { string mime = "application/" + query.Format; // MIME header with default value // Find report Reports reportItem = reportItems.FirstOrDefault((p) => p.Id == id); // we get the value of the collection by id if (reportItem != null) { string webRootPath = _hostingEnvironment.WebRootPath; // determine the path to the wwwroot folder string reportPath = (webRootPath + "/App_Data/" + reportItem.ReportName); // determine the path to the report string dataPath = (webRootPath + "/App_Data/nwind.xml");// determine the path to the database using (MemoryStream stream = new MemoryStream()) // Create a stream for the report { try { using (DataSet dataSet = new DataSet()) { // Fill the source by data dataSet.ReadXml(dataPath); // Turn on web mode FastReport Config.WebMode = true; using (Report report = new Report()) { report.Load(reportPath); // Download the report report.RegisterData(dataSet, "NorthWind"); // Register data in the report if (query.Parameter != null) { report.SetParameterValue("Parameter", query.Parameter); // Set the value of the report parameter if the parameter value is passed to the URL } report.Prepare();//Prepare the report // If pdf format is selected if (query.Format == "pdf") { // Export report to PDF PDFExport pdf = new PDFExport(); // Use the stream to store the report, so as not to create unnecessary files report.Export(pdf, stream); } // If html report format is selected else if (query.Format == "html") { // Export Report to HTML HTMLExport html = new HTMLExport(); html.SinglePage = true; // Single page report html.Navigator = false; // Top navigation bar html.EmbedPictures = true; // Embeds images into a document report.Export(html, stream); mime = "text/" + query.Format; // Override mime for html } } } // Get the name of the resulting report file with the necessary extension var file = String.Concat(Path.GetFileNameWithoutExtension(reportPath), ".", query.Format); // If the inline parameter is true, then open the report in the browser if (query.Inline) return File(stream.ToArray(), mime); else // Otherwise download the report file return File(stream.ToArray(), mime, file); // attachment } // Handle exceptions catch { return new NoContentResult(); } finally { stream.Dispose(); } } } else return NotFound(); } |
Yes, we got quite a great method, but I deliberately did not devote submethods, so you do not lose sight of it.
Now we need a web page to show reports. Of course, you can do without it and enter the URL in the address bar. However, with ready-made hyperlinks to reports will be clearer.
Let's create a simple html index document. Place it in the root of the wwwroot folder. Here are its contents:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
<!DOCTYPE html> <html> <head> <title>FastReport.Core Web Api</title> <meta charset="utf-8" /> </head> <body> <h1>FastReport.Core Web Api</h1> <hr /> <a href="/api/values/">List Of All Reports</a><br /> <a href="/api/values/1?format=pdf">Get First Report in PDF</a><br /> <a href="/api/values/1?format=html">Get First Report in HTML</a><br /> <a href="/api/values/1?format=pdf&inline=true">Get First Report in PDF inline</a><br /> <a href="/api/values/2?format=html&inline=true">Get Second Report in HTML inline</a><br /> <a href="/api/values/1?format=pdf&inline=true¶meter=REPORT">Get First Report in PDF inline with Parameter=REPORT</a><br /> <a href="/api/values/1?format=html&inline=true¶meter=REPORT">Get First Report in HTML inline with Parameter=REPORT</a><br /> </body> </html> </html> |
We added 7 hyperlinks. The first allows you to display a list of available reports. The second one allows you to download a report with index 1 in PDF format. The third hyperlink allows you to download a report with index 1 in HTML format. The fourth - allows you to open a report with index 1 in the browser in PDF format. The fifth - allows you to open a report in your browser with an index of 2 in HTML format. The sixth - allows you to open a report with index 1 in the browser in PDF format and transfer the parameter value to it. The seventh - allows you to open in the browser a report with an index of 1 in HTML format and transfer the parameter value to it.
Of course, to display the value of a parameter in a report, you need to add it to the report and to the report page.
However, it is not enough to add index.html to the root directory. In order to make this page open by default you need to tweak something in the launch settings. Open the Properties folder, the launchSettings.json file. And delete in two places the line: "launchUrl": "api / values".
To enable support for static pages and FastReport libraries, add a few lines to the Configure method in Startup.cs:
1 2 3 |
app.UseFastReport(); app.UseDefaultFiles(); app.UseStaticFiles(); |
It's time to start the application:
We see a list of seven hyperlinks. Let's click on the first one:
The list of reports is displayed in json format. In .Net Core json completely supplanted xml. And the truth is so concise and understandable.
Click on the second link. And the browser downloads the report in pdf format:
Click on the fifth link. The browser opens the report as html page.
Click on the last link. The report also opens in a browser, but pay attention to its title. The header displays the value of the passed parameter - REPORT.
Thus, we learned how to create .Net Core Web API applications using FastReport.Core.