2

Although I can create rdlc report in debug mode, I encounter an error "Access to the path 'C:\xxx.xlsx' is denied." After looking on the web for workaround, I see that lots of the solutions suggest to give permission to the C drive for IIS user. However, it does not seem to be wisely to give permission to entire drive for just rendering a report. So, how to change this render location i.e. C:\inetpub\MyApplication? On the other hand I think there is no settings needed on reporting side i.e. ReportViewer.ProcessingMode = ProcessingMode.Local; or changing rdlc properties "Build Action", "Copy Output Directory"?

Note: I do not want the reports to be rendered on client's machine as some of them has no right to write any location under C:\ and I think generating reports on IIS location is much better. Is not it?

So, what is the best solution in this situation?


Update: How can I modify this method so that it just read the stream as excel withou writing it?

public static void StreamToProcess(Stream readStream)
{
    var writeStream = new FileStream(String.Format("{0}\\{1}.{2}", Environment.GetFolderPath(Environment.SpecialFolder.InternetCache), "MyFile", "xlsx"), FileMode.Create, FileAccess.Write);
    const int length = 16384;
    var buffer = new Byte[length];
    var bytesRead = readStream.Read(buffer, 0, length);
    while (bytesRead > 0)
    {
        writeStream.Write(buffer, 0, bytesRead);
        bytesRead = readStream.Read(buffer, 0, length);
    }
    readStream.Close();
    writeStream.Close();
    Process.Start(Environment.GetFolderPath(Environment.SpecialFolder.InternetCache) + "\\" + "file" + "." + "xlsx");
}       
Jack
  • 1
  • 21
  • 118
  • 236

1 Answers1

2

Here is how we render Excel files from an rdlc without saving it to a server folder. Just call the action and it will download to the user's browser.

    public FileStreamResult ExcelReport(int type)
    {

        var body = _db.MyObjects.Where(x => x.Type == type);
        ReportDataSource rdsBody = new ReportDataSource("MyReport", body);
        ReportViewer viewer = new ReportViewer 
        { 
            ProcessingMode = ProcessingMode.Local 
        };
        viewer.LocalReport.ReportPath = Server.MapPath(@"~\bin\MyReport.rdlc");
        viewer.LocalReport.DataSources.Clear();
        viewer.LocalReport.DataSources.Add(rdsBody);
        viewer.LocalReport.EnableHyperlinks = true;
        string filename = string.Format("MyReport_{0}.xls", type); 
        byte[] bytes = viewer.LocalReport.Render("Excel");
        var stream = new MemoryStream(bytes);
        return File(stream, "application/ms-excel", filename);
    }
Steve Greene
  • 12,029
  • 1
  • 33
  • 54
  • Many thanks for your reply. I add an update to the question. So, how can I make a little notification mentioned in update above? – Jack Dec 14 '15 at 15:49
  • I may be misunderstanding what you want. This answer is for Excel output to the client from an rdlc. Your code above looks like you are trying to get Excel running on the client. I don't think you can do that due to the obvious security issues. We make an xls file that the user can click on which will start Excel. – Steve Greene Dec 14 '15 at 16:50
  • Sorry, I am a little bit confused. I just want to be sure if we should modify such a kind of "file generating" or "report generating" methods by just removing the "write" part to the disk (I think the problem is caused from trying to write the disk and we need a memory to generate and display the file). Is that true? – Jack Dec 15 '15 at 07:25
  • You can do either, but if you write a file there are security issues, whereas a memory stream is handled by the browser. It still saves it as a file. Best suggestion is try the streaming method and see if it meets your needs. – Steve Greene Dec 15 '15 at 14:12
  • I will try it asap. But even if it does not solve my problem thanks a lot for your help. Voted+ – Jack Dec 15 '15 at 14:22
  • Post a followup question if you run into issues. – Steve Greene Dec 15 '15 at 14:25