ASP.NET Core - Gerando relatórios com FastReport - IV
 Neste artigo vamos continuar mostrando como gerar relatórios com o FastReport desta vez em uma aplicação ASP.NET Core Web API.


Continuando a terceira parte do artigo vamos agora realizar a integração do relatório gerado no artigo anterior com a aplicação ASP.NET Core Web API que foi criada no primeiro artigo.

 


 


 

Criando a aplicação ASP.NET Core Web API

 

Vamos criar agora um novo projeto no VS 2022 usando o template ASP .NET Core Web API chamado ApiFastReport:
 

 

Com a aplicação criada vamos remover o controlador WeatherForecastController e a classe WeatherForeCast do projeto.

 

A seguir temos que incluir os pacotes do Entity Framework Core e do FastReport no projeto.

 

Para isso usando a janela no menu Tools->..->Manage Nuget Packages for Solution , na guia Browse basta selecionar e clicar no botão Install os seguintes pacotes:

  1. Microsoft.EntityFrameworkCore.SqlServer

  2. Microsoft.EntityFrameworkCore.Design

  3. FastReport.OpenSource

  4. FastReport.OpenSource.Export.PdfSimple

  5. FastReport.OpenSource.Web

  6. FastReport.OpenSource.Data.MsSql

Observe que incluímos o pacote para realizar a conexão com o SQL Server pois vamos usar o Designer para criar um DataSource usando a conexão com o SQL Server.

 

De forma que ao final do processo na guia Installed você veja os componentes instalados:

 



A seguir vamos criar uma pasta Models e nesta pasta vamos criar a classe Product contendo as propriedades que serão acessadas :

 

namespace ApiFastReport.Models;

public class Product
{
    public int ProductID { get; set; }
    public string? ProductName { get; set; }
    public Int16 UnitsInStock { get; set; }
    public decimal UnitPrice { get; set; }
}

 

Vamos definir a string de conexão para acessar o banco de dados Northwind no seu ambiente no arquivo appsettings.json:

 

{
  "ConnectionStrings": {
    "DefaultConnection": "Data Source=SQLEXPRESS;Initial Catalog=Northwind;Integrated Security=True"
  },
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "AllowedHosts": "*"
}

A seguir vamos criar uma pasta Context no projeto e nesta pasta criar a classe AppDbContext que representa o contexto do EF Core:

public class AppDbContext : DbContext
{
    public AppDbContext(DbContextOptions options) : base(options)
    {}

    public DbSet<Product> Products { get; set; }
}

 

Podemos agora realizar o registro do contexto do EF Core, da conexão com o SQL Server e do middleware do FastReport na classe Program.
 

using Microsoft.EntityFrameworkCore;
using WebFastReport.Models;
using WebFastReport.Services;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllersWithViews();

var con = builder.Configuration.GetConnectionString("DefaultConnection");
builder.Services.AddDbContext<AppDbContext>(options =>
             options.UseSqlServer(con));

FastReport.Utils.RegisteredObjects.AddConnection(typeof(MsSqlDataConnection));

var app = builder.Build();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Home/Error");
    app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseAuthorization();
app.UseFastReport();
app.MapControllers();

app.MapControllerRoute(
    name: "default",
    pattern: "{controller=Home}/{action=Index}/{id?}");

app.Run();

Criando o relatório usando o Designer

Vamos abrir o Designer usando o aplicativo Designer.exe e a seguir vamos criar um Data Source.

Para isso no menu Data selecione Add Data Source...

Na janela Data Wizard vamos criar uma conexão com o banco de dados Northwind.mdf no SQL Server:

 

 

A seguir selecione a tabela Products e os campos : ProductID, ProductName, UnitPrice e UnitsInStock :

 

 

Clicando em Finish teremos a visão da conexão e do Data Source com a tabela Products e os campos selecionados que podemos usar no Designer para criar o relatório.


 

A seguir vamos criar o leiaute mostrado na figura abaixo usando os recursos do Designer :

 

Vamos salvar este relatório com o nome productsreport.frx na pasta wwwroot/reports do projeto Web API.

Criando o controlador ProductsController

 

Na pasta Controllers vamos criar o controlador ProductsController e criar o método Action ReportProducts que vai gerar o relatório no formato PDF usando o código abaixo:
 

using ApiFastReport.Context;
using ApiFastReport.Models;
using FastReport.Export.PdfSimple;
using FastReport.Web;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using System.Data;

namespace ApiFastReport.Controllers;

[Route("api/[controller]")]
[ApiController]

