我的客户希望在搜索结果页面上具有导出到CSV的功能。我正在运行一个ASP.NET MVC应用程序,我们正在使用Razor作为前端。我想我理解引用@模型是如何工作的,但我无法将传递给视图的数据实际传递回控制器以用于不同的操作。例如,我有一个定义为模型类型的搜索结果列表:
@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; }
}
如果我将Model
传递回控制器的操作,那么列表将返回null。我是这样做的:
@Html.ActionLink(linkText: "Export to CSV", actionName: "ExportResults", controllerName: "SearchResults", routeValues: Model)
我收到的清单是这样的:
public IActionResult ExportResultsCSV(List<SearchResult> searchResults) {
return File(new UTF8Encoding().GetBytes(SearchResult.ListToString(searchResults)), "text/csv", "ExportResults.csv");
}
我已经意识到,一个操作通过使用URL的参数传递它使用的任何数据的字符串版本。我的列表可能有数千行长——这太多了,无法包含在URL中,这会带来错误。
我只需要将csv下载到客户端机器有没有办法做到这一点,即使是在前端?我宁愿不从包含结果的HTML表中获取数据来创建CSV。
我认为您需要将您的操作分解为API操作和视图操作,前者将搜索结果返回为csv,后者将搜索结果呈现为html。
class SearchController {
[HttpGet]
[Produces("text/csv")]
IEnumerable<SearchResult> GetSearchResults(string query){
...
}
[HttpGet]
IActionResult ViewSearchResults(string query)
{
var results = GetSearchResults(query);
return View(results);
}
}
在视图中,您将链接到GetSearchResults
操作,该操作将重新运行查询并将结果以csv形式发送回客户端。。。假设您有一个可以生成CSV的格式化程序。默认情况下,在ASP.NET Core中,仅支持JSON。我维护了一个库,它提供了您可以使用的文本.csv格式:Sylvan.AspNetCore.Mvc.Formatters.csv。通过添加这个nuget包并注册格式化程序,您可以使用[Produces("text/csv")]
将结果以csv而不是JSON的形式发送回客户端。
你需要考虑的唯一问题是,搜索结果可能会在查看";视图";,然后单击下载为CSV链接。这通常不是问题,但可能很少有html结果与下载的CSV不一致的情况。