Step by Step adding an RDLC report to MVC4 project
For any large project, reports will be needed. I love RDLC so I’m sticking with them. I had some problems in the beginning but with some search here and there and some testing it start working. So I will describe it from the beginning.
For any large project, reports will be needed. I love RDLC so I’m sticking with them. I had some problems in the beginning but with some search here and there and some testing it start working. So I will describe it from the beginning.
Requirements:
·
In my new MVC I need to
have a number of RDLC reports
·
I need the reports to read
from objects, direct entities or report objects (for large reports I prefer to something
like a Report View Model, in the end a report is view for data)
·
A report my require one or
more data sets
·
Some of the reports will
need parameters that the user will select from the MVC pages
·
I want to export the report
by PDF, but having word and Excel would
be an advantage
·
Some report standardization
point that is needed:
o
Required reports have a description
title
o
Required have right and
left main and sub headers
o
Required to have the user name
printing the report in the footer
o
Required to have the
printing date on the footer
o
Required to have number of
page and total pages in the footer
o
All the reports are A4
stander reports ready for printing.
o
Reports will be multi language
(currently English and Arabic)
o
Reports may contain charts
and bars
o
Reports need to be secure
·
The system contains an
alert module and some of the requirement needs the PDF document to be attached
to the email.
So lets start clean and from the beginning.
Lunching Visual Studio, selecting new project
Selecting MVC4, intrenet application (all template will work
too)
Adding a new project with the name: ASPNET_MVC_RDLC
I will start putting it all in one project; it’s the same if
you have business and data access layers that are in separate projects too, only to make it short im putting it all together and skipping testing too.
1: using System;
2: using System.Collections.Generic;
3: using System.Linq;
4: using System.Web;
5: using Microsoft.Reporting.WebForms;
6: using System.Web;
7: using System.Web.Mvc;
8:
9: namespace ASPNET_MVC_RDLC.Models
10: {
11: public class ReportViewModel
12: {
13: public enum ReportFormat { PDF=1,Word=2,Excel=3}
14: public ReportViewModel()
15: {
16: //initation for the data set holder
17: ReportDataSets = new List<ReportDataSet>();
18: }
19:
20: //Name of the report
21: public string Name { get; set; }
22:
23: //Language of the report
24: public string ReportLanguage { get; set; }
25:
26: //Reference to the RDLC file that contain the report definition
27: public string FileName { get; set; }
28:
29: //The main title for the reprt
30: public string ReportTitle { get; set; }
31:
32: //The right and left titles and sub title for the report
33: public string RightMainTitle { get; set; }
34: public string RightSubTitle { get; set; }
35: public string LeftMainTitle { get; set; }
36: public string LeftSubTitle { get; set; }
37:
38: //the url for the logo,
39: public string ReportLogo { get; set; }
40:
41: //date for printing the report
42: public DateTime ReportDate { get; set; }
43:
44: //the user name that is printing the report
45: public string UserNamPrinting { get; set; }
46:
47: //dataset holder
48: public List<ReportDataSet> ReportDataSets { get; set; }
49:
50: //report format needed
51: public ReportFormat Format { get; set; }
52: public bool ViewAsAttachment { get; set; }
53:
54: //an helper class to store the data for each report data set
55: public class ReportDataSet
56: {
57: public string DatasetName { get; set; }
58: public List<object> DataSetData { get; set; }
59: }
60:
61: public string ReporExportFileName { get {
62: return string.Format("attachment; filename={0}.{1}", this.ReportTitle, ReporExportExtention);
63: } }
64: public string ReporExportExtention
65: {
66: get
67: {
68: switch (this.Format)
69: {
70: case ReportViewModel.ReportFormat.Word: return ".doc";
71: case ReportViewModel.ReportFormat.Excel: return ".xls";
72: default:
73: return ".pdf";
74: }
75: }
76: }
77:
78: public string LastmimeType
79: {
80: get
81: {
82: return mimeType;
83: }
84: }
85: private string mimeType;
86: public byte[] RenderReport()
87: {
88: //geting repot data from the business object
89:
90: //creating a new report and setting its path
91: LocalReport localReport = new LocalReport();
92: localReport.ReportPath =System.Web.HttpContext.Current.Server.MapPath(this.FileName);
93:
94: //adding the reort datasets with there names
95: foreach (var dataset in this.ReportDataSets)
96: {
97: ReportDataSource reportDataSource = new ReportDataSource(dataset.DatasetName, dataset.DataSetData);
98: localReport.DataSources.Add(reportDataSource);
99: }
100: //enabeling external images
101: localReport.EnableExternalImages = true;
102:
103: //seting the partameters for the report
104: localReport.SetParameters(new ReportParameter("RightMainTitle", this.RightMainTitle));
105: localReport.SetParameters(new ReportParameter("RightSubTitle", this.RightSubTitle));
106: localReport.SetParameters(new ReportParameter("LeftMainTitle", this.LeftMainTitle));
107: localReport.SetParameters(new ReportParameter("LeftSubTitle", this.LeftSubTitle));
108: localReport.SetParameters(new ReportParameter("ReportTitle", this.ReportTitle));
109: localReport.SetParameters(new ReportParameter("ReportLogo", System.Web.HttpContext.Current.Server.MapPath(this.ReportLogo)));
110: localReport.SetParameters(new ReportParameter("ReportDate", this.ReportDate.ToShortDateString()));
111: localReport.SetParameters(new ReportParameter("UserNamPrinting", this.UserNamPrinting));
112:
113: //preparing to render the report
114:
115: string reportType = this.Format.ToString();
116:
117: string encoding;
118: string fileNameExtension;
119:
120: //The DeviceInfo settings should be changed based on the reportType
121: //http://msdn2.microsoft.com/en-us/library/ms155397.aspx
122: string deviceInfo =
123: "<DeviceInfo>" +
124: " <OutputFormat>" + this.Format.ToString() + "</OutputFormat>" +
125: "</DeviceInfo>";
126:
127: Warning[] warnings;
128: string[] streams;
129: byte[] renderedBytes;
130:
131: //Render the report
132: renderedBytes = localReport.Render(
133: reportType,
134: deviceInfo,
135: out mimeType,
136: out encoding,
137: out fileNameExtension,
138: out streams,
139: out warnings);
140:
141: return renderedBytes;
142: }
143: }
144:
145: }
lets add a new report called MyMVCReport.rdlc as
below:
we will need to add some stub methods to set the report data sources
Set the data source for the report using the stub methods
1: using System;
2: using System.Collections.Generic;
3: using System.Linq;
4: using System.Web;
5:
6: namespace ASPNET_MVC_RDLC.Models
7: {
8: public class Business
9: {
10: public List<Employee> StubForEmployeeDataSet()
11: {
12: //this is used only to help in adding the dataset of type employee to the report definition
13: return null;
14: }
15: public List<Project> StubForProjectDataSet()
16: {
17: //this is used only to help in adding the dataset of type project to the report definition
18: return null;
19: }
Set the data source for the report using the stub methods
so we have a problem here when selecting add data set from the report menu, the data source drop down list is empty, and when you click new it open a connection to the database.
So after some search I found a solution from stackoverflow, simply add a web form page to the MVC project and it will start working, I didn't have time to check why is this, but it works.
lets add another one.
lets set the design and layout of the report
the above is only for testing.
coming near the last steps , we need to add a reference to the Microsoft web form reports assembly
now lets add the controller that will produce the report.
1: using System;
2: using System.Collections.Generic;
3: using System.Linq;
4: using System.Web;
5: using System.Web.Mvc;
6: using ASPNET_MVC_RDLC.Models;
7:
8: namespace ASPNET_MVC_RDLC.Controllers
9: {
10: public class ReportController : Controller
11: {
12: public ActionResult PrintRepert()
13: {
14: //geting repot data from the business object
15: var Business = new Business();
16: var reportViewModel = Business.GetMyRepoertViewModel();
17:
18: var renderedBytes = reportViewModel.RenderReport();
19:
20: if(reportViewModel.ViewAsAttachment)
21: Response.AddHeader("content-disposition", reportViewModel.ReporExportFileName);
22: return File(renderedBytes, reportViewModel.LastmimeType);
23:
24: }
25:
26: }
27: }
Add a link to the page to open the report wherever is needed.
@{
ViewBag.Title = "Home Page";
}
@section
featured {
<section class="featured">
<div class="content-wrapper">
<hgroup class="title">
<h1>@ViewBag.Title.h1>
<h2>@ViewBag.Messageh2>
hgroup>
div>
section>
}
<h3>We suggest the following:h3>
<ol class="round">
<li class="one">
<h5>Print an RDLC report in MVCh5>
@Html.ActionLink("Print
Report", "PrintRepert","Report")
li>
ol>
ok lets run and see.
And its working, there still more work to be done as checking the other formats, the email attachment,
adding some security, the Multilanguage, and uploading this example and linking it here.
I would love to here some comments.
1:
2: namespace ASPNET_MVC_RDLC.Models
3: {
4: public class Business
5: {
6: public List<Employee> StubForEmployeeDataSet()
7: {
8: //this is used only to help in adding the dataset of type employee to the report definition
9: return null;
10: }
11: public List<Project> StubForProjectDataSet()
12: {
13: //this is used only to help in adding the dataset of type project to the report definition
14: return null;
15: }
16: //somew
17: public ReportViewModel GetMyRepoertViewModel()
18: {
19: // I will not go through getting data from ef, i will assume some test data here
20:
21: //first dataset, employee info
22: var EmplyeeDataSet =new List<object>() {
23: new Employee() { Name="Ahmed Khaled", Mobile = "055111111", Email="Ahmed.Khaled@Somewhere.com", BirthDate=new DateTime(1970,10,10)},
24: new Employee() { Name="Jamal Awsom" , Mobile = "055222222", Email="Jamal.Awsom@Somewhere.com", BirthDate=new DateTime(1977,1,10)},
25: new Employee() { Name="James Salem" , Mobile = "055333333", Email="James.Salem@Somewhere.com", BirthDate=new DateTime(1982,12,10)},
26: new Employee() { Name="Tony Read" , Mobile = "055444444", Email="Tony.Read@Somewhere.com", BirthDate=new DateTime(1982,4,10)}
27:
28: };
29: var ProjectDataSet =new List<object>() ;
30: for (int i=1;i<30;i++)
31: {
32: EmplyeeDataSet.Add(new Employee() { Name = "James Salem", Mobile = "055333333",
33: Email = "James.Salem@Somewhere.com", BirthDate = new DateTime(1982, 12, 10) });
34: }
35:
36: //Assuming the person printing the report is me
37: var UserPrinting="Ali Taki";
38:
39: var reportViewModel = new ReportViewModel()
40: {
41: FileName = "~/Reprots/MyMVCReport2.rdlc",
42: LeftMainTitle = "ABC Company Name",
43: LeftSubTitle = "DEF Department Name",
44: RightMainTitle = "اسم الشركة",
45: RightSubTitle = "اسم القسم",
46: Name = "Statistical Report",
47: ReportDate = DateTime.Now,
48: ReportLogo = "~/Content/logo.jpg",
49: ReportTitle = "Summary report for top employee's and projects",
50: ReportLanguage = "en-US",
51: UserNamPrinting = UserPrinting,
52: Format=ReportViewModel.ReportFormat.PDF,
53: ViewAsAttachment=false,
54:
55: };
56: //adding the dataset information to the report view model object
57: reportViewModel.ReportDataSets.Add(new ReportViewModel.ReportDataSet() { DataSetData = EmplyeeDataSet.ToList(), DatasetName = "Employees" });
58: reportViewModel.ReportDataSets.Add(new ReportViewModel.ReportDataSet() { DataSetData = ProjectDataSet.ToList(), DatasetName = "Projects" });
59:
60:
61: return reportViewModel;
62:
63: }
64: }
65: }
Can you elaborate on this:
ReplyDeleteBusiness.GetMyRepoertViewModel();
You didnt post this method
Thanks
can you post this method:
ReplyDeleteBusiness.GetMyRepoertViewModel();
can you post the code for:
ReplyDeletevar reportViewModel = Business.GetMyRepoertViewModel();
Or show all of the business class including the getmyreportviewmodel method.
Thanks
Nice post,it was very simple to follow, could´nt see the result because of the missing part of the business class, if u can please post it!!
ReplyDeleteThanks
I updated the post to add the business class, I will update a full solution file for download soon for my examples, very sorry for the delay.
ReplyDeleteDo you have a full solution file for download now?
DeleteThanks!
Do you have a full solution file for download now?
DeleteThanks!
Where is the solution for download ?
DeleteTIA.
Is there a way to not have the report take up the whole browser screen? I'd still like my header and menu to still display and the report to simply replace the boyd of my _Layout.cshtml.
ReplyDeleteExcellent post BTW. Works as advertised...
yes use a Html iframe
DeleteHello, I have followed the tutorial, but I have an error on the part of renderdBytes, the error reads:
ReplyDelete"An error occurred locally During report processing"
These lines at:
localReport.Render renderedBytes = (
reportType,
deviceInfo,
out mimeType,
out encoding,
fileNameExtension out,
out streams,
out warnings);
and not due to that, if I would have thought Algua helpful.
regards
hi, this mean that there is a problem with the report itself, most common issues can include:
Delete-- not providing the parameters (or parameter names are not correct)
-- no providing the correct datasets, missing dataset or incorrect names
hope this help.
Hello,
ReplyDeleteThanks for your post.
I have a question.What does it mean stub method?
why and when we can use this?
Thanks
ReplyDeleteI have a question, is possible to get value of navigation properties in the report (rdlc)?
yes get them by the MVC code and send them as parameter to the report
DeleteAfter adding Web.Form why Data Source is available. Please let me know.
ReplyDeleteHello, Thanks, very helpful for me as a newbie.
ReplyDeleteBut i have problem getting data from ef, can you post sample about that
It would be kind of you if you can give a sample solution to download :)
ReplyDeleteIndeed, this subject reamains hot and very actual more than a year after...
could you please post your complete source file...waiting for ur reply
ReplyDeleteFound this very useful today - thanks for the post.
ReplyDeletehi very very good
ReplyDeleteplease sample download
Excelent post, you saved me
ReplyDeleteVery nice post man, greetings
ReplyDeleteCan we use ReportViewer control in MVC Application ?
ReplyDeleteYes, if you read the title "RDLC Reports in MVC Web application", This was for ASP MVC applications
DeleteExcelent Post Ali Taki, thank you so much for this tutorial it really helped me a lot!
ReplyDeleteGreat stuff, this has really helped me, thank you.
ReplyDeleteWhen I deploy to server not work, de dlls are correct in the bin folder. I need to install something in the server?
ReplyDeleteThis article helped me a lot. I was having trouble getting to display the values sent through view models in my report and spend the whole weekend with no result. It took me some time to understand this article fully as it is goes back and forth anyhow It is a great article and Thank you for publishing this.
ReplyDeleteHaving problems (same error icon at the logo) when I'm trying to see the logo.
ReplyDeleteRDLC - > external image -> [@Logo]
I enable external images -> viewer.LocalReport.EnableExternalImages = true;
Set the parameter with Server.MapPath(logopath);
Render the report into pdf/xls
Anyone knows why?
Has anyone had any problems publishing a MVC app with rdlc reports to a production iis server? I have been able to get the reports working well but when I deploy the application to another server, first the ReportViewer dlls don't copy to the server in spite of setting copy local, and when I manually copy those files to the server I get the error:
ReplyDeleteCould not load file or assembly 'Microsoft.ReportViewer.ProcessingObjectModel, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' or one of its dependencies. The system cannot find the file specified.
Looking at the event viewer on the server the error reads:
Could not load file or assembly 'Microsoft.ReportingServices.ProcessingObjectModel' or one of its dependencies. An attempt was made to load a program with an incorrect format.
This looks like it might be a version mismatch.
Any thoughts from others about this?
will you will need to download and install the Microsoft report viewer redistributable (with the version that you are using) this will be good if you have a VPS and have a lot of web apps, or get the main DLL files and add them to your bin if you have one web site with reports or on a shared hosting plan.
Delete