【发布时间】:2020-07-24 14:13:02
【问题描述】:
我正在尝试运行简单的 ASP.NET CORE Web 应用程序,但在允许用户通过 html 链接访问我的服务器上的文件时遇到了问题。我有一个名为“TestModel”的模型、一个名为“TestView”的视图和一个名为“AppController”的控制器。我的视图允许用户在两个单独的字段中输入一些文本以及从他们的硬盘驱动器中选择两个不同的文件,它将所有内容绑定到我的模型并在用户单击按钮时执行 POST。我已经验证模型是否正确地传回了我的控制器。我的控制器正确地将文件保存到我的服务器目录中的文件夹中,使用单独的服务来操作文件,并将模型返回到视图中,即当我使用调试器检查 Testview 中的“返回视图(模型)”时action 被传回的模型填充了它的所有属性。
问题是我希望视图上的两个链接指向服务器上的文件,以便用户可以单击链接并收到下载文件的提示,但我似乎无法启动它。我在 razor 中使用@Html.ActionLink() 功能指向“下载描述”操作并将模型传递给它,认为它将传递当前视图的模型,但它传递的模型的所有字段都为 null .对我做错了什么有任何见解吗?
这些是我的 AppController 中的相关操作:
[HttpPost("~/App/TestView")]
public IActionResult TestView(TestModel Model)
{
if (ModelState.IsValid)
{
Console.WriteLine("Something was sent back from the TestView page");
Model.OnPostAsync();
var x = _descLogicService.Convert(Model);
}
return View(Model);
}
public IActionResult DownloadDescriptions(TestModel model)
{
var cd = new ContentDispositionHeaderValue("attachment")
{
FileNameStar = model.DescriptionFile.FileName
};
Response.Headers.Add(HeaderNames.ContentDisposition, cd.ToString());
byte[] bytes = System.IO.File.ReadAllBytes(model.MeasurementExportFile);
using (FileStream fs = new FileStream(model.MeasurementExportFile, FileMode.Open, FileAccess.Read))
{
fs.Read(bytes, 0, System.Convert.ToInt32(fs.Length));
fs.Close();
}
return File(bytes, "text/csv");
}
这是我的视图模型:
public class TestModel
{
[BindProperty]
[Required]
[MinLength(5)]
public string Name { get; set; }
[BindProperty]
[Required]
[MaxLength(10,ErrorMessage ="Input string is too long.")]
public string MyInput { get; set; }
[BindProperty]
[Required]
public IFormFile DescriptionFile { get; set; }
[BindProperty]
[Required]
public IFormFile MeasurementFile { get; set; }
public string DescriptionDirectory { get; set; }
public string DescriptionExportFile { get; set; }
public string MeasurementDirectory { get; set; }
public string MeasurementExportFile { get; set; }
public async Task OnPostAsync()
{
var token = DateTime.Now.Ticks.ToString();
var directory = Directory.CreateDirectory(@"uploads\"+ token + @"\");
DescriptionDirectory = directory.CreateSubdirectory("Descriptions").FullName + @"\";
DescriptionExportFile = directory.CreateSubdirectory(@"Descriptions\Exports\").FullName + DescriptionFile.FileName;
MeasurementDirectory = directory.CreateSubdirectory("Measurements").FullName + @"\";
MeasurementExportFile = directory.CreateSubdirectory(@"Measurements\Exports\").FullName + MeasurementFile.FileName;
var file = Path.Combine(DescriptionDirectory, DescriptionFile.FileName);
using (var fileStream = new FileStream(file, FileMode.Create))
{
await DescriptionFile.CopyToAsync(fileStream).ConfigureAwait(true);
}
file = Path.Combine(MeasurementDirectory, MeasurementFile.FileName);
using (var fileStream = new FileStream(file, FileMode.Create))
{
await MeasurementFile.CopyToAsync(fileStream).ConfigureAwait(true);
}
}
}
这是视图:
@**I need to add the namespace of C# models I'm creating *@
@using FirstASPNETCOREProject.ViewModels
@*I need to identify the model which 'fits' this page, that is the properties of the model can be
bound to entities on the view page, using "asp-for"*@
@model TestModel
@{
ViewData["Title"] = "Page for File Uploads";
}
@section Scripts{
}
<div asp-validation-summary="ModelOnly" style="color:white"></div>
<form method="post" enctype="multipart/form-data">
<label>Enter a Description File Name</label>
<input asp-for="Name" type="text" />
<span asp-validation-for="Name"></span>
<br>
<label>Select a Description File</label>
<input asp-for="DescriptionFile" type="file" />
<span asp-validation-for="DescriptionFile"></span>
<br>
<label>Enter the Measurement File Name</label>
<input asp-for="MyInput" type="text">
<span asp-validation-for="MyInput"></span>
<br>
<label>Select a Measurement File</label>
<input asp-for="MeasurementFile" type="file">
<span asp-validation-for="MeasurementFile"></span>
<br>
<input type="submit" value="Send Message" />
</form>
@Html.ActionLink("Description File", "DownloadDescriptions", "App")
@Html.ActionLink("Measurement File", "DownloadMeasurements", "App")
【问题讨论】:
-
欢迎来到 StackOverflow。您不能使用 ActionLink 来传递模型。您需要使用第二种和第三种形式,其中包含要发布到下载操作的值。那,或者您创建一个 GET 请求并提供您需要的值作为路由参数。后者可以通过 ActionLink 完成。
-
@Dennis1679 这不是真的...您可以使用 ActionLinks 传递模型...您只需在 ActionLink 调用中添加一个匿名类型并将参数设置为控制器中的 [FromQuery]行动
-
@JonathanAlfaro 您所描述的并不是像我所说的“通过”那样传递模型。我想说的是,你不能通过 ActionLink 传递模型,就像你通过表单/帖子传递它一样。但是,您可以 - 正如您所描述的那样 - 欺骗它从模型创建一个 RouteValueDictionary ,因为 ActionLink 将采用一个对象,而该对象又将被转换为查询字符串。这让我想知道,这是否适用于包含列表的复杂模型?
-
@Dennis1679 你又错了....使用查询字符串参数绑定复杂对象是完全可能的....事实上,我只是发布了一个关于如何做到这一点的示例.
-
仅供参考,这个组合对我有用:在视图中:@Html.ActionLink("Measurement File", "DownloadMeasurements", "App", Model)。在控制器中:public IActionResult DownloadMeasurements([FromQuery]TestModel model){ }。视图中的模型是一个 TestModel 对象。
标签: c# asp.net-mvc asp.net-core model-view-controller mvvm