在 Microsoft MVC 应用程序中使用 AJAX(带 Entity Framework)
本文介绍如何在基于 Microsoft MVC 框架的应用程序中使用 AJAX。
引言
在本文中,我将解释如何在 MVC 应用程序中使用 AJAX。我将使用 Entity Framework 从数据库获取数据。为了实现局部网页更新,我使用了迷人的 JS 框架 prototype。
开始之前需要准备什么
- Visual Studio 2008 (beta)
- MVC 框架
- ADO.NET Entity Framework
- VS 2008 和 Microsoft .NET 3.5 SP1
- Framework Prototype
任务
我的页面上有两个下拉列表:一个国家列表和一个城市列表。当我从第一个下拉列表中选择一个国家时,第二个下拉列表中的城市列表应该被更新,当然,无需重新加载整个页面。
计划
虽然这个任务很简单,但我认为最好有一个开发计划。
- 数据库 — 国家和城市表
- Entity Framework — 访问数据的接口
- Model — 获取国家和城市列表
- Controller — 用于查看主页并将对象传递给视图的 Action 方法
- 视图
- AJAX (prototype) — 用于将数据加载到下拉列表中的 JavaScript 代码
解决方案
- 数据库 — 我创建了两个表,
Country
和City
。City
通过CountryCode
与Country
连接。 - Entity Framework — 我们应该为访问
Country
和City
等数据库对象生成代码。为此,右键单击“Models”文件夹,然后单击“Add ...”,并选择“ADO.NET Entity Data Model”。然后,我们从列表中选择表:Country、City。单击“Finish”按钮后,Studio 会生成模型和类。要更新此模型(创建后),您应该转到 Model Browser(双击“.edmx”文件),单击根对象,然后从数据库中选择“Update Model”。 - Model — 让我们创建两个类 — 分别用于国家和城市。第一个类
StaticData
包含一个用于获取城市列表的私有方法和一个公共属性。public class StaticData { public List<Country> CountryList { get { return GetAllCountries(); } } private static List<Country> GetAllCountries() { List<Country> countries = null; using (DataCoreConnection context = new DataCoreConnection()) { countries = (from c in context.Country select c).ToList(); } return countries; } }
第二个城市类几乎相同,但构造函数接受一个参数,即城市所属国家的代码。
public class Cities { private string countryCode; public Cities(string CountryCode) { countryCode = CountryCode; } public List<City> CitiesForCountry { get { return GetCitiesForCountry(countryCode); } } private List<City> GetCitiesForCountry(string CountryCode) { List<City> list = null; using (DataCoreConnection context = new DataCoreConnection()) { list = (from c in context.City where c.Country.Code == CountryCode select c).ToList(); } return list; } }
- Controller — 我们使用现有的
HomeController
,因为我们的下拉列表在主页上。我们只添加一个 Action 方法来显示为城市下拉列表提供内容的视图。public void UpdateCities(string code) { Cities cities = new Cities(code); RenderView("SelectCity", cities); }
在这里,我们获取一个城市列表(对象
Cities
)并将其传递给SelectCity
视图。别忘了在 Global.asax 中添加路由规则。routes.Add(new Route("Home/UpdateCities/{code}", new RouteValueDictionary(new { controller = "Home", action = "UpdateCities" }), new MvcRouteHandler()));
- Views — 我们使用两个视图,一个用于包含静态数据的主页,另一个用于包含城市数据的下拉列表。从现有视图开始 — Index.aspx。由于我们应该将
StaticData
对象传递给它,因此我们的视图必须继承自ViewPage
,并且还必须继承自ViewPage<StaticData>
。public partial class Index : ViewPage<StaticData> { }
让我们在页面上显示国家列表。
<select id="selCountry" onchange="UpdateCitiesList();"> <option value="0" selected="selected"><Select a country></option> <% foreach (var country in ViewData.CountryList) { %> <option value='<%= country.Code %>'> <%= country.Name %> </option> <% } %> </select>
这段代码非常简单,所以似乎没有必要解释。我注意到
ViewData
对象具有StaticData
类型,因此我们可以调用其成员而无需任何强制类型转换。稍后将讨论获取城市列表的处理程序UpdateCitiesList()
。现在,让我们创建另一个视图来显示城市。public partial class SelectCity : ViewPage<Cities> { }
然后,添加生成下拉列表内容的的代码。
<option value="0"><Select a city></option> <% foreach (var city in ViewData.CitiesForCountry) { %> <option value='<%=city.Id %>'><%= city.Name %></option> <%} %>
首先,我们应该添加一个指向 prototype 文件的链接(我在母版页上做了)。
<script type="text/javascript" src="<%= Page.ResolveClientUrl("~/Views/Scripts/prototype_p.js") %>"></script>
现在,我们添加一些代码,它将在不重新加载整个页面的情况下从数据库获取数据。
<script type="text/javascript" language="javascript"> function UpdateCitiesList() { if ($('selCountry').value == "0") return; var url = '/Home/UpdateCities/' + $('selCountry').value; new Ajax.Updater('selCities', url, { method: 'get' } ); } </script>
这段代码也很简单。首先,我们定义了下拉列表中哪个元素被选中。如果它是“0”元素(只包含文本“Select ...”),我们就退出函数。否则,我们创建一个 URL 来调用 Controller
Home
和 Action 方法UpdateCities
(带有选定国家的代码),并调用 prototype 库对象Ajax.Updater
。此对象允许我们以异步方式获取数据,即,无需重新加载整个页面。一旦我们选择了一个国家,城市下拉列表就会更新。
加载并打开本文附带的解决方案。您可能会看到一个空白页 Default.aspx(SP1 中的 bug),或者可能看不到。无论如何,您需要使用此地址:localhost:NNN/Home/ 来查看结果。
最新更新
Microsoft 推出了 MVC Prerelease 的第 3 个版本,您可以在 此处加载。别忘了加载 Readme 文件(在下载页面的底部),您可以在其中找到更改的完整列表。我曾尝试按照 Readme 的建议重写我的项目,结果代码完全编译但完全无法运行(路由至今不起作用)。所以我创建了一个新项目(因为路由出于某种原因在这里起作用)并将所有文件迁移到那里。因此,您可以在文章的顶部找到 ASP.NET Prerelease 3 的新项目版本。
您可以在 我的博客 中找到此文章的俄语版本。
欢迎提出评论和建议!