Nine MVP's Blog

03/05/2012

ASP.NET MVC Series: Report Report and Report!

Filed under: ASP.NET MVC — Tags: , , , — Nine MVP @ 11:56 pm

เป็นปัญหาและคำถามเกิดขึ้นมากมาย เมื่อสาวก ASP.NET MVC จะทำรายงาน  เนื่องจากเจ้า ASP.NET MVC View Engine อย่าง Razor นั้นไม่รองรับ ReportViewer Control เพราะเจ้านี่เป็น asp.net server control นั้นเอง แต่ก็ไม่ได้เป็นปัญหาโลกแตกไม่มีคำตอบและทางแก้ไขซะทีเดียวไป

โดยปกติแล้วเราสร้างรายงานได้โดยวิธีใดบ้าง

1. ใช้ Reporting Tool อย่างเช่น Report Client (rdlc), Reporting Services (rdl), Crystal Report (rpt), 3rd Party Report tool

2. Custom report อาจจะเป็นการสร้าง report ขึ้นมาเองโดยวิธีการนึง อย่างเช่น การสร้าง PDF, Excel, Word, Image, HTML Report เป็นต้น

ในกรณีที่ต้องใช้ reporting tool ในข้อที่ 1 หากเป็นโลกของ ASP.NET Web Form ก็จะสามารถใช้งานได้เพราะทำมาให้รองรับกัน เพราะมีการใช้งาน ViewState บน webForm

แต่สำหรับโลกของ ASP.NET MVC ที่ไม่ได้ทำงานบน Web Form นั้น  จะไม่สามารถเรียก report ออกมาแสดงผลได้ตรง ๆ ในบทความนี้จะขอยกตัวอย่างการใช้งาน RDLC (Reporting Client) ผ่านตัว ReporViewer พอเป็นแนวทางในการนำไปประยุกต์ใช้งาน

 

Software Required

  1. Visual Studio 11 หรือ  Visual Studio 2010 + Service Pack 1
  2. ASP.NET MVC 3 with Update Toolkit
  3. SQL Server 2005 or later
  4. Northwind Database

การเรียก reporting service มาใช้งานใน MVC เท่าที่ทดสอบมาจะมีอยู่ 3 วิธี

1. สร้าง web site สำหรับ report แยกออกไปต่างหาก และส่ง parameter ผ่านทาง url

2. สร้าง ReportViewer object ขึ้นใน controller แล้วสั่งให้ render ออกเป็นไฟล์รูปแบบต่างๆที่รองรับ ไปแสดงผลหรือส่งให้ user download ไปดู

3. ใช้ aspx + iFrame + Route ภายใน MVC Project  ซึ่งเป็นวิธีที่ผมจะมาแนะนำ    เพราะโดยรวมแล้วมีข้อดีมากกว่า 2 วิธีข้างต้น

 

พื้นฐานความเข้าใจก่อนไปรื้อโค้ดมาคุย

1. จำไว้เสมอพวก asp.net server control ที่เคยใช้งานทั้งหมด จะเอามาใช้ทำงานบน view ของ MVC ไม่ได้ (ไม่ต้องพยายาม)

2. URL ปกติที่เคยใช้เรียกหน้า aspx ก็ให้ลืมไปซะครับ MVC ไม่รู้จักโดยกำเนิด เช่น http://www.test.com/reports/viewreport.aspx?id=3333 ต้องไปเพิ่ม Route ให้รู้จัก โดยกำหนดแทนที่เช่นเมื่อเจอ “Reports/View” ใน url ให้วิ่งไปหา “/reports/viewreport.aspx” เป็นต้น

3. เราจะใช้ชีวิตอยู่กับ javascript, jquery, html, css, json อย่างเลี่ยงไม่ได้

4. โดยค่าพื้นฐานของ software ที่มีไม่สามารถทำงานร่วมกัน อาศัยต้องแก้ไขประยุกต์ให้ทำงานได้ยืดหยุ่นขึ้น (เจอประจำ)

 

ผลลัพธ์ของ DEMO นี้

เรามาดูหน้าตาโปรแกรมหลังกด F5 กันเลยดีกว่า

image

ใส่ parameter เข้าไป แล้วกด “Show Report”

image

Report ก็แสดงผลออกมาทันใด ไม่มีการ Refresh หน้าจอซะด้วย ว้าวว

image

 

การทำงานของโปรแกรม

image

