在 ASP.NET MVC 中使用 AJAX 渲染局部视图和 JSON 数据






4.82/5 (21投票s)
本文解释了如何使用 AJAX 渲染局部视图和 JSON 数据。
引言
本文解释了如何使用 AJAX 渲染局部视图和 JSON 数据。我将本文分为三个部分来理解这两个概念,第一部分描述了这两个概念中通用的基本代码和结构,第二部分描述了如何使用 AJAX 渲染局部视图,最后一部分描述了如何使用 AJAX 在网页上渲染 JSON 数据。
我将通过一个简单的例子来解释这些概念。这个例子是根据出版商在网页上显示书籍。我从下拉列表中选择一个出版商,然后书籍信息将根据该出版商显示在网页上。那么让我们详细看看这个例子。
入门
我将 ADO.NET 实体模型添加到应用程序中,以便执行从“Development
”数据库映射的数据库操作。ADO.NET 实体模型是一种对象关系映射(ORM),它在 ADO.NET 组件之上创建了更高抽象的对象模型。此 ADO.NET 实体模型与“Development
”数据库映射,因此上下文类是继承了 DbContext
类的“DevelopmentEntities
”。
这个“Development
”数据库有两个表,一个是 Publisher
表,另一个是 BOOK
表。两个表都有 1 对多关系,换句话说,一个出版商可以出版多本书,但每本书都与一个出版商相关联。如果您想了解更多关于此应用程序数据库设计的信息,请查阅我的上一篇文章使用 LINQ to SQL 的 MVC 应用程序。
ADO.NET 实体模型映射到这两个表。它的连接字符串与上下文类名同名,并且此连接字符串是在 web.config 文件中创建的。您可以更改连接字符串的名称。上下文类名和连接字符串名称只是一个约定,而不是配置,因此您可以使用有意义的名称进行更改。以下图 1.1 显示了 ADO.NET 实体模型与两个表的映射。
现在 ADO.NET 实体模型已准备好用于应用程序,是时候进入应用程序的下一步,即模型设计,所以让我们看看应用程序的模型。
模型设计
如您所知,应用程序的目的是创建两个实体(Publisher
和 BOOK
),我已经创建了相同的实体,因此我需要创建两个模型,一个用于出版商,另一个用于书籍。
我在 Model 文件夹下创建了一个出版商模型 (Publisher.cs),它包含出版商 ID 和出版商列表,如以下代码片段所示。
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Web.Mvc;
namespace JsonRenderingMvcApplication.Models
{
public class PublisherModel
{
public PublisherModel()
{
PublisherList = new List<SelectListItem>();
}
[Display(Name="Publisher")]
public int Id { get; set; }
public IEnumerable<SelectListItem> PublisherList { get; set; }
}
}
在出版商模型之后,我在同一个文件夹中创建了一个书籍模型 (Book.cs)。它具有与书籍相关的基本属性。以下是书籍模型的代码片段。
namespace JsonRenderingMvcApplication.Models
{
public class BookModel
{
public string Title { get; set; }
public string Author { get; set; }
public string Year { get; set; }
public decimal Price { get; set; }
}
}
现在模型已准备好使用,现在转向控制器。
控制器设计
我创建了两个控制器,一个用于出版商,在下拉列表中显示出版商列表,另一个是书籍控制器,根据出版商显示书籍详情。出版商控制器定义了一个在两个概念中相同的单一操作方法;渲染局部视图和 JSON 数据,而书籍控制器定义了两个操作方法,一个用于局部视图渲染,另一个用于 JSON 数据渲染,因此您将在本文后面看到它。
现在根据 MVC 约定在 Controllers 文件夹下创建出版商控制器 (PublisherController.cs)。此控制器有一个单一的操作方法,用于在视图上显示出版商列表。以下是出版商控制器的代码片段。
using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;
using JsonRenderingMvcApplication.Models;
namespace JsonRenderingMvcApplication.Controllers
{
public class PublisherController : Controller
{
public ActionResult Index()
{
PublisherModel model = new PublisherModel();
using (DAL.DevelopmentEntities context = new DAL.DevelopmentEntities())
{
List<DAL.Publisher> PublisherList = context.Publishers.ToList();
model.PublisherList = PublisherList.Select(x =>
new SelectListItem()
{
Text = x.Name,
Value = x.Id.ToString()
});
}
return View(model);
}
}
}
现在在应用程序的 Controllers 文件夹下创建书籍控制器 (BookController.cs),并将其留空,不带任何操作方法,您将在该控制器中定义两个操作方法,一个用于局部视图渲染,另一个用于 JSON 数据渲染。现在,文章的第一部分已完成,如引言中所述,现在逐个介绍这两种方法。
渲染局部视图
进行 AJAX 请求时,返回 HTML 内容作为结果非常简单。只需使用 PartialView
方法返回一个 ActionResult
,该方法将向调用 JavaScript 返回渲染的 HTML。
现在在书籍控制器中定义一个操作方法,该方法使用 PartialView
返回 ActionResult
。此操作方法根据在此操作方法中作为参数传递的出版商 ID 检索书籍列表。以下是此操作方法的代码片段。
public ActionResult BookByPublisher(int id)
{
IEnumerable<BookModel> modelList = new List<BookModel>();
using (DAL.DevelopmentEntities context = new DAL.DevelopmentEntities())
{
var books = context.BOOKs.Where(x => x.PublisherId == id).ToList();
modelList = books.Select(x =>
new BookModel()
{
Title = x.Title,
Author = x.Auther,
Year = x.Year,
Price = x.Price
});
}
return PartialView(modelList);
}
我在 RouteConfig
类 (App_Start/RouteConfig.cs) 的 RegisterRoute()
方法中为此操作定义了一个路由。
routes.MapRoute("BookByPublisher",
"book/bookbypublisher/",
new { controller = "Book", action = "BookByPublisher" },
new[] { "JsonRenderingMvcApplication.Controllers" });
现在为出版商创建一个视图,该视图包含一个用于出版商的下拉列表,并使用 AJAX 根据出版商下拉列表中选择的值显示书籍详细信息。此视图是一个索引 (Views/Publisher/Index.cshtml)。以下是 Index 视图的代码片段。
@model JsonRenderingMvcApplication.Models.PublisherModel
<script src="~/Scripts/jquery-1.7.1.min.js"></script>
<script type="text/javascript">
$(document).ready(function ()
{
$("#Id").change(function ()
{
var id = $("#Id").val();
var booksDiv = $("#booksDiv");
$.ajax({
cache: false,
type: "GET",
url: "@(Url.RouteUrl("BookByPublisher"))",
data: { "id": id },
success: function (data)
{
booksDiv.html('');
booksDiv.html(data);
},
error: function (xhr, ajaxOptions, thrownError)
{
alert('Failed to retrieve books.');
}
});
});
});
</script>
<div>
@Html.LabelFor(model=>model.Id)
@Html.DropDownListFor(model => model.Id, Model.PublisherList)
</div>
<div id="booksDiv">
</div>
运行应用程序并从出版商下拉列表中选择一个项目。然后您将获得如图 1.2 所示的结果。
渲染 JSON 数据
在上一节中,您已经了解到可以在 AJAX 请求上渲染 HTML,但本节中您将了解只渲染序列化数据,而不是整个 HTML。ASP.NET MVC 以 JsonResult
操作结果的形式提供本机 JSON 支持,它接受一个模型对象,该对象被序列化为 JSON 格式。为了通过 JSON 向控制器操作添加 AJAX 支持,只需使用 Controller.Json()
方法创建一个包含要序列化对象的新 JsonResult
。
现在,在书籍控制器中创建一个操作方法 BooksByPublisherId()
,该方法返回 JsonResult
。此操作方法根据在此操作方法中作为参数传递的出版商 ID 检索书籍列表。以下是此操作方法的代码片段。
public JsonResult BooksByPublisherId(int id)
{
IEnumerable<BookModel> modelList = new List<BookModel>();
using (DAL.DevelopmentEntities context = new DAL.DevelopmentEntities())
{
var books = context.BOOKs.Where(x => x.PublisherId == id).ToList();
modelList = books.Select(x =>
new BookModel()
{
Title = x.Title,
Author = x.Auther,
Year = x.Year,
Price = x.Price
});
}
return Json(modelList,JsonRequestBehavior.AllowGet);
}
创建了操作方法以返回书籍详细信息。这里 Controller.Json()
方法有两个参数,第一个用于将要序列化的数据源,第二个参数是 JsonRequestBehavior.AllowGet
,它明确告知 ASP.NET MVC 框架,在响应 HTTP GET
请求时返回 JSON 数据是可以接受的。
在此案例中,JsonRequestBehavior.AllowGet
参数是必需的,因为默认情况下,ASP.NET MVC 不允许在响应 HTTP GET
请求时返回 JSON,以避免潜在的危险安全漏洞,即 JSON 劫持。
此操作方法返回的 JSON 数据如图 1.3 所示。
我在 RouteConfig
类 (App_Start/RouteConfig.cs) 的 RegisterRoute()
方法中为此操作定义了一个路由。
routes.MapRoute("BooksByPublisherId",
"book/booksbypublisherid/",
new { controller = "Book", action = "BooksByPublisherId" },
new[] { "JsonRenderingMvcApplication.Controllers" });
现在,修改先前创建的出版商 Index 视图,该视图包含一个用于出版商的下拉列表,并使用 AJAX 根据出版商下拉列表中选择的值显示书籍详细信息。以下是 Index 视图的代码片段
@model JsonRenderingMvcApplication.Models.PublisherModel
<script src="~/Scripts/jquery-1.7.1.min.js"></script>
<script type="text/javascript">
$(document).ready(function () {
$("#Id").change(function () {
var id = $("#Id").val();
var booksDiv = $("#booksDiv");
$.ajax({
cache: false,
type: "GET",
url: "@(Url.RouteUrl("BooksByPublisherId"))",
data: { "id": id },
success: function (data) {
var result = "";
booksDiv.html('');
$.each(data, function (id, book) {
result += '<b>Title : </b>' + book.Title + '<br/>' +
'<b> Author :</b>' + book.Author + '<br/>' +
'<b> Year :</b>' + book.Year + '<br/>' +
'<b> Price :</b>' + book.Price + '<hr/>';
});
booksDiv.html(result);
},
error: function (xhr, ajaxOptions, thrownError) {
alert('Failed to retrieve books.');
}
});
});
});
</script>
<div>
@Html.LabelFor(model=>model.Id)
@Html.DropDownListFor(model => model.Id, Model.PublisherList)
</div>
<div id="Div1">
</div>
运行应用程序并从出版商下拉列表中选择一个项目;然后您将获得如图 1.4 所示的结果。
结论
哪个更快?可以说 JSON 数据渲染比局部视图渲染更快。我使用两种方法进行相同的请求,并获得以下表中所示的响应数据(以字节为单位)。
内容类型 | 标题 | 正文 | 总计(字节) |
text/html | 434 | 375 | 809 |
应用程序/json | 398 | 197 | 595 |
当处理少量服务器数据时,这是一个很大的区别。当我使用圆形图表示这些统计数据时,它们看起来像