Search code examples
c#asp.net-corecsvhelper

Does csvhelper work differently in .net core 2.1 mvc as compared to razor pages?


I seem to get different behaviour using the csvhelper addon when I use it in mvc controllers versus razor pages. The following code works in .net core 2.1 mvc:

public void ExportReportsToRecords()
{
    Response.ContentType = "text/csv";
    Response.ContentType = "application/octet-stream";
    StringWriter sw = new StringWriter();

    var writer = new CsvWriter(sw);
    IEnumerable records = (_context.ReportsToRecords.ToList());
    writer.WriteRecords(records);
    foreach (ReportsToRecords record in records)
    {
        writer.WriteRecord(record);
    }

    Response.WriteAsync(sw.ToString());
}

It creates a csv file in my chrome browser which can then be doubleclicked in Excel. The above code being in my controller code.

When I using in a razor page in the code below:

namespace RTMGMTCore2Razor.Pages.RequiredCorrections
{
    public class ExportCorrectionsModel : PageModel
    {
        private readonly RTMGMTCore2Razor.Models.RTMGMTContext _context;

        public ExportCorrectionsModel(RTMGMTContext context)
        {
            _context = context;
        }

        public const string MessageKey = nameof(MessageKey);
        public void OnGet()
        {
            try
            {
                Response.ContentType = "text/csv";

                Response.ContentType = "application/octet-stream";
                StringWriter sw = new StringWriter();

                var writer = new CsvWriter(sw);
                IEnumerable records = (_context.RequiredCorrectionsSet.ToList());
                writer.WriteRecords(records);
                foreach (RequiredCorrectionsSet record in records)
                {
                    writer.WriteRecord(record);

                }
                Response.WriteAsync(sw.ToString());

                TempData[MessageKey] = "Export Succeeded!";
            }
            catch
            {
                TempData[MessageKey] = "Export Failed!";
            }
            return;
        }
    }
}

it tries to create the csv document at the bottom of the chrome browser but it comes up with a network error message. When I switch it to Microsoft Edge, it actually shows the csv text file contents directly in browser.

Anyone have any idea of why the weird behaviour difference between razor pages on this vis a vis views and controllers?

The cshtml is:

@page
@model RTMGMTCore2Razor.Pages.RequiredCorrections.ExportCorrectionsModel
@{
    ViewData["Title"] = "ExportCorrections";
}

<h2>ExportCorrections</h2>

<form method="get" asp-page="ExportCorrections"> </form>

@if (TempData[RTMGMTCore2Razor.Pages.ReportsToRecord.ExportReportsToRecordsModel.MessageKey] is string message)
{

    <h4>@message</h4>
}


<a asp-page="./Index">Back to List</a>

Solution

  • The Razor Page model is page-oriented , which means in most case , Razor page is used to display page . If you want to response with a stream , simply use the File() to return a FileContentResult .

    To Fix the bug , change the method in your PageModel as below :

    // file : ExportCorrectionsMode.cshtml.cs
    // ...
    public class ExportCorrectionsModel : PageModel
    {
        // ...
        public ActionResult OnGet()
        {
            var sw = new StringWriter();
            var writer = new CsvWriter(sw);
            IEnumerable records = (_context.RequiredCorrectionsSet.ToList());
            writer.WriteRecords(records);
            var bytes = Encoding.UTF8.GetBytes(sw.ToString());
            return File(bytes, "application/octet-stream", "text/csv");
        }
    
        // ...
    }