1. มีการเพิ่ม route ใหม่ให้ตัว MVC รู้จักกับ reportview.aspx (reportviewer)

2. ใน Home/Index view มีการเรียกใช้ iframe เพื่อแสดงผล report  โดยเมื่อรับ OrderID เข้ามาและกด Show Report Button แล้วก็จะสร้าง url จาก paraeter และ set ค่าให้ iframe เพื่อเรียกหน้า aspx มาทำงาน

      2.1 เมื่อ iframe มีการส่ง request ตาม url ที่ได้ set ให้ก็จะถูกส่งกลับไปที่ server ก็จะไปเข้ากับ route pattern ที่ได้กำหนดไว้ในข้อ 1

      2.2 ตัว MVC ก็จะวิ่งไปเรียก reportview.aspx ขึ้นมาทำงาน

3. ในตัว reportview.aspx ได้ทำการ inherit มาจาก RpeortBasePage Class ที่ได้สร้างขึ้นเพื่อช่วยในการสร้าง reportdata object ไว้ใช้งานง่ายขึ้น

4. เสร็จแล้วก็จะเข้า Page_Load Event ของ reportview.aspx ปกติ ซึ่งเราจะมี DBQuery class ไว้ช่วยในการติดต่อ database และ execute เพื่อนำ DataSet ไปส่งให้ ReportViewer Control เพื่อแสดงผลบนหน้า aspx

5. เพื่อ ReportView.aspx ทำงานจบโปรเซสแล้วก้จะไปแสดงผลอยู่บน iframe ของ Index View

*** อ่านไม่เข้าไปข้ามไปก่อน เดี๋ยวมาดูใหม่ตอนจบ

 

มาเริ่มเขียนโค้ดกัน

 

1.  สร้าง MVC 3 Project

เปิด VS ขึ้นมาก็ Create New Project

image

เมื่อกด OK แล้วจะมี dialog ขึ้นทำตามลำดับ

image

เมื่อกด OK แล้วก็จะได้ MVCReport Project

ให้สร้าง Folder ภายในโดยกด Right-Click –> Add –> New Folder   โดยตั้งชื่อว่า  “Reports” จะได้ผลลัพธ์ตามมภาพ

image

 

 

 

2.  สร้าง Client Report ไว้ทำการทดสอบ

คลิ๊กขวาที่ Reports Folder –> Add –> New Item..

image

เราจะสร้าง Report ด้วย Wizard ทำตามลำดับจากนั้นกด OK จะขึ้น Dialog ด้านล่าง

เพื่อสร้าง Connection String สำหรับติดต่อไปเอา Schema จาก Stored Procedure มาสร้างรายงาน

image

ทำตามลำดับ กด Continue จะได้ dialog สำหรับติดต่อ Database

image

image

image

เมื่อสร้าง Connection String เสร็จแล้ว กด Next จะได้หน้าต่างสำหรับเลือก Schema จาก Database ของ Northwind

ซึ่งผมจะใช้ Stored Procedure ที่ชื่อ CustOrderDetail  ในการทำรายงาน ตามรูปด้านล่าง

image

image

image

เลือก item ทั้งหมดใน 1 แล้วลากไป 2  จากนั้น uncheck SUM ออกทุก item แล้วกด Next

image

image

เมื่อกด Finish > >  ก็จะได้ Report เข้ามาใน MVC Project ตามรูปด้านล่างนี้

image

 

 

3. สร้าง Report Framework เอาไว้ใช้งาน

 

1. Report Model เพื่อใช้ในเก็บข้อมูลต่าง ๆ ที่ส่งมาจาก MVC

      1.1 ทำการ คลิ๊กขวาที่ Models Folder –> Add –> Class –> ใส่ชื่อ ReportModel

      1.2 เมื่อได้ ReportModel.cs แล้วให้ลบ code ข้างในทิ้งให้หมด จากนั้น copy code ด้านล่างไปวางแทนที่

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace DemoReport.Models
{
    public class ReportData
    {
        public ReportData()
        {
            this.ReportParameters = new List<Parameter>();
            this.DataParameters = new List<Parameter>();
        }
        public bool IsLocal { get; set; }
        public string ReportName { get; set; }
        public List<Parameter> ReportParameters { get; set; }
        public List<Parameter> DataParameters { get; set; }
    }

    public class Parameter
    {
        public string ParameterName { get; set; }
        public string Value { get; set; }
    }
}

 

