简体   繁体   English

IFormFile 始终为空(带有 MVC/Razor 的 ASP.NET Core)

[英]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; }
}

Upon Submit提交后在此处输入图像描述

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.

相关问题 IFormFile 在 ASP.NET Core 3.0 MVC 中始终为 NULL - IFormFile is always NULL in ASP.NET Core 3.0 MVC IFormFile 在 asp.net core 2.1 中总是返回 null - IFormFile always return null in asp.net core 2.1 ASP.NET Core MVC:上传的文件很大时,IFormFile 返回 Null - ASP.NET Core MVC: IFormFile return Null when uploaded file is large 如何在asp.net MVC Core的IFormFile中转换byte []? - How to convert byte[] in IFormFile in asp.net MVC Core? IFormFile 在 ASP.NET Core 3.0 中返回 NULL - IFormFile is returning NULL in ASP.NET Core 3.0 ASP.NET Core Web Application using .NET 5.0: IFormFile always null when passing from view to controller - ASP.NET Core Web Application using .NET 5.0: IFormFile always null when passing from view to controller 在ASP.Net Core 2.1 MVC中,TempData始终为空 - TempData is always Null at ASP.Net Core 2.1 MVC 如何在ASP.Net Core 2.0 Razor页面中发布IFormFile? - How do I post an IFormFile in ASP.Net Core 2.0 Razor Pages? 在asp.net核心中调用asp.net mvc 5 Web api,FromBody始终为null - calling asp.net mvc 5 web api in asp.net core, FromBody always null 在IAsyncPageFilter-Asp.Net Core 2.0 Razor Pages中的OnPageHandlerExecutionAsync中,PageResult始终返回null - PageResult always returns null in IAsyncPageFilter - OnPageHandlerExecutionAsync in Asp.Net Core 2.0 Razor Pages
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM