在 ASP.NET Core MVC6 中将文件和模型发布到控制器

Posted

技术标签:

【中文标题】在 ASP.NET Core MVC6 中将文件和模型发布到控制器【英文标题】:Posting files and model to controller in ASP.NET Core MVC6 【发布时间】:2016-07-20 17:50:34 【问题描述】:

我正在将一个项目从 ASP.NET RC1 迁移到 ASP.NET Core 1.0。

我有一个视图允许用户上传多个文件中的一个,我使用 Jquery Ajax 发布这些文件。我还在同一篇文章中序列化并发布了一些设置。

以下都在 RC1(和 pre-asp.net 核心)中工作:

Js:

    $('#submit').click(function ()       
        var postData = $('#fields :input').serializeArray();
        var fileSelect = document.getElementById('file-select');
        var files = fileSelect.files;

        var data = new FormData();
        for (var i = 0; i < files.length; i++) 
            data.append('file' + i, files[i]);
        
        $.each(postData, function (key, input) 
            data.append(input.name, input.value);
        );
        var url = '/ajax/uploadfile';
        $.ajax(
            url: url,
            type: "POST",
            contentType: false,
            processData: false,
            cache: false,
            data: data,
            success: function (result) 
                alert('success');                   
            ,
            error: function () 
                alert('error'); 
            
        );
    );

控制器:

  public IActionResult UploadFile(UploadFileModel model)
    
        var result = new JsonResultData();
        try
        
            if (Request.Form.Files.Count > 0)
            
                IFormFile file = Request.Form.Files[0];
                //etc
             
        
     

所以上面的方法不再起作用,没有文件上传,也没有模型绑定。 我设法解决了一半的问题,所以现在我可以让模型与以下代码绑定。但是,控制器仍然会在Request.Files 上给我一个例外。我添加了“标题”属性,并使用了serializeObject(自定义方法)。在控制器中我添加了FromBody

Js:

 $('#submit').click(function ()       
        var postData = $('#fields :input').serializeArray();
        var fileSelect = document.getElementById('file-select');
        var files = fileSelect.files;

        var data = new FormData();
        for (var i = 0; i < files.length; i++) 
            data.append('file' + i, files[i]);
        
        $.each(postData, function (key, input) 
            data.append(input.name, input.value);
        );
        var url = '/ajax/uploadfile';
        $.ajax(
            url: url,
            type: "POST",
            headers: 
                'Accept': 'application/json',
                'Content-Type': 'application/json'
            ,
            processData: false,
            cache: false,
            data: serializeAndStingifyArray(data),
            success: function (result) 
                alert('success');                   
            ,
            error: function () 
                alert('error'); 
            
        );
    );

    function serializeAndStingifyArray(array) 
    var o = ;
    var a = array;
    $.each(a, function () 
        if (o[this.name] !== undefined) 
            if (!o[this.name].push) 
                o[this.name] = [o[this.name]];
            
            o[this.name].push(this.value || '');
         else 
            o[this.name] = this.value || '';
        
    );
    return JSON.stringify(o);
;

控制器:

    [HttpPost]
    public IActionResult UploadFile([FromBody]UploadFileModel model)
    
        var result = new JsonResultData();
        try
        
            if (Request.Form.Files.Count > 0)
            
                IFormFile file = Request.Form.Files[0];
                //etc
             
         
       

html:

    <div id="file-list">
    <input type="file" name="file" class="file-select" accept="application/pdf,application">
    <input type="file" name="file" class="file-select"           accept="application/pdf,application" />
    </div>

【问题讨论】:

您能分享一下您的UploadFileModel 模型的外观吗?还有你的多部分请求是什么样子的? (来自浏览器开发工具) 在这种情况下,上传文件模型只有一个属性,即语言设置(视图中的隐藏字段)。这绑定得很好,问题似乎出在文件发送中,我添加了 html,我不确定您要查找的有关请求的信息。 您的控制器看起来不太正确,请查看HERE 的类似问题。 @Frank 哪一部分不正确?请记住,这是 asp.net core 而不是 mvc 3 作为您链接的问题。 访问Request.Files时遇到什么异常? 【参考方案1】:

我从这篇文章开始,其中的一些代码与您的Upload Files In ASP.NET Core 1.0 几乎相同(参见 Ajax 案例)。

这对我来说在 1.0.0 上工作得很好,所以我实施了你的更改,我看到的是它无法在请求中发送文件(客户端问题)。

这是在 chrome 中使用 F12 正常工作时有效负载的外观:(不确定为什么文件内容被 chrome 隐藏)。

稍作调试,您将错误的数据传递给data.append

修复就在这一行

        $(".file-select").each(function ()  data.append($(this).val(), $(this).get(0).files[0]); i++; )

完整代码:

$(document).ready(function () 
    $("#submit").click(function (evt) 

        var data = new FormData();
        i = 0;

        $(".file-select").each(function ()  data.append($(this).val(), $(this).get(0).files[0]); i++; )

        var postData = $('#fields :input');
        $.each(postData, function (key, input) 
            data.append(input.name, input.value);
        );

        $.ajax(
            type: "POST",
            url: "/ajax/uploadfile",     // <--- Double check this url.
            contentType: false,
            processData: false,
            data: data,
            success: function (message) 
                alert(message);
            ,
            error: function () 
                alert("There was error uploading files!");
            
        );
    );
);

无需使用[FromBody] 或serializeArray()

    [HttpPost]
    public IActionResult UploadFilesAjax(MyViewModel xxx )
    

这是我的html,以防万一:

<form method="post" enctype="multipart/form-data">

<div id="file-list">
    <input type="file" name="file" class="file-select" accept="application/pdf,application">
    <input type="file" name="file" class="file-select" accept="application/pdf,application" />
</div>
<div id="fields">
    <input type="text" name="Email" />
</div>

<input type="button"
        id="submit"
        value="Upload Selected Files" />
</form>

【讨论】:

是的,您对将错误数据传递给 FormData 对象“数据”是正确的,我也注意到了这一点。 很抱歉回复晚了,因为我有一段时间无法查看该特定项目。我尝试了您的解决方案,并设法使用您的代码作为指导使其正常工作。我仍然需要在 $('#fields :input') 选择器上应用 serializeArray() 以序列化正确的字段(例如正确的复选框值和 radiobtn 值。)无论如何,你拯救了我的一天,所以谢谢你 :) 很棒的帖子。 JsonResult 呢?

以上是关于在 ASP.NET Core MVC6 中将文件和模型发布到控制器的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 ASP.NET Core RC2 MVC6 和 IIS7 获取当前 Windows 用户

Asp.Net core MVC6如何在Identity 3中初始添加角色

ASP.NET Core 2.0/Razor Pages - 如何在请求之间将数据保存在 NonFactors MVC6 网格中?

asp.net 5 MVC6 中标签助手和路由属性之间的奇怪行为

微软ASP.NET 电商网站开发实战 MVC6 +HTML5 +WCF+WebAPI+NoSQL+mongoDB+Redis+Core视频 代码 面试题

在 asp .net CORE / MVC 6 应用程序中设置 Swagger 时出现 500 错误