2.  สร้าง ReportBasePage class สำหรับจัดการ RouteData นำมาสร้างเป็น ReportData object

      2.1 ไปที่ Solution Explorer-> Reports Folder –> Right click –> Add –> Class –> ตั้งชื่อว่า ReportBasePage

      2.2 จะได้ ReportBasePage.cs   และให้ลบโค้ดในนั้นทิ้งทั้งหมด  แล้วนำ Code ด้านล่างไปวางแทนที่

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using DemoReport.Models;

namespace DemoReport.Reports
{
    public class ReportBasePage : System.Web.UI.Page
    {
        protected ReportData ReportDataObj { get; set; }

        protected override void OnInit(EventArgs e)
        {
            base.OnInit(e);
            if (HttpContext.Current != null)
                if (HttpContext.Current.Session["ReportData"] != null)
                {
                    ReportDataObj = HttpContext.Current.Session["ReportData"] as ReportData;
                    return;
                }
            ReportDataObj = new ReportData();
            CaptureRouteData(Page.RouteData);

        }

        private void CaptureRouteData<T>(T obj) where T : System.Web.Routing.RouteData
        {
            var mode = (obj.Values["rptmode"] + "").Trim();
            ReportDataObj.IsLocal = mode == "local" ? true : false;
            ReportDataObj.ReportName = obj.Values["reportname"] + "";
            string dquerystr = obj.Values["parameters"] + "";
            if (!String.IsNullOrEmpty(dquerystr.Trim()))
            {
                var param1 = dquerystr.Split(‘&’);
                foreach (string pm in param1)
                {
                    var rp = new Parameter();
                    var kd = pm.Split(‘=’);
                    if (kd[0].Substring(0, 2) == "rp")
                    {                      
                        rp.ParameterName = kd[0].Replace("rp","");
                        if (kd.Length > 1) rp.Value = kd[1];
                        ReportDataObj.ReportParameters.Add(rp);
                    }
                    else if (kd[0].Substring(0, 2) == "dp")
                    {
                        rp.ParameterName = kd[0].Replace("dp", "");
                        if (kd.Length > 1) rp.Value = kd[1];
                        ReportDataObj.DataParameters.Add(rp);
                    }
                }
            }
        }

    }
}

3. สร้าง DAL สำหรับ Report ใช้งาน

     3.1  ไปที่ Solution Explorer –> DemoReport Project –> Right Click –> Add –> New Folder  ตั้งชื่อว่า DAL

     3.2  จากนั้นเลือกที่ DAL Folder –> Right click –> Add –> Class   ตั้งชื่อว่า DBQuery 

using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using System.Web;
using DemoReport.Models;

namespace DemoReport.DAL
{
    public class DBQuery
    {
        string constr = ConfigurationManager.ConnectionStrings["NorthwindConnectionString"].ConnectionString;

        public DBQuery() { }

        public DataSet ExecuteDS(string queryName, bool isProcedure, List<Parameter> parameters)
        {
            try
            {
                using (SqlConnection conn = new SqlConnection(constr))
                {
                    using (SqlCommand cmd = new SqlCommand(queryName, conn))
                    {
                        conn.Open();
                        if (isProcedure) // stored procudure execute
                        {
                            cmd.CommandType = CommandType.StoredProcedure;
                            //load parameter of stored procedure to command.parameters
                            SqlCommandBuilder.DeriveParameters(cmd);

                            //assign value to all parameter by name
                            foreach (SqlParameter param in cmd.Parameters)
                            {
                                var x = parameters.SingleOrDefault(o => o.ParameterName.ToLower() == param.ParameterName.ToLower().Replace("@", ""));
                                if (x != null)
                                {
                                    param.Value = x.Value;
                                }
                            }
                        }
                        else // command text execute
                        {
                            cmd.CommandType = CommandType.Text;
                            //add parameter to command
                            foreach (var item in parameters)
                            {
                                cmd.Parameters.AddWithValue(item.ParameterName, item.Value);
                            }
                        }
                        //execute command
                        using (SqlDataAdapter da = new SqlDataAdapter(cmd))
                        {
                            var ds = new DataSet();
                            da.Fill(ds);
                            return ds;
                        }
                    }
                }
            }
            catch (Exception ex) {
                throw ex;
            }
        }

    }
}

4. สร้าง ReportView Page

      4.1 ให้เพิ่มหน้า asp.net web form ลงไปใน Reports Folder ตั้งชื่อว่า ReportView.aspx

