【问题标题】:IFormFile always null (ASP.NET Core with MVC/Razor)IFormFile 始终为空(带有 MVC/Razor 的 ASP.NET Core)
【发布时间】:2017-09-26 23:02:22
【问题描述】:

我有一个 ASP.NET Core MVC 应用程序尝试上传 IFormFile。但是,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>

【问题讨论】:

  • 您的代码看起来非常好。你怎么知道它是 null ?您是否在您的操作方法中设置了断点并进行了检查?
  • 是的。我在Contribute方法中放了一个断点,发现SubmitterPicture对象始终为null。因此,由于某种原因,此绑定无法正常工作。
  • 我也遇到了同样的问题。到目前为止,我已经学习了 3 个教程,特别是 docs.microsoft.com/en-us/aspnet/core/tutorials/razor-pages/…,但我的 viewmodel 属性始终为空。是否有一些代码需要在启动类中配置?
  • @C.H.我发现了这个问题。如果您提交带有一个输入的表单,您应该在参数中获取变量,因为在这种情况下帖子没有使用视图模型(这是我的假设)。只要您在表单中提交多个属性,您的视图模型就会被填充。请看下面我的回答。 +1 给 OP。

标签: c# asp.net-mvc asp.net-core-mvc


【解决方案1】:
<form method="post" enctype="multipart/form-data">
</form>

enctype="multipart/form-data"

多部分表单数据是关键。

【讨论】:

  • 问题中的代码已经有 enctype="multipart/form-data
  • 我遇到了类似的上传问题。将 enctype="multipart/form-data" 添加到我的表单后,一切正常!非常感谢!!
【解决方案2】:

您也可以从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 请求有问题。

【讨论】:

  • 谢谢 - 今天下午我会试一试,然后告诉你会发生什么。
  • 是的 - 也失败了。任何想法,多部分请求可能有什么问题,甚至从哪里开始?这是我不熟悉的堆栈区域。
  • @C.H. :去掉asp-antiforgery="true"或者设置为false,看看会发生什么。对了,尝试上传一个小文件(1KB的小文本文件),可能超过了请求最大长度限制。
  • @C.H.:试试File[0] 而不是'File["Name"]'。
  • 这些都没有影响。如果我深入研究表单请求,我会看到“文件”的计数为 0,根据我得到的错误,这是有道理的。没有意义的是为什么它是零。
【解决方案3】:

在同一个问题坐了几个小时后,我找到了解决方案。

问题:

在表单中提交单个输入。

结论:

基本上,在您的 html 表单中,如果除了提交按钮之外只有一个输入,这将不起作用。当我在 viewModel 上添加另一个属性并在表单中添加另一个输入时,我的属性不再为空。

我希望这对其他人有帮助。

Razor 页面 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();
        }
    }

SomeViewModel:

public class SomeViewModel
    {
        public IFormFile SingleInput{ get; set; }
        public string AnotherInput{ get; set; }
    }

【讨论】:

  • 谢谢!这是唯一对我有用的解决方案。仅当 IFormFile 在另一个类中时,它才从我的集成测试、邮递员等开始正常工作。似乎没有任何示例或文档提到这一点
【解决方案4】:

我发现通过在我的 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)
{
    //...
}

【讨论】:

    【解决方案5】:

    您的代码看起来非常好,只要您使用与您在问题上发布的相同版本的代码,它就应该可以工作。我有一种非常强烈的感觉,你得到了 falseModelState.IsValid 表达式,因此看到了某种意想不到的行为。

    FileExtensions 数据注释应该与String 类型属性一起使用,而不是与IFormFile 类型属性一起使用。由于这个原因,IsValid 返回 false。

    所以从你的视图模型中删除它。

    public class EmailForm
    {
        [Display(Name = "Add a picture")]
        [DataType(DataType.Upload)]
        public IFormFile SubmitterPicture { get; set; }
    }
    

    这是一个团队成员的相关 GH 问题和解释,供您参考。

    FileExtensions Data annotation invalid ModelState #5117

    【讨论】:

    • 谢谢,但这没有用。该代码正在通过模型验证,并且在尝试读取文件时失败。 SubmitterPicture 始终为空。如果我尝试使用任何更简单的数据类型(即 bool、int、string)的相同代码,它工作正常。
    【解决方案6】:

    同样,如果有人在 .Net Core 2.1 中工作并使用 asp-for 为您的输入元素绑定模型,则不要为该 &lt;input&gt; 元素提供名称和 ID 属性。理想情况下,InputTagHelper 在浏览器上呈现时会生成带有它们的值的name and id 属性。如果您为 name & id w.r.t Model 类提供相同的值,那么一切正常。否则,系统不知道它应该绑定到哪个模型属性。 更好的方法是不要在&lt;input&gt; 上提供 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; }
    }
    

    提交时

    谢谢。

    【讨论】:

      【解决方案7】:

      我遇到了这个问题,解决方法是确保“input type="file"”的元素设置了 id 和 name。然后,在控制器中,将 IFormFile 参数名称设置为完全相同,大小写也是如此。 好运

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-11-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-10-29
        相关资源
        最近更新 更多