为什么这个AJAX表单在MVC5中不起作用?

时间:2014-06-17 21:58:19

标签: jquery ajax asp.net-mvc asp.net-mvc-5

我正在为使用.NET 4.5的ASP.NET MVC 5应用程序(Razor引擎)中使用的网站构建一个联系表单。表单显示正确,似乎也正确验证,但AJAX部分根本不起作用。

这个想法是当用户按下SUBMIT并且所有验证成功时,通过AJAX联系服务器以发送电子邮件。在此期间,页面应显示"正在进行中"旋转图标,我们看到所有AJAX的东西。完成后,服务器返回一个JSON响应,指示它是否成功以及消息。然后,当该过程结束时,该信息将显示在divResult上。

但正如我所说,当我按下提交时显示进度动画,发送电子邮件而不是在我的DIV中获取JSON结果,整个页面将被原始JSON响应替换。我在这里缺少什么?

我的EmailModel如下(为简洁省略了验证属性):

public class EmailModel {
    [Required]
    public string Subject { get; set; }
    [Required]
    public string FromEmail { get; set; }
    [Required]
    public string FromName { get; set; }
    [Required]
    public ItemViewModel Receptor { get; set; }
    [Required]
    public string MessageBody { get; set; }
}

" Receptor"只是一个构造,我在其中显示联系表单中的标签列表而不是电子邮件地址,例如"信息","反馈"等。它在视图中显示为带有给定"标签的下拉列表"其中一个是预先选定的。

我的ItemViewModel如下所示:

public class ItemViewModel {
    public string SelectedId { get; set; }
    public IEnumerable<SelectListItem> Items { get; set; }
}

控制器视图方法非常简单,它只是创建一个EmailModel模型实例并设置所有值。然后控制器方法返回一个ActionResult,如下所示:

EmailModel model = new EmailModel() { ... properties set here ... }
return view(model);

该视图将调用以下控制器方法(Post),它也可以正常工作:

[HttpPost]
public JsonResult SendContactMail(Models.EmailModel model) {
    ResponseModel response;
    try {
        if (ModelState.IsValid) {
             response = SendEmail(model);   // pretty obvious what it does and it works
        } else {
            response = new ResponseModel { Success = false, ResponseText = "hum..." };
        }
    } catch (Exception ex) {
         response = new ResponseModel { Success = false, ResponseText = ex.Message };
    }   
}

最后,我的Razor视图或多或少看起来像这样:

