1

我正在使用带有 Jquery 对话框的 MVC C#。当我做一个 POST 时,我被重定向到一个普通页面而不是对话框。

这是我的代码的样子:

内部视图:

    <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);
                           }
                         }  
                  });
                 }

它会很好地转到 url 并显示对话框。当我进行 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 会很好。我认为我的问题之一是当我执行重定向操作时,对话框不再打开..

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

4

1 回答 1

1

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

  1. 您想在 jQuery UI 对话框中显示包含表单的部分视图
  2. 此表单包含一个文件上传输入,允许用户从他的计算机选择文件并将其上传到服务器
  3. 您希望此上传使用 AJAX 异步进行
  4. 如果上传成功,您要感谢用户上传文件并关闭 jQuery 对话框
  5. 如果在请求期间出现错误,您希望向用户显示错误消息。例如,如果他没有选择任何文件,即使此字段是必需的

如果我不理解您的某些目标,您可以停止阅读我的答案并更新您的问题,以提供有关您到底想要实现什么的更多信息。

这里的挑战在于上传带有 AJAX 请求的文件。如您所知,这对于标准技术是不可能的。虽然有很多解决方法。您可以使用一个插件,例如UploadifyorFineUploader或使用新的插件,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>

简单:一个包含锚点的强类型视图,该锚点随后(见我的回答后面)将被 AJAX 化,以便在 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>
}

再一次,这里很标准的东西 => 一个包含文件输入的 HTML 表单,允许用户选择要上传的文件。

最后一步当然是让这一切变得生动的javascript。您可以将此 javascript 放在您从 _Layout 覆盖的索引视图内的脚本部分中。理想情况下,脚本应该放在文档的末尾,在结束</body>标记之前(这就是我不将.click()处理程序订阅包装在 a 中的原因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 File API 上传文件的表单提交。

于 2013-02-04T21:01:39.530 回答