[英]IFormFile always null (ASP.NET Core with MVC/Razor)
I have an ASP.NET Core MVC app attempting to upload an IFormFile.我有一个尝试上传 IFormFile 的 ASP.NET Core MVC 应用程序。 However, the IFormFile is always null.
但是,IFormFile 始终为空。 None of the other solutions I've found have solved this issue.
我发现的其他解决方案都没有解决这个问题。 What am I doing wrong?
我究竟做错了什么?
Model模型
public class EmailForm
{
[Display(Name = "Add a picture")]
[DataType(DataType.Upload)]
[FileExtensions(Extensions = "jpg,png,gif,jpeg,bmp,svg")]
public IFormFile SubmitterPicture { get; set; }
}
Controller控制器
public async Task<ActionResult> Contribute([Bind("SubmitterPicture")] EmailForm model)
{
if (ModelState.IsValid)
{
//Do some stuff
}
}
View看法
<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="multipart/form-data"
enctype="多部分/表单数据"
The multipart form data is the key.多部分表单数据是关键。
You can alternatively get the file from the HttpContext.Request.Form.Files
and get rid of the IFormFile
interface in your model.您也可以从
HttpContext.Request.Form.Files
获取文件并摆脱模型中的IFormFile
接口。 I recommend this method as I believe that files have nothing to do with data models.我推荐这种方法,因为我认为文件与数据模型无关。
The example would be:这个例子是:
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();
}
If this method also fails, that means there is something wrong with the multipart
request.如果此方法也失败,则意味着
multipart
请求有问题。
After sitting with the same problem for hours I found the solution.在同一个问题坐了几个小时后,我找到了解决方案。
The Problem:问题:
Submitting a single input in a form.在表单中提交单个输入。
The Conclusion:结论:
Basically in your html form this won't work if you only have one input besides the submit button.基本上,在您的 html 表单中,如果除了提交按钮之外只有一个输入,这将不起作用。 My property was no longer null as soon I added another property on my viewModel and another input in my form.
当我在 viewModel 上添加另一个属性并在表单中添加另一个输入时,我的属性不再为空。
I hope this helps someone else.我希望这对其他人有帮助。
Razor Page HTML:剃刀页面 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 Page Code Behind: 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();
}
}
SomeViewModel:一些视图模型:
public class SomeViewModel
{
public IFormFile SingleInput{ get; set; }
public string AnotherInput{ get; set; }
}
I found that by providing names on my html form, I was able to map to parameters (ASP.NET Core 2.1):我发现通过在我的 html 表单上提供名称,我能够映射到参数(ASP.NET Core 2.1):
Client side:客户端:
<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>
Server side:服务器端:
[HttpPost()]
public async Task<IActionResult> Post(IFormFile myFile, [FromForm]string myPass)
{
//...
}
Your code looks perfectly fine and it should work as long as you are using the same version of code you posted on the question.您的代码看起来非常好,只要您使用您在问题上发布的相同版本的代码,它就应该可以工作。 I have a very strong feeling that you are getting
false
for the ModelState.IsValid
expression and hence seeing the some sort of unexpected behavior.我有一种非常强烈的感觉,即您对
ModelState.IsValid
表达式变得false
,因此看到了某种意外行为。
The FileExtensions
data annotation is supposed to be used with String
type properties, not with IFormFile
type properties. FileExtensions
数据注释应该与String
类型属性一起使用,而不是与IFormFile
类型属性一起使用。 Because of this reason, the IsValid
returns false.由于这个原因,
IsValid
返回 false。
So remove that from your view model.所以从你的视图模型中删除它。
public class EmailForm
{
[Display(Name = "Add a picture")]
[DataType(DataType.Upload)]
public IFormFile SubmitterPicture { get; set; }
}
Here is a relevant GH issue and explanation from one of the team member, for your reference.这是来自团队成员之一的相关 GH 问题和解释,供您参考。
FileExtensions Data annotation invalid ModelState #5117 FileExtensions Data annotation 无效 ModelState #5117
Similarly, if anyone working in .Net Core 2.1 and are using asp-for
inorder bind the model for your input elements, then do not give name & id properties for that <input>
elements.同样,如果有人在 .Net Core 2.1 中工作并使用
asp-for
为您的输入元素绑定模型,则不要为该<input>
元素提供 name 和 id 属性。 Ideally, the InputTagHelper
upon the rendering on the browser generates the name and id
properties with their values.理想情况下,在浏览器上呈现时的
InputTagHelper
会生成name and id
属性及其值。 If you give the same value for name & id wrt Model class, then everything works fine.如果您为 name 和 id wrt 模型类提供相同的值,那么一切正常。 Else, system doesn't know to which model property it should bind.
否则,系统不知道它应该绑定到哪个模型属性。 Better approach is not to give id and name on the
<input>
Below is the sample code.更好的方法是不在
<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>
Model.cs模型.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; }
}
Thank you.谢谢你。
I had this issue and the fix was to make sure the element of "input type="file"" had an id and name set.我遇到了这个问题,解决方法是确保“input type="file"”的元素设置了 id 和 name。 Then, in the controller, set the IFormFile parameter name to be exactly the same, case as well.
然后,在控制器中,将 IFormFile 参数名称设置为完全相同,大小写也是如此。 G-luck
G-幸运
Adding the below to my controller fixed the issue for me.将以下内容添加到我的控制器为我解决了这个问题。 It was because my file was large.
这是因为我的文件很大。 Adjust the limits as needed.
根据需要调整限制。
[RequestFormLimits(ValueLengthLimit = int.MaxValue, MultipartBodyLengthLimit = int.MaxValue)]
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.