image

 

     4.2 จากนั้นเปิดไฟล์ ReportView.aspx ขึ้นมาแล้วลบออกทั้งหมดใส่ code นี้ลงไปแทน

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="ReportView.aspx.cs" Inherits="DemoReport.Reports.ReportView"
    ClientIDMode="Static" %>

<%@ Register Assembly="Microsoft.ReportViewer.WebForms, Version=11.0.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91"
    Namespace="Microsoft.Reporting.WebForms" TagPrefix="rsweb" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>Report Page</title>
</head>
<body>
    <form id="form1" runat="server">
    <asp:ScriptManager ID="ScriptManager1" runat="server" EnablePartialRendering="true">
    </asp:ScriptManager>
    <div>
        <asp:UpdatePanel ID="UpdatePanel1" runat="server">
            <ContentTemplate>
                <rsweb:ReportViewer ID="ReportViewer1" runat="server"></rsweb:ReportViewer>
            </ContentTemplate>
        </asp:UpdatePanel>
    </div>
    </form>

</body>
</html>

ส่วนที่ทำ highlight ไว้ คือโค้ดที่เรียก ReportViewer Control มาใช้งานโดยทำงานภายใต้ UpdatePanel อีกที  ที่ลืมไม่ได้คือ ScriptManager ต้องระบุ EnablePartialRendering=true  ด้วย

 

      4.3 เปิด ReportView.aspx.cs ขึ้นมาแล้วลบ code ทิ้งทั้งหมดจากนั้นวาง code ข้างล่างนี้ลงไปแทนที่

โดยโค้ดด้านล่างจะทำการใส่ parameter และ datasource name รวมไปถึงส่ง dataset เข้าไปใน report ให้เองอัตโนมัติ

using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.IO;
using System.Linq;
using System.Web;
using System.Web.Routing;
using System.Web.UI;
using System.Web.UI.WebControls;
using DemoReport.DAL;
using Microsoft.Reporting.WebForms;

namespace DemoReport.Reports
{
    public partial class ReportView : ReportBasePage //System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            if (!IsPostBack)
            {
                //Get Query/Procedure Name By Report Name from AppSettings (web.config)
                var spName = ConfigurationManager.AppSettings[this.ReportDataObj.ReportName.ToLower() + "_Report"];

                //Execute Data Result
                var ds = new DBQuery().ExecuteDS(spName, true, this.ReportDataObj.DataParameters);
                if (ds == null && ds.Tables.Count > 0)
                    return;

                //Render Report
                RenderReport(ds, this.ReportDataObj);
            }
        }

        private void RenderReport(DataSet ds, Models.ReportData reportData)
        {

            // Reset report properties.
            ReportViewer1.Height = Unit.Parse("100%");
            ReportViewer1.Width = Unit.Parse("100%");
            ReportViewer1.CssClass = "table";

            // Clear out any previous datasources.
            this.ReportViewer1.LocalReport.DataSources.Clear();

            //Set report mode for local processing.
            ReportViewer1.ProcessingMode =  ProcessingMode.Local;

            //Validate report source
            var rptPath = Server.MapPath("/Reports/" + reportData.ReportName + ".rdlc");
            if (!File.Exists(rptPath))
                return;

            //Set report path
            this.ReportViewer1.LocalReport.ReportPath = rptPath;
           
            //Set report parameters
            var rpPms = ReportViewer1.LocalReport.GetParameters();
            foreach (var rpm in rpPms)
            {
                var p = reportData.ReportParameters.SingleOrDefault(o => o.ParameterName.ToLower() == rpm.Name.ToLower());
                if (p != null)
                {
                    ReportParameter rp = new ReportParameter(rpm.Name, p.Value);
                    ReportViewer1.LocalReport.SetParameters(rp);
                }
            }

            // Load the dataSource.
            var dsmems = ReportViewer1.LocalReport.GetDataSourceNames();
            ReportViewer1.LocalReport.DataSources.Add(new ReportDataSource(dsmems[0], ds.Tables[0]));

            // Refresh the ReportViewer
            ReportViewer1.LocalReport.Refresh();
        }

    }
}

 

      4.4  ให้ทำการ Add Assembly ตัวที่ชือ Microsoft.ReportViewer.WebForms  version 11.0.0 ตามรูปนี้เข้ามาในโปรเจ็ค

image

 

      4.5  แก้ไข web.config (ตัวนอก folder)  โดยเราจะต้องเพิ่มส่วนของ report config ให้ IIS รู้จัก

