Crystal Reporting in MVC 4

Problem:

Problem statement is fairly simple that is how one can use crystal reports using MVC 4 framework using database records?

Solution:

Solution to that issue in not entirely my finding, i find couple of good examples on internet and mix them to obtained my required result, here is how it went down.

1. Adding a folder in mvc project for crystal reports:

You can place you reports on root if you like to but it is good to create a separate folder for these. MVC project did't contain it by default so you have to add it by yourself.
Inside this folder i further create the sub-folders for every single report, if you got single report then you don't have to but again it is good way to divide things.


After creating folder for a report, you have to add two items for each report, those are:
i. Data Set
ii. Crystal Report

In Data Set you have to create a table or more than tables as par your needs those will be bonded with crystal report.
In Crystal report  you design your report and place the columns of data set you already bonded with.

2. Adding property class for every report in Models folder:

After doing above you have to create a class which contains the properties for Data-Set's columns you already defined. Remember type of the property and column should be same. 

Along with defining properties you will write a method that will return the records for the report.
Those can be hard-coded that is my case or you can call the DB here to get records from there, point is you have to convert those records in type of List<> of this class like below:

public List<BucketPurchaseandStock> GetData()
        {
            _BucketPASList = new List<BucketPurchaseandStock>();

            _BucketPASList.Add(new BucketPurchaseandStock() { MovementType = "501", TransactionDate = DateTime.Now.ToString("yyyyMMdd"), DocumentDate = DateTime.Now.ToString("yyyyMMdd"), BusinessDomain = "0008", Material = "PC200LC     8  PSO00020", Description = "PC200LC     8  PSO00020", PointCode = "2B400", Units = 1, Plant = "0008", StockLocation = "W000", MaterialCode = 2, Amount = 654603, PrintDate = DateTime.Now.Date.ToString("dd-MMM-yyyy") });

            _BucketPASList.Add(new BucketPurchaseandStock() { MovementType = "501", TransactionDate = DateTime.Now.ToString("yyyyMMdd"), DocumentDate = DateTime.Now.ToString("yyyyMMdd"), BusinessDomain = "0008", Material = "PC200LC     8  PSO00021", Description = "PC200LC     8  PSO00021", PointCode = "2B400", Units = 1, Plant = "0008", StockLocation = "W000", MaterialCode = 2, Amount = 654603, PrintDate = DateTime.Now.Date.ToString("dd-MMM-yyyy") });

            _BucketPASList.Add(new BucketPurchaseandStock() { MovementType = "501", TransactionDate = DateTime.Now.ToString("yyyyMMdd"), DocumentDate = DateTime.Now.ToString("yyyyMMdd"), BusinessDomain = "0008", Material = "PC200LC     8  PSO00022", Description = "PC200LC     8  PSO00022", PointCode = "2B400", Units = 1, Plant = "0008", StockLocation = "W000", MaterialCode = 2, Amount = 654603, PrintDate = DateTime.Now.Date.ToString("dd-MMM-yyyy") });

            _BucketPASList.Add(new BucketPurchaseandStock() { MovementType = "501", TransactionDate = DateTime.Now.ToString("yyyyMMdd"), DocumentDate = DateTime.Now.ToString("yyyyMMdd"), BusinessDomain = "0008", Material = "PC200LC     8  PSO00023", Description = "PC200LC     8  PSO00023", PointCode = "2B400", Units = 1, Plant = "0008", StockLocation = "W000", MaterialCode = 2, Amount = 654603, PrintDate = DateTime.Now.Date.ToString("dd-MMM-yyyy") });

            _BucketPASList.Add(new BucketPurchaseandStock() { MovementType = "501", TransactionDate = DateTime.Now.ToString("yyyyMMdd"), DocumentDate = DateTime.Now.ToString("yyyyMMdd"), BusinessDomain = "0008", Material = "PC200LC     8  PSO00024", Description = "PC200LC     8  PSO00024", PointCode = "2B400", Units = 1, Plant = "0008", StockLocation = "W000", MaterialCode = 2, Amount = 654603, PrintDate = DateTime.Now.Date.ToString("dd-MMM-yyyy") });

            _BucketPASList.Add(new BucketPurchaseandStock() { MovementType = "501", TransactionDate = DateTime.Now.ToString("yyyyMMdd"), DocumentDate = DateTime.Now.ToString("yyyyMMdd"), BusinessDomain = "0008", Material = "PC200LC     8  PSO00025", Description = "PC200LC     8  PSO00025", PointCode = "2B400", Units = 1, Plant = "0008", StockLocation = "W000", MaterialCode = 2, Amount = 654603, PrintDate = DateTime.Now.Date.ToString("dd-MMM-yyyy") });

            return _BucketPASList;
        }

3. Adding a Web Form in project:

Now you will add a web form in your project, you can add it anywhere but i added it on root as one web form is enough to display as many reports as you needed.


You have to add CrystalReportViewer to your web page and your report path in web page's PageLoad event.

Below code written in Web Form PageLoad event:

if (string.Equals(Session["ReportName"].ToString(), "BucketPASReport", StringComparison.InvariantCultureIgnoreCase))
            {
                BucketPASDataSet rptSource = (BucketPASDataSet)System.Web.HttpContext.Current.Session["ReportDS"];
                ReportDocument rptDoc = new ReportDocument();
                // Your .rpt file path will be below
                rptDoc.Load(Server.MapPath("~/CrystalReports/BucketPASReport/crBucketPAS.rpt"));
                //set dataset to the report viewer.
                rptDoc.SetDataSource(rptSource);
                crvReport.ReportSource = rptDoc;
            }

In above lines, i am using report identifier to point out the report i need to show. Report Data and its identifier are added in Session in next step.


 4. Writing method in Controller:

Next step is to write a method in your controller that should be hit on let's say "Print" button click event, i am using JQuery to achieve this. In this method you do this:

i. Create an instance of your report data set.
ii. Create the class instance whose method will return the data
iii. Storing this data in session along with identifier
iv. Redirecting to you .aspx page.

public JavaScriptResult ExportReportPAS()
        {
            //  create an instance of apropriate class
            BucketPurchasedAndStocked clsObj = new BucketPurchasedAndStocked();
            List<BucketPurchasedAndStocked> dataList = clsObj.AddDataToList();

            //  creating an instance of required data set
            BucketPASDataSet dataSet = new BucketPASDataSet();

            foreach (BucketPurchasedAndStocked lstObj in dataList)
            {
                dataSet.DTBucketPAS.AddDTBucketPASRow(lstObj.MaterialType, lstObj.Material, lstObj.Amount.ToString(), lstObj.Plant, lstObj.PrintDate);

            }

            //  store this data set and its name in session
            Session["ReportDS"] = dataSet;
            Session["ReportName"] = "BucketPASReport";

            //  java script will call the redirect function that will open report in new window
            return JavaScript("redirect()");
        }

5. Methods needed in View:

View, where you place the Print button, you need to add below methods in script section:

/*Evants and Methods*/
    // on Print
    function Print() 
    {
            $.post("@Url.Action("ExportReportToSession", "R01S010")",{},function(data) { });
    }

    //on Redirect  
    function redirect()
    {
        window.open("../ViewReport.aspx", "ReportWindow", "width=1024,height=700,left=80,top=300, scrollbars=yes,resizable=yes"); 
    }

Suggestions and questions are warmly welcome !

Popular Posts