使用MVC从标准Html表单进行局部视图回传

4
我在我的MVC视图上有一个文件上传按钮。文件上传后,页面上的FileList局部视图应该刷新。
我试着使用Ajax.BeginForm()上传,但发现Ajax不会提交文件数据。
现在我已经通过使用jQuery Form插件使文件上传工作了,它允许您将普通的Html.BeginForm()提交方法ajax化。
使用这种方法仍然可以触发局部页面更新吗?
2个回答

3

你可以在 .ajaxForm 中使用 success 选项来传递文件上传的数据,然后将该数据传递给 PartialView 或者刷新 partial。

     // Setup the from plugin
    $('#formId').ajaxForm(
                          success: function(data) { UploadSuccess(data); },
                          dataType: 'json', 
                          iframe:true);
    $('#formId').submit();

    // Success callback fundtion
    function UploadSuccess(data)
    {
        // You can then access any data in the JSON object and pass it in the route to the partial
        $('#divId').load('/FileList/' + data.FileName);
    }

// Original HTML of partial
<div id="divId">
    <%Html.RenderPartial("FileList");%>
</div>

        // Action to handle upload
        public FileUploadJSONResult Upload()
        {
            FileUploadJSONResult result;

            try
            {
                if (Request.Files.Count > 0)
                {
                    //  Logic to save file goes here

                    result = new FileUploadJSONResult()
                    {
                        Data = new
                        {
                            FileName = "Test filename",
                            ErrorMessage = string.Empty
                        }
                    };
                }
                else
                {
                    result = new FileUploadJSONResult
                    {
                        Data = new
                        {
                            FileName = string.Empty,
                            LogicalName = string.Empty,
                            ErrorMessage = "No file to upload. Please select a file to upload."
                        }
                    };
                }
            }
            catch (Exception e)
            {
                Exception root = e;
                while ((root.InnerException) != null)
                {
                    root = root.InnerException;
                }

                result = new FileUploadJSONResult
                {
                    Data = new
                    {
                        FileName = string.Empty,
                        LogicalName = string.Empty,
                        ErrorMessage = root.Message
                    }
                };
            }

            return result;
        }

// Then needed to wrap the JSON result due to the iframe textarea issue with this plugin
public class FileUploadJSONResult : JsonResult
    {  
        /// <summary>
        /// The following explanation of this code is from http://www.malsup.com/jquery/form:
        /// 
        ///  Since it is not possible to upload files using the browser's XMLHttpRequest object, the Form Plugin 
        ///  uses a hidden iframe element to help with the task. This is a common technique, but it has inherent limitations. 
        ///  The iframe element is used as the target of the form's submit operation which means that the server response is 
        ///  written to the iframe. This is fine if the response type is HTML or XML, but doesn't work as well if the 
        ///  response type is script or JSON, both of which often contain characters that need to be repesented using 
        ///  entity references when found in HTML markup.
        ///  To account for the challenges of script and JSON responses, the Form Plugin allows these responses to be 
        ///  embedded in a textarea element and it is recommended that you do so for these response types when used in 
        ///  conjuction with file uploads. Please note, however, that if a file has not been selected by the user for the 
        ///  file input then the request uses normal XHR to submit the form (not an iframe). This puts the burden on your 
        ///  server code to know when to use a textarea and when not to. If you like, you can use the iframe option of the 
        ///  plugin to force it to always use an iframe mode and then your server can always embed the response in a textarea. 
        /// </summary>
        /// <param name="context">Controller context</param>
        public override void ExecuteResult(ControllerContext context)
        {
            this.ContentType = "text/html";
            context.HttpContext.Response.Write("<textarea>");
            base.ExecuteResult(context);
            context.HttpContext.Response.Write("</textarea>");
        }
    }

谢谢,你的答案指引了我正确的方向。实际上这比你说的要简单得多,因为我可以直接从部分视图返回HTML,而不是返回JSON数据对象。 - fearofawhackplanet

2
如果我正确理解了您的问题,您应该能够为jQuery表单插件的success属性提供一个回调函数(查看此链接以获取所有选项:http://jquery.malsup.com/form/#options-object)。然后在这个JavaScript函数内部,您可以对FileList部分视图进行任何更新,不管是使用GET请求来更新部分视图,还是仅捕获jQuery表单插件的成功回调函数中的responseText

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接