2

I have asp.net MVC2 application. I am using VS2008 and want to hook up generated report from my controller to reportviewer.

any ideas?

so far i have this code "Controller"

//should pass data to report
 public ActionResult GenerateReport()
      {


        LocalReport report = new LocalReport();
        report.ReportPath = Server.MapPath("~/Reports/KingsCourt.rdlc");

        List<InvoiceRow> rows = new List<InvoiceRow>();

        rows.Add(new InvoiceRow { name = "Testing item", value = (decimal)25.85 });
        rows.Add(new InvoiceRow { name = "Testing item2", value = (decimal)5.15 });
        ReportDataSource source = new ReportDataSource("InvoiceRow", rows);
        report.DataSources.Add(source);

        ViewData["InvoiceRow"] = report;
        return View();
      }

and View page:

 <form id="form1" runat="server">

  <h2>GenerateReport</h2>
  <rsweb:ReportViewer ID="ReportViewer1" runat="server" Font-Names="Verdana" 
      Font-Size="8pt" Height="400px" Width="400px">
    <LocalReport ReportPath="Reports\KingsCourt.rdlc">
      <DataSources>
        <rsweb:ReportDataSource DataSourceId="ObjectDataSource1" Name="InvoiceRow" />
      </DataSources>
    </LocalReport>


  </rsweb:ReportViewer>    

  <asp:ObjectDataSource ID="ObjectDataSource1" runat="server" SelectMethod="Rows" 
      TypeName="Accounts.Classes.Invoices"></asp:ObjectDataSource>
 </form>
Sachin Chavan
  • 5,578
  • 5
  • 49
  • 75
cpoDesign
  • 8,953
  • 13
  • 62
  • 106

3 Answers3

9

You can always use ASP.NET WebForms with MVC. I guess this is the only way to do it.
I've prepared a sample for you here.

You can create a folder where you're going to put your asp.net WebForm and the report (rdlc). I've put in the same folder the schema (xsd) and the data (xml) but, obviously, I guess you're going to use the database. I've mapped the route to the report(s) like this:

    //Custom route for reports
    routes.MapRoute(
     "ReportRoute",
     "Reports/{reportname}",                
     "~/Reports/{reportname}.aspx"
     );

UPDATE:

I have prepared some code for ASP.NET MVC3 (MvcReportViewerMVC3).
It is pretty much the same with some minor changes on the webform: I've integrated the new ReportViewer (10) and I had to add the ScriptManager to the same page:

<asp:ScriptManager ID="ScriptManager1" runat="server"></asp:ScriptManager>

I've changed the WebForm code as well cause it appears that page_load event is called loads of times:

protected void Page_Load(object sender, EventArgs e)
{
    if (!this.IsPostBack)
    {
    ....
    }
}

Hope it helps.

