First, create a MVC application project, and
then create InvoiceHeader class and InvoiceDetails class inside your model folder as below.
public class InvoiceHeader
{
public int InvoiceId
{ get; set; }
public string
InvoiceNo { get; set;
}
public string
AccountNo { get; set;
}
public string
CustomerName { get; set;
}
public string
BillingAddress { get; set;
}
public DateTime
InvoicedDate { get; set;
}
public decimal
SubTotal{get;set;}
public decimal
DiscountAmount { get; set;
}
public decimal
TaxAmount { get; set;
}
private decimal
_InvoiceAmount;
public Decimal
InvoiceAmount
{
get
{
_InvoiceAmount = SubTotal - DiscountAmount + TaxAmount;
return _InvoiceAmount;
}
set
{
if (_InvoiceAmount == 0)
_InvoiceAmount = 0.0M;
else
_InvoiceAmount = value;
}
}
public List<InvoiceDetails> Details { get; set; }
}
public class InvoiceDetails
{
public int InvoiceId
{ get; set; }
public int ItemID { get; set; }
public string
ItemCode { get; set;
}
public string
Description { get; set;
}
public decimal
UnitPrice { get; set;
}
public int Quantity {
get; set; }
public decimal
DiscountAmount { get; set;
}
public decimal
TaxAmount { get; set;
}
public decimal
TotalAmount { get; set;
}
}
Then
create a file named “InvoiceDAL.cs” inside a
folder called DAL. There i have added a method called getAllInvoices() to
get invoice data .I just put some dummy data and return a list of invoices to
show in crystal report .
public List<InvoiceHeader> getAllInvoices()
{
List<InvoiceHeader>
invoiceList = new List<InvoiceHeader>();
//here add some invoice headers with invoice details
//You can download the source code and find this file if you want
//invoiceList.Add(new InvoiceHeader{InvoiceId=1,
.....,,Details=detailslist.....)
return invoiceList;
}
You can get data from database as you want.
Here i want to show how to create a crystal report in MVC. So i am not
going to make this demo with database connections etc. But i am following MVC architecture
well.
After creating model class and data layer
,create a folder named "Reports" inside the solution and add new data
set item .(right click the folder->add ->new item ->select DataSet
from the dialog window) name it as InvoiceDtSet.xsd .This is the custom data
set which we are going to map with crystal report later.
Then add two data tables (InvoiceHeaderTbl
and InvoiceDetailsTbl) to InvoiceDtSet dataset and add columns as you want to
show in crystal report. Make sure to put correct data types for columns. (Right
click column ->properties ->change Data type property)
Data set should looks like this.
Here we can put relationship between tables .But it s not necessary.
Then
create a controller. I have named it as reportController.cs .Then create a
action method inside it and create a view where you want to put a button to
show crystal report.
public ActionResult Index()
{
return
View();
}
In the "Index.aspx" view page put this code lines to create a button and "PrintInvoice()" java script method.
<label>Click here to get all invoices</label>
<input type="button" onclick="PrintInvoice()" value="Print"/>
<script type="text/javascript">function PrintInvoice(){$.ajax({url: '<%=ResolveUrl("~/")%>Reports/InvoicePrint',//data: JSON.stringify(oParam),if you want to pass data you can pass as json object heretype: 'POST',contentType: 'application/json;',dataType: 'json',success: function () {window.open("<%=ResolveUrl("~/")%>Reports/MyInvoices.aspx");}});}</script>
I assume you have good javascript/jquery
knowledge .Here I have implemented Ajax request to get data by server side
controller.
Then add these two methods to your “reportcontroller”.
Here what i am doing is filling the
data set and put it in to the session.
///
<summary>
///puting filled dataset in
to session
/// </summary>
public void
InvoicePrint()
{
this.HttpContext.Session["rptSource"]
= getInvoice();
}
/// <summary>
/// This method is for
getting invoices and filling the dataset which we are going to asign to the crystal
report
/// </summary>
/// <returns></returns>
private DataSet
getInvoice()
{
InvoiceDtSet invdt = new
InvoiceDtSet();
try
{
InvoiceDAL dal = new InvoiceDAL();
List<InvoiceHeader>
results = dal.getAllInvoices();
results = results.OrderByDescending(x => x.InvoiceNo).ToList();
foreach (InvoiceHeader
inv in results)
{
/// filling invoiceheader data table
invdt.InvoiceHeaderTbl.AddInvoiceHeaderTblRow(inv.InvoiceId, inv.InvoiceNo, inv.AccountNo, inv.CustomerName, inv.BillingAddress, inv.InvoicedDate, inv.SubTotal, inv.DiscountAmount, inv.TaxAmount, inv.InvoiceAmount);
if (inv.Details != null && inv.Details.Count > 0)
{
foreach (InvoiceDetails invDet in inv.Details)
{
/// filling invoiceDetails data table
/// filling invoiceDetails data table
invdt.InvoiceDetailsTbl.AddInvoiceDetailsTblRow(invDet.InvoiceId, invDet.ItemID, invDet.ItemCode, invDet.Description, invDet.UnitPrice,
invDet.Quantity, invDet.DiscountAmount, invDet.TaxAmount,
invDet.TotalAmount);
}
}
}
}
catch (Exception
ex)
{
throw new
Exception(ex.Message);
}
return invdt;
}
Then create a new web form inside Reports
folder. Name it as "MyInvoices.aspx".Drag a "crystal report
viewer control" from tool box and put it to
"MyInvoices.aspx" and go to its code behind file. "Page_Load”
event should like this.
**Note: You must have install Crystal
reports in your computer.
**Note: You must add references to
CrystalDecisions.CrystalReports.Engine (It is under References->.Net )
using System;using System.Collections.Generic;using System.Linq;using System.Web;using System.Web.UI;using System.Web.UI.WebControls;using CrystalDecisions.CrystalReports.Engine;namespace crystalreportswithMvc.Reports{public partial class MyInvoices : System.Web.UI.Page{protected void Page_Load(object sender, EventArgs e){InvoiceDtSet rptSource = (InvoiceDtSet)System.Web.HttpContext.Current.Session["rptSource"];ReportDocument rptDoc = new ReportDocument();// Your .rpt file path will be belowrptDoc.Load(Server.MapPath("~/Reports/InvoiceReport.rpt"));//set dataset to the report viewer.rptDoc.SetDataSource(rptSource);InvoiceViewver.ReportSource = rptDoc;}}}
Here what i am doing is taking the dataset which i put earlier in to the session "rptSource" and assigning it as data source to the report document.
rptDoc.Load(Server.MapPath("~/Reports/InvoiceReport.rpt"));
This line of code loads the crystal report to report document.
And then report document is assigned as the crystal report viewer control's report source. "InvoiceViewver" is the name of crystal report viewer control in the web form.
InvoiceViewver.ReportSource = rptDoc;**Note: Be careful with paths/URLs of files**
So far we didn't create a crystal report.
Now add a new crystal report item under Reports folder and name it as
"InvoiceReport.rpt". Then choose crystal report wizard and then choose
the data source under "project Data ->ADO.net DataSet" .You have
to choose the data set which we have already created ("InvoiceDtSet").
Then choose both tables InvoiceHeaderTbl and InvoiceDetailsTbl and finish.
Now we have a crystal report bound
with our dataset. Then drag and drop fields from Field Explorer ->database
fields-> invoiceHeaderTbl as you want. You can design the report view as you
wish.(I am not going to explain how to design crystal report here because here
i am talking only about integration of crystal report with MVC. )
This picture depicts the arrangement of invoiceHeadertbl fields.
**Then right click on a section and go to
section expert and choose details section, go to Paging tab and put a tick in
front of ”end of section" property. If you don't do this all invoices
will show in a one page.
How add a sub report inside crystal report to show invoice item details?
Right click in the middle of the details
section and choose insert -> subreport .This sub report is to show invoice
item details. In the dialog box appeared choose "Create a sub report with
the report wizard” option and put a name for the sub report and click report
wizard button. Then select “InvoiceDetailsTbl” and click finish.
Then right click on sub report and click
edit sub report and design the invoice details as you want. Below picture will
show the arrangement of the sub report.
Then
we have to link invoiceheader and invoiceDetils by InvoiceID. To do this right
clicks on subreport in main report ->Choose "change subreport links”. Then
in the dialog box choose the field to link from invoiceHeaderTbl and choose
matching field from subreport to link.
Now one InvoiceHeader shows only related InvoiceDetails in report
view.
Ok, now you can run your project and go to the relevant
action method and click on the button created and view the crystal report
.According to above code example go to
"http://localhost:62848/reports/index"(port may vary) and click
"print" button.
You will see the crystal report like this.
**Only thing you have to remember is to
link sub report and main report carefully.
Difference between Asp.net web forms and
MVC in integration of crystal report is in MVC we have to create separate “.aspx”
page and load it using a java script. We have to do this because MVC does not
have events to fire.
If you want to load crystal report in the
same page (Page with the print button -index.aspx) only thing you have to do is
create an Iframe and set its src to the "/Reports/MyInvoices.aspx".To do this you have to change the
java script little bit.
<iframe id="ReportFrame" src="" width="100%" height="1000px" style="border:none">
</iframe>
<script type="text/javascript">
function PrintInvoice()
{
$.ajax({
url: '<%=ResolveUrl("~/")%>Reports/InvoicePrint',
//data: JSON.stringify(oParam),if you want to pass data you can pass as json object here
type: 'POST',
contentType: 'application/json;',
dataType: 'json',
success: function () {
$("#ReportFrame").attr("src"," <%=ResolveUrl("~/")%>Reports/MyInvoices.aspx"); }
});
}
</script>
<iframe id="ReportFrame" src="" width="100%" height="1000px" style="border:none">
</iframe>
<script type="text/javascript">
function PrintInvoice()
{
$.ajax({
url: '<%=ResolveUrl("~/")%>Reports/InvoicePrint',
//data: JSON.stringify(oParam),if you want to pass data you can pass as json object here
type: 'POST',
contentType: 'application/json;',
dataType: 'json',
success: function () {
$("#ReportFrame").attr("src"," <%=ResolveUrl("~/")%>Reports/MyInvoices.aspx"); }
});
}
</script>
Hope you got an idea about integration of
crystal reports on MVC framework well. You can download the source code of this
example from below link .If you have any question or comments about this
article please feel free to post them as comments.
(Go to the above link and choose File->download to download the
zip file)
Good post. Keep it up.
ReplyDeletenice work,this is good blog which help for anyone who work with the MVC, crystal Report
ReplyDeleteThumbs up
ReplyDeletegood work ..
ReplyDeleteGood work, Keep it up. :)
ReplyDeleteGreat ! keep it up
ReplyDeleteThanx all
ReplyDeleteI don't understand it because I am not familiar with either .NET/ CrystalReport. But I see it's useful for someone who might be struggling for hours to get their report working.
ReplyDeleteKeep up the good work!
This comment has been removed by the author.
ReplyDeleteThanx shakunthala, There are some blog posts regarding OOP in here ,may be you can understand them ,bcz they are language independent.
ReplyDeleteGood Start ! keep it up
ReplyDeleteGreat.. Keep it up!
ReplyDeleteAny one can help me , when i added the webform to my mvc project .
ReplyDeletei cant able to edit the webform designer.
Did you try to click on Design button in the bottom of the page?
ReplyDeleteI am having difficulty also I am new to mvc that "Index.aspx" to mean "Index.cshtml can define
ReplyDeletea view with an aspx from your controller
No, You just need to add a new .aspx page which like in web forms.Because in MVC we dnt work on controls like web forms.So in this situation we need to have a web form which we can put a Cristal report viewer control.That why here we use an .aspx page.no need to put controller action method.Just put a normal web form and put Cristal report viewer control
DeleteGreat article.
ReplyDeleteThanks for sharing!
Do you have another example but using entity framework and crystal reports?
DeleteHow to display crystal report viewer toolbar menu?
ReplyDeleteThank you
Hi,Miss Darshani:I successfully build my own cystal reports , but in my case,Ican't get
ReplyDeletethe correct result page using POST to submit the ajax call,so I modify it to GET, it worked, and continue to put the report page into the Iframe . during the debugging, also encounted the javacript bobj not defined error. after searching the web solved it . thank u for your post, can you give me some ideas as how to submit parameters using $.ajax get/post to the controller? btw, I'm now using EF6 code first and MVC5, due to crystal report , I had to create some views in LocalDB (can We do by EF6's entity view model?) , and drag them to XSD desinger , in controller , using LINQ to entities to get the result DATASETs to feed the report source,
--- this is GET version, Why POST didn't work? ---
function PrintCheduiRoutesDetails()
{
$.ajax({
url: '/report/cheduiRoutesPrint',
type: 'GET',
success: function () {
$("#ReportFrame").attr("src","/Webform/cheduiRoutesDetails.aspx");
}
});
}
-------
Have a good day!
Thank you very much! Very understandable and helpful to me
ReplyDeleteAll these are aspx pages where do the MVC goes ?
ReplyDeletebut i want generate crystal report without using web forms (.aspx file)
ReplyDeletehttps://stackoverflow.com/questions/22247272/using-crystal-report-in-mvcasp-net-application-not-using-aspx-file
DeleteShort answer: You can't if you want to use the report viewer.
very very thanks i was searching this topic from 2 days finally i got it
ReplyDeleteThanks a lot for sharing this with all folks you really recognise what you are talking about! Bookmarked. Kindly additionally seek advice from my website =). We can have a hyperlink trade arrangement among us
ReplyDeletewhoah this weblog is excellent i like reading your posts. Keep up the great work! You know, a lot of individuals are searching round for this info, you could help them greatly.
ReplyDeleteMerkur 200% Situs Judi Slot Online Terpercaya No 1 di
ReplyDeleteMerkur deposit via pulsa 5000 merupakan provider yang sudah keuntungan dimainkan bonus seperti 메리트 카지노 주소 Slot Online, poker online, domino online, dana, menangkita, Rating: 97% · 5,755,861 kadangpintar votes หาเงินออนไลน์