[翻译]ASP.NET MVC 3 开发的20个秘诀(十四)[20 Recipes for Programming MVC 3]:使用Ajax提交Form...

议题

当你有一个页面,其中列出重要细节并希望用户可以快速而方便的填写并提交表单,而不需要重新载入整个页面,或在网站上跳转而失去当前导航的页面。

 

解决方案

使用AjaxHelper类,创建一个使用Ajax提交并自动更新现有内容的新表单。

 

讨论

下面这个例子与之前的秘诀一起,演示如果允许用户在页面没有刷新的情况下查看评论并提交评论。

 

首先,创建新的模型用于存储书的评论。右键单击“Models”文件夹,然后选择“添加”“类”,将其命名为“BookComment.cs”。此模型将用于提交和存储书籍的评论:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.ComponentModel.DataAnnotations;

namespace MvcApplication4.Models
{
public class BookComment
{
public int ID { get; set; }
[Required]
public string Comment { get; set; }
public DateTime Created { get; set; }
public int BookId { get; set; }
public virtual Book Book { get; set; }
}
}

接下来,就需要修改BookDBContext必须添加这个表的引用。这个类中已包含之前创建的“Book”模型类。在这个时候,我们需要专门创建一个新文件来存储这个类,因为它会继续增长,可能需要添加你项目中的其他的表。再次右键单击“Models”文件夹,选择“添加”“类”。将其命名为“BookDBContext”:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Data.Entity;

namespace MvcApplication4.Models
{
public class BookDBContext : DbContext
{
public DbSet<Book> Books { get; set; }
public DbSet<BookComment> BookComments { get; set; }
}
}

这是,需要重新编译应用程序,使新创建的模型在下一步可以被引用。

 

编译完成后,接下来必须创建一个新的控制器来创建和管理评论信息。右键单击“Controllers”文件夹,选择“添加”“控制器”。将其命名为“BookCommentsController.cs”。为了减少输入,选择使用实体框架的方式,模型类型,选择新创建的“BookComment”模型类。数据上下文中选择之前创建的“BookDBContext”,选择完毕后,点击“添加”。

 

当程序下次运行时,会接收到一个错误提示。表明在最后一次使用之后,BookDBContext已经发生改变,我们需要创建一个DBContext初始化方法,这并不是要发布网站,而是在初始化时删除并重新创建数据库。执行此操作,请右键单击“Models”文件夹,并选择“添加”“类”。将其命名为“BookInitializer.cs”:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Data.Entity;

namespace MvcApplication4.Models
{
public class BookInitializer :
DropCreateDatabaseIfModelChanges<BookDBContext>
{
}
}

接下来,修改Global.asax.cs文件,在Application_Start中调用BookInitializer

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
using MvcApplication4.Models;
using System.Data.Entity;
using System.Globalization;
using System.Threading;

namespace MvcApplication4
{
public class MvcApplication :
System.Web.HttpApplication
{
...
protected void Application_Start()
{
Database.SetInitializer<BookDBContext>(new BookInitializer());
...
}
...
}
}

 

设置工作全部完成,是时候对“Books”文件夹中“Details”视图进行一些修改以允许用户用Ajax提交书籍评论,这也是添加和实现评论最合理的位置:

@model MvcApplication4.Models.Book
@{
ViewBag.Title = "Details";
}
<h2>Details</h2>
<fieldset>
<legend>Book</legend>
<div class="display-label">Title</div>
<div class="display-field">
@Html.DisplayFor(model => model.Title)
</div>
<div class="display-label">Isbn</div>
<div class="display-field">
@Html.DisplayFor(model => model.Isbn)
</div>
<div class="display-label">Summary</div>
<div class="display-field">
@Html.DisplayFor(model => model.Summary)
</div>
<div class="display-label">Author</div>
<div class="display-field">
@Html.DisplayFor(model => model.Author)
</div>
<div class="display-label">Thumbnail</div>
<div class="display-field">
@Html.DisplayFor(model => model.Thumbnail)
</div>
<div class="display-label">Price</div>
<div class="display-field">
@Html.DisplayFor(model => model.Price)
</div>
<div class="display-label">Published</div>
<div class="display-field">
@Html.DisplayFor(model => model.Published)
</div>
</fieldset>
<fieldset>
<legend>Comments</legend>
<div id="Comments">
@{Html.RenderAction("Index", "BookComments",
new { BookId = Model.ID });}
</div>
</fieldset>
<p>
@Html.ActionLink("Edit", "Edit", new { id=Model.ID }) |
@Html.ActionLink("Back to List", "Index")
</p>

 

在上面这个示例中,在书籍细节后面创建了新的<fieldset>标记,在<fieldset>标记中添加新的idComments<div>标记。在这个<div>Html标记中,执行HTML.RenderAction方法,将当前书籍ID作为参数传回给BookCommentsIndex方法。

 

