O Report Viewer só tem suporte nativo ao Windows Forms e Web Forms, ou seja, quem trabalha com outras plataformas (como WPF ou MVC) precisa fazer alguns ajustes para poder utilizá-lo nos seus projetos. No caso do WPF, é só adicionar um WindowsFormsHost com o controle do Report Viewer dentro, como eu mostrei neste artigo. Já no ASP.NET MVC, ou adicionamos um WebForm (não recomendado) ou utilizamos uma biblioteca que possibilita a criação dos relatórios no “estilo MVC” de desenvolver.
Eu já escrevi um artigo mostrando como utilizar o Report Viewer no ASP.NET MVC, onde eu mostro as duas modalidades mencionadas acima. Devido à popularidade desse artigo, eu resolvi fazer uma versão em vídeo explorando um pouco mais a ideia da utilização da biblioteca “ReportViewerForMVC“. No vídeo eu mostro também um problema que temos ao utilizá-la com sub-relatórios. Confere aí:
Biblioteca ReportViewerForMVC
A biblioteca que podemos utilizar para trabalharmos com o Report Viewer no MVC (sem termos que adicionar um WebForm manualmente) é a “ReportViewerForMVC“. Como você pode reparar no site da biblioteca no CodePlex, ela não tem sido atualizada há um bom tempo. Porém, ela funciona bem com a versão 11 do Report Viewer, então ela acaba dando conta do recado.
Para adicionarmos uma referência a essa biblioteca no nosso projeto, nós utilizamos o NuGet. Basta procurarmos por “ReportViewerForMVC” na janela de gerenciamento de pacotes do NuGet ou digitarmos “Install-Package ReportViewerForMVC” no Package Manager Console:
Essa biblioteca adicionará a referência às dlls “Microsoft.ReportViewer.WebForms” e “ReportViewerForMvc“.
Outras referências necessárias
Em computadores que tenham a runtime do Report Viewer instalada, somente a referência à biblioteca já é o suficiente para que o nosso projeto funcione. Porém, para o caso em que a versão correta da runtime do Report Viewer não estiver instalada, algumas outras referências serão necessárias.
Por segurança, eu recomendo que você adicione pelo NuGet as referências às bibliotecas “MicrosoftReportViewerWebForms” e “Microsoft.SqlServer.Types” (versão 11.0.0):
O código do Controller
Uma vez adicionadas todas as referências necessárias, vamos partir para a criação do código do nosso Controller. Adicione um novo Controller vazio do MVC na pasta “Controllers” para que possamos fazer essa implementação.
A ideia é muito simples. Primeiramente nós temos que carregar os dados da nossa fonte de dados e armazená-los em um DataSet ou coleção. Em seguida, nós criamos uma instância da classe “Microsoft.Reporting.WebForms.ReportViewer” e configuramos algumas propriedades (como caminho do relatório e sua fonte de dados). Por fim, nós retornamos essa instância de “ReportViewer” através da ViewBag.
Veja só este exemplo:
// C# public ActionResult Index() { var ds = ObterDados(); var viewer = new Microsoft.Reporting.WebForms.ReportViewer(); viewer.ProcessingMode = Microsoft.Reporting.WebForms.ProcessingMode.Local; viewer.LocalReport.ReportPath = Request.MapPath(Request.ApplicationPath) + @"CaminhoDoSeuRelatorio.rdlc"; viewer.LocalReport.DataSources.Add(new Microsoft.Reporting.WebForms.ReportDataSource("NomeDoDataSetNoRelatorio", (System.Data.DataTable)ds.NomeDaDataTable)); ViewBag.ReportViewer = viewer; return View(); }
' VB.NET Dim Ds = ObterDados() Dim Viewer = New Microsoft.Reporting.WebForms.ReportViewer() Viewer.ProcessingMode = Microsoft.Reporting.WebForms.ProcessingMode.Local Viewer.LocalReport.ReportPath = Request.MapPath(Request.ApplicationPath) + "CaminhoDoSeuRelatorio.rdlc" Viewer.LocalReport.DataSources.Add(New Microsoft.Reporting.WebForms.ReportDataSource("NomeDoDataSetNoRelatorio", DirectCast(Ds.NomeDaDataTable, System.Data.DataTable))) ViewBag.ReportViewer = Viewer Return View()
E como fica a View?
Com o Controller em mãos, podemos partir para a criação da nossa View. O código dela é muito simples. Primeiramente nós temos que adicionar uma referência à biblioteca “ReportViewerForMvc” (com uma cláusula “using” no início da View). Adicionada essa referência, nós teremos alguns métodos extras à nossa disposição, como o “Html.ReportViewer“. Ao chamarmos esse método passando a instância do ReportViewer da ViewBag, o relatório será renderizado naquele local:
<!-- C# --> @using ReportViewerForMvc; @{ ViewBag.Title = "Index"; } <h2>Relatório</h2> @Html.ReportViewer(ViewBag.ReportViewer as Microsoft.Reporting.WebForms.ReportViewer)
<!-- VB.NET --> @Imports ReportViewerForMvc @Code ViewData("Title") = "Index" End Code <h2>Index</h2> @Html.ReportViewer(DirectCast(ViewBag.ReportViewer, Microsoft.Reporting.WebForms.ReportViewer))
Execute o projeto e veja o resultado:
Ajuste automático do tamanho do controle
Se observarmos o resultado apresentado na imagem acima, veremos que o controle está com um tamanho fixo (o tamanho padrão). No controle do Report Viewer web, temos a possibilidade de configurarmos um tamanho dinâmico, ou seja, o controle será automaticamente redimensionado dependendo do tamanho do relatório.
Para atingirmos esse resultado, temos que alterar a propriedade “SizeToReportContent” para verdadeiro, além de configurarmos o Width e Height de forma que eles ocupem 100% da área disponível na View. Coloque este código antes de retornar o controle para a ViewBag e veja a diferença:
// C# viewer.SizeToReportContent = true; viewer.Width = System.Web.UI.WebControls.Unit.Percentage(100); viewer.Height = System.Web.UI.WebControls.Unit.Percentage(100);
' VB.NET Viewer.SizeToReportContent = True Viewer.Width = System.Web.UI.WebControls.Unit.Percentage(100) Viewer.Height = System.Web.UI.WebControls.Unit.Percentage(100)
Problemas com sub-relatórios
A biblioteca Report Viewer for MVC funciona muito bem até o momento em que tivermos que trabalhar com sub-relatórios. Para exibirmos um relatório que tenha sub-relatório, o código do Controller ficaria assim:
// C# DataSet ds; public ActionResult Index() { ds = ObterDados(); var viewer = new Microsoft.Reporting.WebForms.ReportViewer(); viewer.ProcessingMode = Microsoft.Reporting.WebForms.ProcessingMode.Local; viewer.LocalReport.ReportPath = Request.MapPath(Request.ApplicationPath) + @"CaminhoDoSeuRelatorio.rdlc"; viewer.LocalReport.DataSources.Add(new Microsoft.Reporting.WebForms.ReportDataSource("NomeDoDataSetNoRelatorio", (System.Data.DataTable)ds.NomeDaDataTable)); viewer.LocalReport.SubreportProcessing += LocalReport_SubreportProcessing; ViewBag.ReportViewer = viewer; return View(); } private void LocalReport_SubreportProcessing(object sender, Microsoft.Reporting.WebForms.SubreportProcessingEventArgs e) { e.DataSources.Add(new Microsoft.Reporting.WebForms.ReportDataSource("NomeDoDataSetNoSubRelatorio", (System.Data.DataTable)ds.NomeDaDataTableDetalhe)); }
' VB.NET Private Ds As DataSet Public Function Index() As ActionResult Ds = ObterDados() Dim Viewer = New Microsoft.Reporting.WebForms.ReportViewer() Viewer.ProcessingMode = Microsoft.Reporting.WebForms.ProcessingMode.Local Viewer.LocalReport.ReportPath = Request.MapPath(Request.ApplicationPath) + "CaminhoDoSeuRelatorio.rdlc" Viewer.LocalReport.DataSources.Add(New Microsoft.Reporting.WebForms.ReportDataSource("NomeDoDataSetNoRelatorio", DirectCast(Ds.NomeDaDataTable, System.Data.DataTable))) AddHandler Viewer.LocalReport.SubreportProcessing, AddressOf LocalReport_SubreportProcessing Viewer.SizeToReportContent = True Viewer.Width = System.Web.UI.WebControls.Unit.Percentage(100) Viewer.Height = System.Web.UI.WebControls.Unit.Percentage(100) ViewBag.ReportViewer = Viewer Return View() End Function Private Sub LocalReport_SubreportProcessing(sender As Object, e As Microsoft.Reporting.WebForms.SubreportProcessingEventArgs) e.DataSources.Add(New Microsoft.Reporting.WebForms.ReportDataSource("NomeDoDataSetNoSubRelatorio", DirectCast(Ds.NomeDaDataTableDetalhe, System.Data.DataTable))) End Sub
Porém, se testarmos esse cenário com um breakpoint no evento “SubReportProcessing“, veremos que ele não será disparado. Isso acontece porque a biblioteca tem um bug que evita o disparo desse evento. Existe até uma “issue” criada no site da biblioteca falando sobre esse problema.
No link acima você pode notar que eu respondi aquela “issue” com a correção necessária para que os sub-relatórios funcionem. Eu fiz essa correção, recompilei a biblioteca e você pode baixar a versão corrigida aqui. Substitua essa dll na pasta “packages” e na pasta “Bin” do seu projeto para que os sub-relatórios funcionem corretamente. E acompanhe este repositório no meu GitHub, onde eu pretendo dar manutenção nessa biblioteca e disponibilizar atualizações.
Baixe o projeto de exemplo
Para baixar o projeto de exemplo desse artigo, assine a minha newsletter. Ao fazer isso, além de ter acesso ao projeto, você receberá um e-mail toda semana sobre o artigo publicado e ficará sabendo também em primeira mão sobre o artigo da próxima semana, além de receber dicas “bônus” que eu só compartilho por e-mail. Inscreva-se utilizando o formulário no final do artigo.
Até a próxima!
André Lima
Photo by Peter Shanks used under Creative Commons
https://pixabay.com/en/startup-start-up-notebooks-creative-593327/
Song Rocket Power Kevin MacLeod (incompetech.com)
Licensed under Creative Commons: By Attribution 3.0 License
http://creativecommons.org/licenses/by/3.0/
The post Trabalhando com o Report Viewer no MVC appeared first on André Alves de Lima.