[英]IFormFile always null (ASP.NET Core with MVC/Razor)
我有一个尝试上传 IFormFile 的 ASP.NET Core MVC 应用程序。 但是,IFormFile 始终为空。 我发现的其他解决方案都没有解决这个问题。 我究竟做错了什么?
模型
public class EmailForm
{
[Display(Name = "Add a picture")]
[DataType(DataType.Upload)]
[FileExtensions(Extensions = "jpg,png,gif,jpeg,bmp,svg")]
public IFormFile SubmitterPicture { get; set; }
}
控制器
public async Task<ActionResult> Contribute([Bind("SubmitterPicture")] EmailForm model)
{
if (ModelState.IsValid)
{
//Do some stuff
}
}
看法
<form method="post" asp-action="Contribute" asp-antiforgery="true" enctype="multipart/form-data" >
<div class="form-group" >
<div class="col-md-2">@Html.LabelFor(m => m.SubmitterPicture)</div>
<div class="col-md-4">
<input type="file" name="SubmitterPicture" id="SubmitterPicture" />
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" class="btn btn-default" value="Contribute" />
</div>
</div>
<form method="post" enctype="multipart/form-data">
</form>
enctype="多部分/表单数据"
多部分表单数据是关键。
您也可以从HttpContext.Request.Form.Files
获取文件并摆脱模型中的IFormFile
接口。 我推荐这种方法,因为我认为文件与数据模型无关。
这个例子是:
public IActionResult Index()
{
//Please note that if no form data is posted
// HttpContext.Request.Form will throw an exception
if (HttpContext.Request.Form.Files[0] != null) {
var file = HttpContext.Request.Form.Files[0];
using (FileStream fs = new FileStream("Your Path", FileMode.CreateNew, FileAccess.Write, FileShare.Write)) {
file.CopyTo(fs);
}
}
return View();
}
如果此方法也失败,则意味着multipart
请求有问题。
在同一个问题坐了几个小时后,我找到了解决方案。
问题:
在表单中提交单个输入。
结论:
基本上,在您的 html 表单中,如果除了提交按钮之外只有一个输入,这将不起作用。 当我在 viewModel 上添加另一个属性并在表单中添加另一个输入时,我的属性不再为空。
我希望这对其他人有帮助。
剃刀页面 HTML:
@page
@model SomeModel
<form method="post" enctype="multipart/form-data">
<div class="form-group">
<div class="col-md-10">
<p>Upload one or more files using this form:</p>
<input asp-for="Input.SingleInput" type="file" class="form-control" />
<input asp-for="Input.AnotherInput" class="form-control" />
</div>
</div>
<div class="form-group">
<div class="col-md-10">
<input type="submit" value="Upload" />
</div>
</div>
</form>
Razor 页面代码背后:
public class SomeModel: PageModel
{
[BindProperty]
public SomeViewModel Input { get; set; }
public async Task OnGetAsync()
{
}
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
// This won't be null.
var showMeSomething = Input.SingleInput;
return RedirectToPage();
}
}
一些视图模型:
public class SomeViewModel
{
public IFormFile SingleInput{ get; set; }
public string AnotherInput{ get; set; }
}
我发现通过在我的 html 表单上提供名称,我能够映射到参数(ASP.NET Core 2.1):
客户端:
<form method="post" enctype="multipart/form-data" action="...">
<input type="file" name="myFile" required />
<input type="password" name="myPass" required />
<input type="submit" value="post" />
</form>
服务器端:
[HttpPost()]
public async Task<IActionResult> Post(IFormFile myFile, [FromForm]string myPass)
{
//...
}
您的代码看起来非常好,只要您使用您在问题上发布的相同版本的代码,它就应该可以工作。 我有一种非常强烈的感觉,即您对ModelState.IsValid
表达式变得false
,因此看到了某种意外行为。
FileExtensions
数据注释应该与String
类型属性一起使用,而不是与IFormFile
类型属性一起使用。 由于这个原因, IsValid
返回 false。
所以从你的视图模型中删除它。
public class EmailForm
{
[Display(Name = "Add a picture")]
[DataType(DataType.Upload)]
public IFormFile SubmitterPicture { get; set; }
}
这是来自团队成员之一的相关 GH 问题和解释,供您参考。
同样,如果有人在 .Net Core 2.1 中工作并使用asp-for
为您的输入元素绑定模型,则不要为该<input>
元素提供 name 和 id 属性。 理想情况下,在浏览器上呈现时的InputTagHelper
会生成name and id
属性及其值。 如果您为 name 和 id wrt 模型类提供相同的值,那么一切正常。 否则,系统不知道它应该绑定到哪个模型属性。 更好的方法是不在<input>
上提供 id 和 name 下面是示例代码。
<form id="uploadForm" enctype="multipart/form-data" name="uploadForm" asp-action="UploadExcel" method="post">
<div class="form-group form-group-lg form-group-sm row ">
<div class="col-sm-12 col-md-10 col-lg-10 uploadDiv" style="display: flex !important">
<label asp-for="FileName" class="col-sm-12 col-md-10 col-lg-10" style="font-size: 15px; max-width: fit-content ">File Name :</label>
<input asp-for="FileName" class="form form-control fileName"
type="text"
placeholder="Enter your file name" />
<!--File upload control-->
<label asp-for="FileName" class="col-sm-12 col-md-10 col-lg-10" style="font-size: 15px; max-width: fit-content ">Attachment :</label>
<input asp-for="File" required class="form-control" type="file" placeholder="File Name" />
</div>
</div>
<div class=" form-group form-group-lg form-group-sm row">
<span asp-validation-for="FileName" class="text-danger"></span>
</div>
<div class=" form-group form-group-lg form-group-sm row">
<small>Please upload .xls or .xlxs or json or xml formatted files only</small>
</div>
<div class="form-group form-group-lg form-group-sm row">
<div class="col-sm-12 col-md-10 col-lg-10">
<input type="submit" class="btn btn-primary" name="submit" id="fileUploadButton" value="Upload" />
<input type="reset" class="btn btn-Gray" name="result" id="resetButton" value="Reset" />
</div>
</div>
<a asp-action="DownloadTemplate" asp-controller="Download" title="Click to download template">Import Batch Transactions Template</a>
</form>
模型.cs
public class ExcelUploadViewModel
{
/// <summary>
/// Gets or Sets the FileName
/// </summary>
[Required(ErrorMessage = "FileName is required")]
public string FileName { get; set; }
[Required(ErrorMessage = "File is required")]
[DataType(DataType.Upload)]
[FromForm(Name = "File")]
public IFormFile File { get; set; }
}
谢谢你。
我遇到了这个问题,解决方法是确保“input type="file"”的元素设置了 id 和 name。 然后,在控制器中,将 IFormFile 参数名称设置为完全相同,大小写也是如此。 G-幸运
将以下内容添加到我的控制器为我解决了这个问题。 这是因为我的文件很大。 根据需要调整限制。
[RequestFormLimits(ValueLengthLimit = int.MaxValue, MultipartBodyLengthLimit = int.MaxValue)]
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.