@model Models.EmailModel;
@using System.Web.Mvc.Ajax;
@{
    ViewBag.Title = "contact form";
    System.Web.Mvc.Ajax.AjaxOptions ajaxopts = new AjaxOptions() { 
    HttpMethod = "Post", InsertionMode = InsertionMode.Replace, UpdateTargetId = "divResult",
    OnBegin = "OnBegin", OnComplete = "OnComplete", OnSuccess = "OnSuccess", OnFailure = "OnFailure"
};    

@using (Ajax.BeginForm("SendContactMail", "Mail", null, ajaxopts, 
            new { @encType = "multipart/form-data", @id = "contactusform", 
                  @name = "contactusform" }))
{
    @Html.AntiForgeryToken()
    @Html.ValidationSummary(true)

    <div class="editor-label">
        @Html.LabelFor(model => model.Subject)
    </div>
    <div class="editor-field">
        @Html.EditorFor(model => model.Subject)
        @Html.ValidationMessageFor(model => model.Subject)
    </div>

    <div class="editor-label">
        @Html.LabelFor(model => model.FromEmail)
    </div>
    <div class="editor-field">
        @Html.EditorFor(model => model.FromEmail)
        @Html.ValidationMessageFor(model => model.FromEmail)
    </div>

    <div class="editor-label">
        @Html.LabelFor(model => model.FromName)
    </div>

    <div class="editor-field">
        @Html.EditorFor(model => model.FromName)
        @Html.ValidationMessageFor(model => model.FromName)
    </div>

    <div class="editor-label">
        @Html.LabelFor(model => model.Receptor)
    </div>
    <div class="editor-field">
        @Html.DropDownListFor(model => model.Receptor.SelectedId, Model.Receptor.Items, new { @class = "select1" })
        @Html.ValidationMessageFor(model => model.Receptor)
    </div>

    <div class="editor-label">
        @Html.LabelFor(model => model.MessageBody)
    </div>
    <div class="editor-field">
        @Html.EditorFor(model => model.MessageBody)
        @Html.ValidationMessageFor(model => model.MessageBody)
    </div>

    <p>
        <input type="submit" name="operation" id="process" value="Send" class="btn btn-info" />
    </p>
    </fieldset>

<div id="divProcessing" style="text-align: center;">
    <img src="/Images/ajax-loader.gif" /><br />
    <p>@Resources_Controller_Mail.Msg_SendingEmail</p>
</div>
<div id="divMsg"></div>
<div id="divResult"></div>

}  @* ajax.beginform *@

@section Scripts {
    @Scripts.Render("~/bundles/jqueryval")

    <script type="text/javascript">

        $(document).ready(function () {
            // Hide the "busy" Gif at load:
            $("#divProcessing").hide();
            $("#divMsg").hide();

            // Attach click handler to the submit button:
            $('#process').click(function () {
                $('#contactusform').submit();
            });

            // Handle the form submit event, and make the Ajax request:
            $("#contactusform").on("submit", function (event) {
                event.preventDefault();

                // Show the "busy" Gif:
                $("#divProcessing").show();
                $("#divResult").empty();
                var url = $(this).attr("action");
                var formData = $(this).serialize();
                $.ajax({
                    url: url,
                    type: "POST",
                    data: formData,
                    dataType: "json",
                    success: function (resp) {

                        // Hide the "busy" gif:
                        $("#divProcessing").hide();

                        // Do something useful with the data:
                        // var image = resp.Success ? "/Images/Yes.png" : "/Images/No.png";
                        //$("<h3><img src=\"" + image + "\"/></h3>" + "<p>" + resp.ResponseText + "</p>").appendTo("#divResult");
                        $("<h3>" + resp.Success + "</h3>" + "<p>" + resp.ResponseText + "</p>").appendTo("#divResult");
                    }
                })
            });
        });

        function OnBegin() {
            $("#divMsg").append("Ajax Begins");
            $("#divMsg").show();
        }
        function OnComplete() {
            $("#divMsg").append("Ajax Complete");
            $("#divMsg").show();
        }
        function OnSuccess() {
            $("#divMsg").append("Success");
            $("#divMsg").show();
        }
        function OnFailure() {
            $("#divMsg").append("Failed");
            $("#divMsg").show();
        }
    </script>
}

现在在有人要求之前...布局在HTML 表单标签关闭之后在视图中插入/呈现以下内容,并且正好在上面显示的具有 .ready()的脚本之前功能:

    <script src="/Scripts/jquery-1.10.2.js"></script>
    <script src="/Scripts/bootstrap.js"></script>
    <script src="/Scripts/respond.js"></script>
    <script src="/Scripts/jquery.validate.js"></script>
    <script src="/Scripts/jquery.validate.unobtrusive.js"></script>

并按照建议在HEAD部分插入(感谢提示!)。它们来自MicrosoftMvcAjax.Mvc5 NuGet包,它将它们放在〜/ Scripts文件夹中:

<script type="text/javascript" src="/Scripts/MicrosoftAjax.js"></script>
<script type="text/javascript" src="/Scripts/MicrosoftMvcAjax.js"></script>

总结......

  • 为什么视图上没有AJAX进度活动?
  • 为什么视图在提交时的行为类似于常规HTTP帖子(没有ajax)?

2 个答案:

答案 0 :(得分:1)

您没有包含ajax

<script src="/Content/MicrosoftAjax.debug.js" type="text/javascript"></script>
<script src="/Content/MicrosoftMvcAjax.debug.js" type="text/javascript"></script>

http://www.hanselman.com/blog/ASPNETMVCPreview4UsingAjaxAndAjaxForm.aspx

答案 1 :(得分:1)

在您的HTML中:

 <input type="submit" name="operation" id="process" value="Send" class="btn btn-info" /> ...

使用:

<button id="process" value="Send" class="btn btn-info" >Submit</button> ...

并在JS中改变了

    // Handle the form submit event, and make the Ajax request:
                $("#contactusform").on("submit", function (event) {
                    event.preventDefault();
// Show the "busy" Gif:
                $("#divProcessing").show();
                $("#divResult").empty();
                var url = $(this).attr("action");
                var formData = $(this).serialize();

 // Handle the form submit event, and make the Ajax request:
                $("#process").on("click", function (event) {
                    event.preventDefault();
// Show the "busy" Gif:
                $("#divProcessing").show();
                $("#divResult").empty();
                var url = $('#contactusform').attr("action");
                var formData = $('#contactusform').serialize();