'How can I export search results to CSV in ASP.NET MVC application?

My client wants Export to CSV functionality on a search results page. I am running a ASP.NET MVC application and we are using Razor for our frontend. I think I understand how referring to the @model works, but I am unable to actually pass the data passed to the view back to a controller to use with a different action. For example, I have a list of search results defined as the model's type:

@model IList<Capstone_Museum.Models.SearchResult>

SearchResult.cs:

public class SearchResult {
        [JsonPropertyName("guid")]
        public string Guid { get; set; }
        [JsonPropertyName("scientific_name")]
        public string ScientificName { get; set; }
        [JsonPropertyName("verbatim_date")]
        public string Date { get; set; }
        [JsonPropertyName("country")]
        public string Country { get; set; }
        [JsonPropertyName("state_prov")]
        public string State { get; set; }
        [JsonPropertyName("spec_locality")]
        public string Locality { get; set; }
        [JsonPropertyName("dec_lat")]
        public decimal? Latitude { get; set; }
        [JsonPropertyName("dec_long")]
        public decimal? Longitude { get; set; }
        [JsonPropertyName("coordinateuncertaintyinmeters")]
        public int? UncertaintyMeters { get; set; }
}

If I pass the Model back to a controller's action, the list comes back null. I do it like this:

@Html.ActionLink(linkText: "Export to CSV", actionName: "ExportResults", controllerName: "SearchResults", routeValues: Model)

and I'm receiving the list in my action like this:

public IActionResult ExportResultsCSV(List<SearchResult> searchResults) {
        return File(new UTF8Encoding().GetBytes(SearchResult.ListToString(searchResults)), "text/csv", "ExportResults.csv");
}

I've realized that an action passes a string version of whatever data it uses by parameter using the URL. My lists may be thousands of lines long - which is too much to include in a URL, bringing an error.

I just need to download the csv to the client machine. Is there a way to do this, even on the frontend? I'd rather not get the data from the HTML table containing the results to create the CSV.



Solution 1:[1]

I think you want to break your actions up into an API action that returns the search results as csv, and a view action that renders the search results to html.

class SearchController {

  [HttpGet]
  [Produces("text/csv")]
  IEnumerable<SearchResult> GetSearchResults(string query){
    ...
  }

  [HttpGet]
  IActionResult ViewSearchResults(string query)
  {
    var results = GetSearchResults(query);
    return View(results);
  }
}

In the view you would link to the GetSearchResults action, which would re-run the query and send the results back to the client as csv... assuming you have a formatter that can produce CSV. By default, in ASP.NET Core only JSON is supported. I maintain a library that provides text/csv formatting that you can use: Sylvan.AspNetCore.Mvc.Formatters.Csv. By adding this nuget package, and registering the formatter, you can use the [Produces("text/csv")] to send results back to the client as CSV instead of JSON.

The only issue you'll need to consider, is that the search results might change between viewing the "view", and then clicking the download as CSV link. It usually isn't an issue, but there might be rare occasion where the html results would disagree with the downloaded CSV.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 MarkPflug