โดยมองหา <system.webServer> …… </system.webServer> แล้ววางส่วนที่ highlight ไว้ในตำแหน่งตามด้านล่าง

<system.webServer>
  <validation validateIntegratedModeConfiguration="false"/>
  <modules runAllManagedModulesForAllRequests="true"/>
  <handlers>
    <add name="ReportViewerWebControlHandler" preCondition="integratedMode" verb="*" path="Reserved.ReportViewerWebControl.axd"
         type="Microsoft.Reporting.WebForms.HttpHandler, Microsoft.ReportViewer.WebForms, Version=11.0.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91" />
  </handlers>

</system.webServer>

ต่อมามองหา <appSettings> …. </appSettings>  แล้วเพิ่ม config ด้านล่างนี้ลงไป  ซึ่งเอาไว้ใช้ในการจับคู่ Report Name กับ Stored Procedure / Query ไว้ที่นี่

<appSettings>
 
  <add key="CustomerOrder_Report" value="CustOrdersDetail"/>
 
  <add key="webpages:Version" value="1.0.0.0" />
  <add key="ClientValidationEnabled" value="true" />
  <add key="UnobtrusiveJavaScriptEnabled" value="true" />
</appSettings>

ให้ทดสอบ build และ run project ด้วยการกด F5  จะได้ผลลัพธ์ด้านล่าง เนื่องจากยังไม่ได้สร้าง Controller / Action / View ของ Default Route ไว้จึงเกิด error ขึ้น

image

 

 

4. เรียกใช้งาน Report Framework ที่สร้างขึ้น

 

1. กำหนดค่า Route ใน Global.asax

ให้ MVC เข้าใจว่าว่าเจอ url patern นี้ “Reports/View/{rpmode}/{reportname}/{*parameter}” ให้ไปเรียก "~/Reports/ReportView.aspx” ตาม virtual path ขึ้นมาทำงานโดย

{rpmode} คือตัวแปรที่ผมกำหนดไว้ใช้งานเพื่อบอกว่าเป็น client report หรือ reporting service

{reportname} คือตัวแปรชือ report ที่เราต้องการจะให้โหลดเข้าไปทำงานใน reportviewer control

{*parameter} คือตัวแปร parameter ที่จะส่งไปทำงานใน ReportViewer โดยจะโดน mvc attach เข้าไปเป็นตัวแปร RouteData ในระบบกำหนดเป็น 2 กลุ่มคือ

  1. กลุ่ม data parameter ไว้สำหรับส่งไปใส่ใน Stored Procedure  โดยผมกำหนดให้มี prefix dp* เช่น dpOrderID
  2. กลุ่ม report parameter ไว้สำหรับส่งเข้าไปใน report ตรงๆ จะใช้ prefix rp* เช่น rpReportName
            ## ให้มองหาไฟล์ Global.asax.cs ใน solution explorer ขึ่นมาแก้ไข มองหาเมดธอดที่ชื่อ RegisterRoutes() แล้วเพิ่มโค้ดที่ highlight ข้างล่างลงไป

    public static void RegisterRoutes(RouteCollection routes)
    {
        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

        routes.MapRoute(
            "Default", // Route name
            "{controller}/{action}/{id}", // URL with parameters
            new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
        );
        //Custom route for reports
        routes.MapPageRoute(
         "ReportRoute",                         // Route name
         "Reports/View/{rptmode}/{reportname}/{*parameters}",                // URL
         "~/Reports/ReportView.aspx"  // File
         );

    }

 

2. สร้าง Home Controller และ View

ไปที่ Solution Explorer –> Controllers folder –> Right click –> Add –> Controller.. 

จะได้หน้าต่างด้านล่าง ตั้งชื่อ HomeController แล้วกด Add

image

image

ให้แก้ไข Action Index() โดยเพิ่มโค้ดลงไปตามนี้

public ActionResult Index()
{
    ViewData["reportUrl"] = "/Reports/View/local/CustomerOrder/";
    return View();
}

*** ใช้เป็น url สำหรับยิง request ไปยัง report page

จากนั้นเลื่อน cursor ไปคลิ๊กบริเวณ Index()  แล้วกด Right Click –> Add View..   

แล้วใส่ค่าตามรูปด้านล่างนี้ และกด Add

image