LeftyX
  • 35,328
  • 21
  • 132
  • 193
  • Your option is i thing so far the best, thank you for example its great,i have been wondering about similar solution but urs is neater thnx – cpoDesign Mar 14 '11 at 17:09
  • I am afraid this is the only solution if you want to use the server control. That is a asp.net server control and can't be used in MVC. Plus ReportViewer uses viewstate ... and you don't have that in MVC. If you think my answer is good enough for you, could you please close it ;-) – LeftyX Mar 14 '11 at 17:17
  • You can, sure. The only problem I see is ReportViewer uses client-script so I guess you have to load it in an IFRAME. I've tried something like this and it works but it has some problems with the refresh: – LeftyX Mar 15 '11 at 09:39
  • thnx, will play around to see what solution is better – cpoDesign Mar 15 '11 at 20:33
  • 2
    MVC3 here ... i get "controllerName cannot be null" when using this approach (the route is registered before the default one) – Alex Oct 24 '11 at 10:42
  • Yes I got the same error as alex under MVC3. But by moving the aspx page out of the Views folder to a folder on the root (as your example code) enabled me to pass a full URL path directly to the aspx but then I get a parser error "Could not load type 'System.Web.Mvc.ViewPage'" – Johncl Oct 26 '11 at 13:30
  • Ok I figured out the parser error as I was using a different example. Yours works fine though. But I cant make the MapRoute to work, the "controllerName cannot be null" error persists. I have to use a straight URL directly to the aspx file (which the MVC framework dont seem to mind oddly). – Johncl Oct 27 '11 at 06:57
  • @Johncl: I've updated my answer and added some sample code for MVC3.Hope it helps. – LeftyX Oct 27 '11 at 09:47
  • For anyone coming here with the "controllerName cannot be null" issue, you should be using MapPageRoute (http://msdn.microsoft.com/en-us/library/system.web.routing.routecollection.mappageroute.aspx) instead of MapRoute – Simon Fox May 28 '12 at 09:35
0

I doubt usage of reportviewer in asp.net mvc is possible.
Best thing You can do is return report rendered as an image.

Community
  • 1
  • 1
Arnis Lapsa
  • 45,880
  • 29
  • 115
  • 195
0

Pavel, I've struggled a little while with that. At the end decided to implement my own ActionResult and streaming a PDF file. This is my action:

public ActionResults.DownloadFileResult PrintReport()
{
    rvDocument = new WebForms.ReportViewer();

    rvDocument.ProcessingMode = ProcessingMode.Local;

    LocalReport report = rvDocument.LocalReport;
    report.ReportPath = Server.MapPath("~/Reports/KingsCourt.rdlc");

    string sGuid = Guid.NewGuid.ToString.Replace("-", "");

    List<InvoiceRow> rows = new List<InvoiceRow>();

    rows.Add(new InvoiceRow { name = "Testing item", value = (decimal)25.85 });
    rows.Add(new InvoiceRow { name = "Testing item2", value = (decimal)5.15 });
    ReportDataSource source = new ReportDataSource("InvoiceRow", rows);
    report.DataSources.Add(source);

    rvDocument.LocalReport.Refresh();

    string sFileName = Path.Combine("<temp folder>", sGuid + ".PDF");
    byte[] StreamBytes = null;

    string mimeType = "";
    string encoding = "";
    string filenameExtension = "";
    string[] streamids = null;
    Warning[] warnings = null;

    StreamBytes = rvDocument.LocalReport.Render("PDF", null, mimeType, encoding, filenameExtension, streamids, warnings);
    if ((StreamBytes != null)) {
        try {
            using (FileStream fs = new FileStream(sFileName, FileMode.CreateNew, FileAccess.Write, FileShare.Write)) {
                fs.Write(StreamBytes, 0, StreamBytes.Length);
            }
        } catch (Exception ex) {
            // Log.Logger.WriteException(string.Empty, ex, Log.Logger.LogTypes.Error, this.GetType, "Report001_Load");
        }
        StreamBytes = null;
    }

    BPMVC.ActionResults.DownloadFileResult oPdfToStream = new BPMVC.ActionResults.DownloadFileResult();
    {
        oPdfToStream.FileName = sFileName;
        oPdfToStream.ContentType = "application/pdf";
        oPdfToStream.DocumentName = "ReportName.pdf";
    }

    return (oPdfToStream);

}

and this is my custom ActionResult

using System.Web.Mvc;
using System.Web;
using System.IO;

namespace ActionResults
{

    public class DownloadFileResult : ActionResult
    {

        #region " Public Properties "

        private string _VirtualPath = "";
        public string VirtualPath {
            get { return (_VirtualPath); }
            set { _VirtualPath = value; }
        }

        private string _FileName = "";
        public string FileName {
            get { return (_FileName); }
            set { _FileName = value; }
        }

        private string _ContentType = "text/html";
        public string ContentType {
            get { return (_ContentType); }
            set { _ContentType = value; }
        }

        private string _DocumentName = "";
        public string DocumentName {
            get { return (_DocumentName); }
            set { _DocumentName = value; }
        }

        #endregion


        public override void ExecuteResult(System.Web.Mvc.ControllerContext context)
        {
            if ((context == null)) {
                throw new ArgumentNullException("context");
            }

            if (string.IsNullOrEmpty(this.FileName) && string.IsNullOrEmpty(this.VirtualPath)) {
                throw new ArgumentNullException("FileName is Empty");
            }


            string filePath = "";

            if (string.IsNullOrEmpty(this.VirtualPath)) {
                filePath = this.FileName;
            } else {
                filePath = context.HttpContext.Server.MapPath(this.VirtualPath);
            }

            if (string.IsNullOrEmpty(this.DocumentName)) {
                this.DocumentName = Path.GetFileName(filePath);
            }

            {
                context.HttpContext.Response.Clear();
                context.HttpContext.Response.ClearHeaders();
                context.HttpContext.Response.ClearContent();
                context.HttpContext.Response.ContentType = this.ContentType;
                context.HttpContext.Response.AddHeader("Content-Type", this.ContentType);
                context.HttpContext.Response.AddHeader("content-disposition", "attachment; filename=\"" + this.DocumentName + "\"");
                context.HttpContext.Response.TransmitFile(this.FileName);
                context.HttpContext.Response.End();
            }

        }

    }

}
LeftyX
  • 35,328
  • 21
  • 132
  • 193
  • Hi, i have version which is allready returning pdf "onfly" but i need to present the report to confirm it by user – cpoDesign Mar 14 '11 at 10:58
  • See my answer to [this question](http://stackoverflow.com/questions/6144513) for a MVC3 version of the above code. – Adrian Toman Aug 24 '11 at 15:04