【发布时间】:2014-08-08 01:34:35
【问题描述】:
我正在为带有 .NET 4.5 的 ASP.NET MVC 5 应用程序(Razor 引擎)中使用的网站构建一个联系表单。表单显示正确,并且似乎也可以正确验证,但是 AJAX 部分根本不起作用。
这个想法是,当用户按下提交并且所有验证都成功时,通过 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 form 标记关闭之后和上面显示的具有 .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)?
【问题讨论】:
标签: jquery ajax asp.net-mvc asp.net-mvc-5