ก็จะได้ Index View มาใช้งาน ต่อไปเราจะแก้ไขหน้า Index View ให้รับค่า OrderID และมี button สำหรับสั่งงานให้ไปเรียก ReportView.aspx มาทำงานใน iframe

โค้ดสำหรับ Index.cshtml  View

@{
    ViewBag.Title = "Index";
    Layout = "~/Views/Shared/_Layout.cshtml";
}

<h2>Hello MVC Report Solution</h2>

<script type="text/javascript">

    $('#ShowReport').live('click', function () {
        var url = $('#hdUrl').val();
        var url = url + "dpOrderID=" + $('#orderid').val();
        $('#ifrReport').attr('src', url);
    });

</script>

<form>

<input id="hdUrl" type="hidden" value="@ViewData["reportUrl"]" />
<div style="height: 25px">
    <label>Fill Order ID:</label>
    <input id="orderid" type="text" required="required" placeholder="Order ID" value="10248" />
    <button type="button" id="ShowReport" title="Show Report" >Show Report</button>
</div>

<iframe src="" id="ifrReport" style="width: 100%; height: 500px;" frameborder="0" hspace="0" vspace="0" marginheight="0" marginwidth="0"></iframe>

</form>

อธิบายโค้ดในหน้า Index.cshtml ด้านบน

<script type=”text/javascript”> …….

เราจะใช้ jqeury ทำการดัก event click ของ <button.ShowReport  เมื่อมีการกดปุ่ม

ให้เอาค่าจาก <hidden.hdUrl ออกมาใช้งาน ซึ่งส่งค่ามาใส่ใน value=’@ViewData[“reportUrl”]’ 

มาแปะ dpOrderID พร้อมค่าจาก input.orderid เข้าไป

และส่งให้ set ค่า url ให้กับ <iframe.ifrReport โดยกำหนด src = url ที่สร้างมาได้

เจ้า iframe ก็จะสร้าง request ส่งไปยัง server ให้เราเอง แค่นี้ก็เป็นการเรียกหน้า ReportView.Aspx แล้วครับ

 

เมื่อจบ step ลองย้อนกลับไปอ่าน flow diagram ด้านบนอีกครั้งก็จะเข้าใจการทำงานเพิ่มขึ้นครับ

 

สรุปทิ้งท้าย

มาถึงช่วงสุดท้าย จากตัวอย่างที่ได้ทำ demo ให้ดูไปนั้น ยังไม่สามารถรองรับ Reporting Services, Crystal Report ได้  ต้องปรับโค้ดส่วน Report Framework อีกนิดหน่อย  แต่ก็พอเป็นแนวทางให้ทุกคนที่ยังติดปัญหาในการสร้าง report กับตัว MVC อยู่ได้บ้าง  และได้เข้าใจการทำงานของ MVC มากขึ้นอีก ซึ่งมีความรู้แฝงอยู่ในบทความนี้มากมาย หวังว่าจะเป็นประโยชน์ในการทำงานครับ

 

Demo Source Code

http://dl.dropbox.com/u/34809954/MVCReport.zip

 

*อย่าลืมตามไปแก้ connection string ใน web.config  ให้ชี้ไปที่ sql server ของตัวเอง

** ใน zip จะมี northwind_db_script.sql ให้นำไปสร้าง database กรณีที่ไม่มี database ในเครื่อง


image

About Me:

Chalermpon Areepong : Nine (นาย)

Microsoft MVP Thailand ASP.NET

ASP.NET & MVC Developers Thailand Group : http://www.facebook.com/groups/MVCTHAIDEV/

Greatfriends.biz Community Leader : http://greatfriends.biz

Email : nine_biz-talk.net at hotmail dot com

Blog : https://nine69.wordpress.com

2 Comments »

  1. thanks and love you MS MVP P’Nine

    Comment by ชาณุพล เพิ่มพูล — 05/09/2012 @ 4:34 pm

  2. สอบถามนิดนึงครับ ผม set iis แล้ว พอรันผ่าน ie พิมพ์ี url ตามนี้ http://localhost/MVCDemoReport มันก็จะแสดงผลปกติ แต่แล้วพอกดปุ่ม Show Report ตรง iFrame มันจะขึ้น error ว่า The webpage cannot be found ไม่ทราบว่า ผมต้องแก้ไขตรงส่วนไหนครับ

    Comment by Jittagonnoi Satonggan — 29/04/2013 @ 12:17 pm


RSS feed for comments on this post. TrackBack URI

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Blog at WordPress.com.

%d bloggers like this: