MVC Jquery对话框没有出现在POST上

时间:2013-02-01 22:24:12

标签: jquery asp.net-mvc-3 jquery-ui-dialog

我正在使用带有Jquery Dialog的MVC C#。当我执行POST时,我被重定向到正常页面vs 对话框。

以下是我的代码:

内部视图:

    <div id="dialog" title="" style="overflow: hidden;">
    </div>

在我的点击事件中,我有以下内容:

      $('#dialog').dialog({
                   autoOpen: false,
                   width: 500,
                   resizable: true,
                   title: 'PVT Report',
                   modal: true,           
                   buttons: {
                       "Close": function () {
                       $(this).dialog("close");
                        }
                      }
                  });


       $('#dialog').dialog('open');

                 $.ajax({
                           url: url,
                           type: 'GET',
                           success: function(result) {

                           if (result.success) 
                           {
                             $('#dialog').dialog('close');
                          } 
                           else 
                           {
                              $('#dialog').html(result);
                           }
                         }  
                  });
                 }

它转到网址就好了并显示对话框。 当我执行POST时,它确实没有返回到对话框,而是转到常规页面:

以下是我的GET和POST:

     public ActionResult FileUpload(int id)
     {
        var model = new FileUpload { PlNum = id}           
        return PartialView(model);
     }


    [HttpPost]
    public ActionResult FileUpload(HttpPostedFileBase file, FileUpload model)
    {
        // Verify that the user selected a file
        if (file != null && file.ContentLength > 0)
        {
            // extract only the fielname
            var fileName = Path.GetFileName(file.FileName);
            string extension = Path.GetExtension(file.FileName);

            if (extension != ".pdf")
            {
                TempData["ErrMessage"] = "Error, wrong file type. File must be a PDF file.";
                return RedirectToAction("FileUpload", new { id = model.PlNum });
            }

.....

这是我的观点:

@using (Html.BeginForm("FileUpload", "Plt", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
       @Html.HiddenFor(a => a.PlNum)     
       <p>File upload for Pl# @Model.PlNum</p>
       <input type="file" name="file" />
       <input type="submit" value="OK" />
}

我认为用$ .ajax做这件事会很好。我认为我的一个问题是,当我执行redirecttoAction时,对话框不再存在 开..

请注意,无论哪种方式,如果成功或不成功,我都想返回对话框。如果成功,将会显示“成功”的消息。如果不成功,将会出现错误消息。

1 个答案:

答案 0 :(得分:1)

为了确保我已正确理解您的问题,请允许我在回答之前首先重申您的目标。如果我错了,请纠正我。

  1. 您希望在jQuery UI对话框中显示包含表单的部分视图
  2. 此表单包含一个文件上传输入,允许用户从他的计算机中选择文件并将其上传到服务器
  3. 您希望使用AJAX
  4. 异步进行此上传
  5. 如果上传成功,您要感谢用户上传文件并关闭jQuery对话框
  6. 如果请求期间出现错误,您希望向用户显示错误消息。例如,如果他没有选择任何文件,即使需要此字段
  7. 如果我不了解您的一些目标,您可以停止阅读我的答案并更新您的问题,以提供有关您想要实现的目标的更多信息。

    这里的挑战在于使用AJAX请求上传文件。如您所知,标准技术无法做到这一点。但是有很多变通方法。您可以使用UploadifyFineUploader这样的插件,或者使用新的HTML5 File API来实现这一点,并且所有现代浏览器都支持这种插件(不,IE9不是现代浏览器)对不起)。我将介绍lats选项,因为我们在2013年,我们都使用现代浏览器,没有人给出关于IE的...

    因此,在每个ASP.NET MVC应用程序中,我们都可以从设计视图模型开始,该模型将满足我们的视图要求以及我们希望在上载表单中提供的信息:

    public class MyViewModel
    {
        public int Id { get; set; }
    
        [Required]
        public HttpPostedFileBase File { get; set; }
    }
    

    然后我们可以有一个控制器来处理这个过程:

    public class HomeController : Controller
    {
        public ActionResult Index()
        {
            return View();
        }
    
        public ActionResult Upload(int id)
        {
            var model = new MyViewModel
            {
                Id = id
            };
            return PartialView(model);
        }
    
        [HttpPost]
        public ActionResult Upload(MyViewModel model)
        {
            if (!ModelState.IsValid)
            {
                // There was a validation error, probably the user didn't select any file
                // we set the status code to 400 (BadRequest) and return the 
                // same partial which will contain the validation error
                Response.StatusCode = (int)System.Net.HttpStatusCode.BadRequest;
                return PartialView(model);
            }
    
            // at this stage we know that the model is valid => 
            // we could process the uploaded file. In this particular example
            // I am saving the uploaded file to the App_Data folder on the server
            // and ignoring the Id parameter of the view model. Obviously
            // in a more real world application here you might want to store the
            // physical location of this file in your data store as well as it's MIME type
            // so that you could display it later
            var file = Path.Combine(
                Server.MapPath("~/App_Data"), 
                Path.GetFileName(model.File.FileName)
            );
            model.File.SaveAs(file);
    
            // we have finished => let's set the response status code to 
            // 204 (NoContent) so that the client side javascript that I will show
            // later in my answer could distinguish this case from the error scenario
            Response.StatusCode = (int)System.Net.HttpStatusCode.NoContent;
    
            // we will return an EmptyResult because in this particular example
            // I don't really care about returning some information to the client
            // from the server. If you care you could of course set the status code 
            // to 200 (Success) and return, say, a JsonResult here
            return new EmptyResult();
        }
    }
    

    关于这个控制器的说法不多。很标准的东西。用于提供虚拟视图的Index操作,其中包含用于启动上载过程的链接。 Upload(GET)操作为部分上传表单提供服务,当然还有Upload(POST)操作来处理实际的文件上传(在这个过于简化的示例中,我将文件存储在服务器上)。

    然后我们可以得到相应的~/Views/Home/Index.cshtml虚拟视图:

    @model MyViewModel
    @Html.ActionLink(
        "click here to upload a file", 
        "Upload", 
        new { id = 154 }, 
        new { id = "uploadLink" }
    )
    <div id="dialog"></div>
    

    简单:包含锚点的强类型视图随后(在我的回答中稍后会看到)是AJAXified,以便在jQuery对话框和对话框的div占位符中显示上传部分。

    接下来,我们可以编写包含表单(~/Views/Home/Upload.cshtml)的上传部分:

    @model MyViewModel
    
    @using (Html.BeginForm(null, null, new { id = Model.Id }, FormMethod.Post, new { enctype = "multipart/form-data" }))
    {
        <div>
            @Html.LabelFor(x => x.File)
            @Html.TextBoxFor(x => x.File, new { type = "file" })
            @Html.ValidationMessageFor(x => x.File)
        </div>
        <button type="submit">Upload</button>
    }
    

    再次,这里非常标准的东西=&gt;包含文件输入的HTML表单,允许用户选择要上载的文件。

    最后一步当然是javascript,这将使所有这些活跃起来。您可以将此javascript放在Index视图中的一个Scripts部分中,该部分是从_Layout覆盖的。理想情况下,脚本应放在文档的末尾,在结束</body>标记之前(这就是我没有在.click()中包装document.ready处理程序订阅的原因):

    $('#uploadLink').click(function () {
        $.ajax({
            url: this.href,
            type: 'GET',
            cache: false,
            success: function (result) {
                $('#dialog').html(result).dialog({
                    autoOpen: true,
                    width: 500,
                    resizable: true,
                    title: 'PVT Report',
                    modal: true,
                    buttons: {
                        'Close': function () {
                            $(this).dialog("close");
                        }
                    }
                });
            }
        });
        return false;
    });
    
    $('#dialog').on('submit', 'form', function () {
        var xhr = new XMLHttpRequest();
        xhr.open(this.method, this.action);
        xhr.onreadystatechange = function () {
            if (xhr.readyState == 4) {
                if (xhr.status == 204) {
                    // upload was successful => thank the user and close
                    // the dialog
                    alert('Thank you for uploading the file');
                    $('#dialog').dialog('close');
                } else if (xhr.status == 400) {
                    // validation error occurred on the server => redisplay the form
                    $('#dialog').html(xhr.responseText);
                }
            }
        };
        xhr.send(new FormData(this));
        return false;
    });
    

    这个javascript处理了2个事件:点击主视图中的锚点,显示jQuery对话框和将使用AJAX请求和HTML 5文件API上传文件的表单提交。