接下来,修改BookComments中的Index视图。在下面示例中,创建的新链接在不刷新页面的情况下,通过Ajax提交并显示表单。当Ajax调用完成,将更新链接下面id为“AddComment”的<div>标记,显示添加评论的表单。在完成的时候,会添加删除评论的链接,当前没有提供管理评论的功能,只能添加评论。

@model IEnumerable<MvcApplication4.Models.BookComment>
@{
ViewBag.Title = "Index";
}
<h2>Index</h2>
<p>
@Ajax.ActionLink("Create New", "Create", new {
BookId = ViewBag.BookId },
new AjaxOptions { UpdateTargetId = "AddComment" })
</p>
<div id="AddComment"></div>
<table>
<tr>
<th>
Comment
</th>
<th>
Created
</th>
</tr>
@foreach (var item in Model) {
<tr>
<td>
@Html.DisplayFor(modelItem => item.Comment)
</td>
<td>
@Html.DisplayFor(modelItem => item.Created)
</td>
<td>
@Html.DisplayFor(modelItem => item.Book.Title)
</td>
</tr>
}

</table>

最后,需要修改自动生成的BookComments/Create视图。用Ajax.BeginForm替换Html.BeginForm,另外定义名为ReloadCommentsJavascript函数,在Ajax提交完成时调用这个函数。此函数执行了一个JQueryAjax请求,检索更新的评论列表。还创建了一个名为“BookId”的表单隐藏项。

@model MvcApplication4.Models.BookComment
@{
ViewBag.Title = "Create";
}

<h2>Create</h2>
<script src="@Url.Content("~/Scripts/jquery.validate.min.js")"
type
="text/javascript"></script>
<script src="
@Url.Content("
~/Scripts/jquery.validate.unobtrusive.min.js")"
type
="text/javascript"></script>
<script type="text/javascript">
function ReloadComments() {
$(
"#Comments").load("@Url.Content(
"~/BookComments/Index?BookId=" + ViewBag.BookId)");
}
</script>
@using (Ajax.BeginForm(new AjaxOptions {
OnComplete="ReloadComments()" }))
{
@Html.Hidden("BookId", (int)ViewBag.BookId);
@Html.ValidationSummary(true)
<fieldset>
<legend>BookComment</legend>
<div class="editor-label">
@Html.LabelFor(model => model.Comment)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.Comment)
@Html.ValidationMessageFor(model => model.Comment)
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>

}

完成这个之后,需要对BookCommentsController进行些修改:

 

using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using MvcApplication4.Models;

namespace MvcApplication4.Controllers
{
public class BookCommentsController : Controller
{
private BookDBContext db = new BookDBContext();
//
// GET: /BookComments/
public ActionResult Index(int BookId)
{
ViewBag.BookId = BookId;
var bookcomments = db.BookComments.Include(
b => b.Book).Where(b => b.BookId == BookId);
return PartialView(bookcomments.ToList());
}

//
// GET: /BookComments/Create
public ActionResult Create(int BookId)
{
ViewBag.BookId = BookId;
return PartialView();
}

//
// POST: /BookComments/Create
[HttpPost]
public ActionResult Create(BookComment bookcomment)
{
if (ModelState.IsValid)
{
bookcomment.Created = DateTime.Now;
db.BookComments.Add(bookcomment);
db.SaveChanges();
}
ViewBag.BookId = bookcomment.BookId;
return PartialView(bookcomment);
}
protected override void Dispose(bool disposing)
{
db.Dispose();
base.Dispose(disposing);
}
}
}

在上面的这个例子中,Index方法接受一个名为BookId的整型参数,并赋值给ViewBag。在其他控制器的这个方法中会返回完整的视图内容,但是在这里只返回分布视图的部分(防止显示完整视图)。如果你还记得刚才的例子,你需要在实现Ajax请求完成时,禁用Layout模版功能。但是这个例子通过Ajax获取的仅仅只会返回分布视图的部分。

 

最后,在完成时需要修改Create方法,第一个Create就像之前Index方法一样接受BookId参数,并返回一个分布视图结果。第二个Create方法会为提交的BookComment对象的Created属性为当前时间,并将评论存储到数据库中并返回一个分布视图。EditDetailsDelete方法以及它们的视图都可以删除掉了,因为它们都没有使用过。

 

现在,当用户查看书籍详情时,他们就可以在页面中看到关于书籍的评论或通过点击“Create New“的链接,输入他们的评论内容,点击“提交”,在不刷新页面的情况下提交并看到更新的评论。

 

参考

原书地址 书籍源代码

转载于:https://www.cnblogs.com/o2ds/archive/2011/12/18/2291999.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值