public class ProductsController : ControllerBase
{
    private readonly AppDbContext _context;
    private readonly IWebHostEnvironment _webHostEnvironment;

    public ProductsController(AppDbContext context, IWebHostEnvironment
webHostEnvironment)
    {
        _context = context;
        _webHostEnvironment = webHostEnvironment;
    }

    [Route("report")]
    [HttpGet]
    [ProducesResponseType(typeof(List<Product>), StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status400BadRequest)]
    [ProducesResponseType(StatusCodes.Status404NotFound)]

    public async Task<ActionResult<List<Product>>> ReportProducts()
    {
        try
        {
            var products = await _context.Products.ToListAsync();

            if (products is null)
                return NotFound();

            var webReport = new WebReport();

            webReport.Report.Load(Path.Combine(
                 _webHostEnvironment.ContentRootPath,
                "wwwroot/reports", "productsreport.frx"));

            GenerateDataTableReport(products, webReport);

            webReport.Report.Prepare();

            using MemoryStream stream = new MemoryStream();
            webReport.Report.Export(new PDFSimpleExport(), stream);
            stream.Flush();
            byte[] arrayReport = stream.ToArray();

            return File(arrayReport, "application/zip", "ProductsReport.pdf");
        }
        catch (Exception)
        {
            return BadRequest();        }
    }

    private void GenerateDataTableReport(List<Product> products,
                                                             WebReport webReport)
    {
        var productsDataTable = new DataTable();
        productsDataTable.Columns.Add("ProductName", typeof(string));
        productsDataTable.Columns.Add("UnitsInStock", typeof(int));
        productsDataTable.Columns.Add("UnitPrice", typeof(decimal));

        foreach (var item in products)
        {
            productsDataTable.Rows.Add(item.ProductName,
                           item.UnitsInStock, item.UnitPrice);
        }
        //registra o datatable para usar no relatorio
        webReport.Report.RegisterData(productsDataTable, "Products");
    }
}

 

Vamos entender o código :

 

Injetamos o construtor do controlador a instância do contexto e de IWebHostEnvironment e no método Action

obtemos a lista de produtos.

 

A seguir criamos uma instância de WebReport :

  var webReport = new WebReport();

 

Carregamos o relatório productsreport.frx da pasta wwwroot/reports:

   webReport.Report.Load(Path.Combine(_webHostEnvironment.ContentRootPath,
                "wwwroot/reports", "productsreport.frx"));

 

Chamamos o método GenerateDataTableReport para gerar o DataTable, preencher com dados e registrar este objeto para uso no FastReport.
    GenerateDataTableReport(products, webReport);

 

A seguir preparamos o relatório para uso:

     webReport.Report.Prepare();

 

A seguir criamos um MemoryStream e exportamos no formato PDF. A seguir gravamos o relatório gerado neste formato em um array de bytes e retornamos o arquivo com este conteúdo como um arquivo que poderá ser baixado e aberto para exibir o relatório:

            using MemoryStream stream = new MemoryStream();
            webReport.Report.Export(new PDFSimpleExport(), stream);
            stream.Flush();
            byte[] arrayReport = stream.ToArray();
            return File(arrayReport, "application/zip", "ProductsReport.pdf");

Com isso podemos executar o projeto e verificar a nossa implementação.  Agora é só alegria...

 

Executando o projeto teremos inicialmente a exibição do endpoint da API com o mapeamento: /ápi/Products/report
 


 

Acionando o endpoint e executando teremos como resultado o status Code 200 e no Response Body temos o link para fazer o download do arquivo gerado:

 

 

Como estou usando o Chrome é exibido na base do navegador o arquivo baixado onde podemos abrir o arquivo :

 

 

Clicando em Abrir teremos o relatório no formato PDF gerado:

 

 

Baixe o projeto no github :  https://github.com/macoratti/ApiFastReport
 

"Ele (Jesus) deu a si mesmo por nós, a fim de nos remir de toda iniquidade e purificar, para si mesmo, um povo exclusivamente seu, dedicado à prática de boas obras."
Tito 2:14

 

Porque um menino nos nasceu, um filho se nos deu, e o principado está sobre os seus ombros, e se chamará o seu nome: Maravilhoso, Conselheiro, Deus Forte, Pai da Eternidade, Príncipe da Paz.

Isaías 9:6
Porque um menino nos nasceu, um filho se nos deu, e o principado está sobre os seus ombros, e se chamará o seu nome: Maravilhoso, Conselheiro, Deus Forte, Pai da Eternidade, Príncipe da Paz.

Isaías 9:6

Referências:


José Carlos Macoratti