增强 Web 应用程序

概述

本动手实验基于 PlanMyNight 演示,使用了以下技术:MVC 2 Framework、Visual Studio 2010、.Net Framework 4.0、Project Velocity 和 ASP.NET AJAX。

在整个实验中,您将了解如何使用 Project Velocity 增强 ASP.NET MVC 应用程序,如何使用 MVC Areas 设计其结构。

本动手实验假设开发人员具有 HTML、JavaScript、ASP.NET MVC Framework 和 Project Velocity 方面的基本经验。在该培训套件中,您将找到介绍这些技术的实验。

               

目标

在本次动手实验中,您将学习如何:

•              使用 Project Velocity 作为缓存提供程序,增强 MVC 应用程序。

•              使用 MVC 2 Areas 设计应用程序的结构。

               

系统要求

您必须拥有以下内容才能完成本实验:

•             Microsoft Visual Studio 2010 Beta 2

•              Microsoft SQL 2005 或 Microsoft SQL 2008(速成版或更高版本)

•             Project Velocity

◦              可在如下地址下载 Project Velocity:http://www.microsoft.com/downloads/details.aspx?FamilyId=B24C3708-EEFF-4055-A867-19B5851E7CD2&displaylang=en.

注意:如果您对于 Project Velocity 的安装存在疑问,请参考实验:Project

Velocity 简介,在培训包中即可找到。

               

安装

使用 Configuration Wizard 验证本实验的所有先决条件。要确保正确配置所有内容,请按照以下步骤进行。

注意:要执行安装步骤,您需要使用管理员权限在命令行窗口中运行脚本。

1.            如果之前没有执行,运行 Training Kit 的 Configuration Wizard。为此,运行位于 %TrainingKitInstallationFolder%\Labs\IntroToWF\Setup 文件夹下的 CheckDependencies.cmd 脚本。安装先决条件中没有安装的软件(如有必要请重新扫描),并完成向导。

注意:为了方便,本实验中管理的许多代码都可用于 Visual Studio 代码片段。CheckDependencies.cmd 文件启动 Visual Studio 安装程序文件安装该代码片段。

               

练习

本次动手实验由以下练习组成:

1.            练习 1:使用 Velocity 添加缓存

2.            练习 2:使用 MVC Areas 设计应用程序的结构

               

完成本实验的估计时间:60 分钟。

注意:每个练习都附带了一个初始解决方案。这些解决方案中有些代码片段是空的,我们将通过每个练习填写完整。因此,如果直接运行,初始解决方案将无法运行。

在每个练习中,您都可以找到 End 文件夹,其中包括完成练习后应该得到的解决方案。如果需要其他帮助来完成练习,您可以使用该解决方案作为指南。

               

下一步:

练习 1:使用 Velocity 添加缓存

               

练习 1:使用 Velocity 添加缓存

在此练习中,您将了解如何使用 Project Velocity 为 MVC 应用程序添加缓存功能。

注意:有关 Velocity 的更多信息,请访问:http://msdn.microsoft.com/en-us/data/

cc655792.aspx。

任务 1 –配置 Velocity Cluster

在此任务中,您将设置 Project Velocity Cluster,创建具有以下名称的缓存:

•              ActivitySearch:用于缓存给定查询的搜索结果。

•              Activity:用于缓存活动细节。

•              Reference:用于缓存使用数据库中的可用数据填充视图的 States 和 ActivityType 的列表。

Microsoft Velocity 随带了一个命令行管理工具,用于管理群集和缓存。您将使用此工具来启动群集,创建已命名缓存。

1.            启动 Velocity Administration Tool。导航到 Start | All Programs | Microsoft Distributed Cache | Administration Tool - Microsoft Distributed Cache。出现 Velocity Administration Tool。

注意:在使用 UAC 的操作系统上,您必须右键单击 "Velocity" PowerShell 快捷方式,并选择 Run as administrator,缓存管理工具才能正确工作。

2.            键入“get-cachehost”查看主机服务的状态。

注意:服务状态为“DOWN”表示服务还未启动。

3.            键入“start-cachecluster”启动群集。

 

图 1

启动缓存群集

4.            键入“New-Cache –CacheName Activity”创建名为 Activity 的新缓存

 

图 2

创建指定的缓存

5.            使用相同的命令,以 ActivitySearch 和 Reference 替换 Activity,创建相应的缓存。

Script

New-Cache –CacheName ActivitySearch

Script

New-Cache –CacheName Reference

6.            为了验证所有指定缓存均已成功创建,请在 Administration Tool 中键入“Get-Cache”

 

图 3

获取现有缓存

注意:您将看到四个已命名缓存,其中包括您创建的三个已命名缓存(Activity、ActivitySearch 和 Reference),第四个名为 default,是在设置群集时创建的。

               

任务 2 –配置 Plan My Night 以使用 Velocity

创建了已命名缓存之后,您需要添加必要的配置,以便在您的 ASP.NET MVC 应用程序内使用 Project Velocity。为此,执行以下步骤:

1.            从 Start | All Programs | Microsoft Visual Studio 2010 | Microsoft Visual Studio 2010 打开 Microsoft Visual Studio 2010。

2.            打开 %TrainingKitInstallFolder%\Labs\EnhancingAspNetMvcPlanMyNight\Source\Ex01-AddingVelocity\Begin 文件夹中的解决方案文件 Begin.sln,生成解决方案。

注意:此外,也可以使用在完成创建 ASP.NET MVC 应用程序 PlanMyNight 实验之后得到的解决方案。

3.            添加对缓存库的引用

a.            在 Visual Studio 中打开 PlanMyNight 项目,选择 Project | Add Reference…。将出现 Add References 对话框。 

b.            选择 Browse 选项卡。

c.             打开 %ProgramFiles%\Microsoft Distributed Cache\V1.0 文件夹并选择 CacheBaseLibrary.dll 和 ClientLibrary.dll。单击 OK 按钮添加对这些库的引用。

4.            对 Web.Config 做出以下更改:

a.            将以下部分添加到 Web.Config 文件“configuration”部分的开头处:

XML

<configSections>

<section name="dataCacheClient" type="Microsoft.Data.Caching.DataCacheClientSection, CacheBaseLibrary" allowLocation="true" allowDefinition="Everywhere"/>

</configSections>

注意:这将告诉应用程序如何解析 web.config 缓存部分中的信息

b.            将以下代码添加到“configSections”组之后的“configuration”部分:

XML

<dataCacheClient deployment="routing">

<hosts>

<host name="127.0.0.1" cachePort="22233" cacheHostName="DistributedCacheService"/>

</hosts>

</dataCacheClient>

注意:这些部分为 Web 应用程序提供了如何配置缓存的细节。有关配置缓存的更多信息,请访问:http://msdn.microsoft.com/en-us/library/dd169031.aspx

c.             将 Velocity 添加为 SessionState 提供程序。为此,在应用程序的 Web.Config 文件的 <system.web> 部分中添加以下配置:

XML

<system.web>

<sessionState mode="Custom" customProvider="Velocity">

<providers>

<add name="Velocity" type="Microsoft.Data.Caching.DataCacheSessionStoreProvider, ClientLibrary" />

</providers>

</sessionState>

               

任务 3 –创建 Velocity 缓存提供程序

在此任务中,您将创建 Velocity 缓存提供程序,它包含缓存功能,提供了添加、删除和获取各已命名缓存项的能力。

1.            在 Models 内创建一个新文件夹,存储缓存提供程序。

a.            在 Solution Explorer 中,右键单击 Models 文件夹。

b.            指向 Add,并单击 New Folder。

c.             将其命名为 Caching。

2.            在 Caching 文件夹中添加一个名为 ICachingProvider 的接口。

a.            在 Solution Explorer 中,右键单击 Models 下的 Caching 文件夹。

b.            指向 Add,并单击 New Item。

c.             选择  Visual c# 下的 Interface。

d.            键入 ICachingProvider.cs 作为接口名,单击 Add。

3.            替换默认接口实现,以包含 Remove、Get、Add 和 HasKey 方法签名。

(代码片段 – 增强 PlanMyNight MVC 应用程序– ICachingProvider)

C#

namespace PlanMyNight.Models.Caching

{

    using System;

    public interface ICachingProvider

    {

        bool HasKey(string container, string key);

        object Get(string container, string key);

        void Remove(string container, string key);

        void Add(string container, string key, object value, TimeSpan timeout);

    }

}

4.            在 Caching 文件夹内创建 VelocityProvider.cs 类。

a.            在 Solution Explorer 中,右键单击 Models 下的 Caching 文件夹。

b.            指向 Add,并单击 Class。

c.             键入 VelocityProvider.cs 作为类名,单击 Add。

5.            将以下命名空间指令添加到 VelocityProvider.cs 类中。

C#

using Microsoft.Data.Caching;

using PlanMyNight.Models.Caching;

6.            替换类签名,以实现 ICachingProvider 接口。

C#

public class VelocityProvider : ICachingProvider

7.            实现 HasKey 方法。为此,复制 VelocityProvider.cs 类中的以下代码。

(代码片段 – 增强 PlanMyNight MVC 应用程序– VelocityProvider HasKey)

C#

public bool HasKey(string container, string key)

{

    using (var cacheFactory = new DataCacheFactory())

    {

        try

        {

            var cacheContainer = cacheFactory.GetCache(container);

            return cacheContainer.Get(key) != null;

        }

        catch (DataCacheException ex)

        {

            if (ex.ErrorCode == DataCacheErrorCode.RetryLater)

            {

                // temporal failure, ignore and continue

                return false;

            }

            throw;

        }

    }

}

注意:HasKey 方法搜索已命名缓存中的特定键,若存在则返回 true。

请注意,此方法接受容器作为参数。

容器名称将用在所有方法中,识别在其中查找所请求的键的已命名缓存。

8.            实现 Get 方法,检索具有给定键的对象。

(代码片段 – 增强 PlanMyNight MVC 应用程序– VelocityProvider Get)

C#

public object Get(string container, string key)

{

    using (var cacheFactory = new DataCacheFactory())

    {

        try

        {

            var cacheContainer = cacheFactory.GetCache(container);

            return cacheContainer.Get(key);

        }

        catch (DataCacheException ex)

        {

            if (ex.ErrorCode == DataCacheErrorCode.RetryLater)

            {

                // temporal failure, ignore and continue

                return null;

            }

            throw;

        }

    }

}

注意:请注意,该实现非常普通,在所有方法中都是类似的:

1- 使用给定容器名称从 DataCacheFactory 中获取已命名缓存。

2- 使用键和其他参数(若存在)执行操作 (Add、Get、Remove)。

9.            实现 Add 和 Remove 方法。为此,复制 VelocityProvider.cs 类中的以下代码。

(代码片段 – 增强 PlanMyNight MVC 应用程序– VelocityProvider Add Remove)

C#

public void Add(string container, string key, object value, TimeSpan timeout)

{

    if (value == null) return;

    using (var cacheFactory = new DataCacheFactory())

    {

        try

        {

            var cacheContainer = cacheFactory.GetCache(container);

            cacheContainer.Put(key, value, timeout);

        }

        catch (DataCacheException ex)

        {

            if (ex.ErrorCode == DataCacheErrorCode.RetryLater)

            {

                // temporal failure, ignore and continue

                return;

            }

            throw;

        }

    }

}

public void Remove(string container, string key)

{

    using (var cacheFactory = new DataCacheFactory())

    {

        try

        {

            var cacheContainer = cacheFactory.GetCache(container);

            cacheContainer.Remove(key);

        }

        catch (DataCacheException ex)

        {

            if (ex.ErrorCode == DataCacheErrorCode.KeyDoesNotExist)

            {

                return;

            }

            throw;

        }

    }

}

10.          按 CTRL + SHIFT + B 生成解决方案。

               

任务 4 –创建 CachedActivitiesRepository

在此任务中,您将创建 CachedActivitiesRepository。

注意:CachedActivitiesRepository 是 ActivitiesRepository 的装饰器。它为其添加缓存功能。

每个方法从缓存中搜索请求的对象,若未发现资源,则从 ActivitiesRepository 中进行检索,并将其存储在缓存中,以备未来请求之用。

1.            在 Models 文件夹中添加一个名为 CachedActivitiesRepository.cs 的类。

a.            在 Solution Explorer 中,右键单击 Models 文件夹。

b.            指向 Add,并单击 Class。

c.             键入 CachedActivitiesRepository.cs 作为类名,单击 Add。

2.            向 CachedActivitiesRepository.cs 添加以下命名空间指令

C#

using System.Globalization;

using System.Text;

using PlanMyNight.Models.Caching;

using PlanMyNight.Models.Entities;

3.            替换 CachedActivitiesRepository 类签名,以实现 IActivitiesRepository。

C#

public class CachedActivitiesRepository : IActivitiesRepository

4.            将以下变量和构造函数添加到 CachedActivitiesRepository 中

(代码片段 – 增强 PlanMyNight MVC 应用程序– CachedActivitiesRepository 变量和构造函数)

C#

// Container Names

private const string ReferenceDataCacheContainer = "Reference";

private const string ActivityCacheContainer = "Activity";

private const string SearchQueryCacheContainer = "ActivitySearch";

private readonly ICachingProvider cacheProvider;

private readonly IActivitiesRepository activitiesRepository;

public CachedActivitiesRepository() :

    this(new VelocityProvider(), new ActivitiesRepository())

{

}

public CachedActivitiesRepository(ICachingProvider cacheProvider, IActivitiesRepository activitiesRepository)

{

    this.cacheProvider = cacheProvider;

    this.activitiesRepository = activitiesRepository;

}

注意:CachedActivitiesRepository 包含您在任务 1 中创建的已命名缓存的名称。

此外,它还有一个缓存提供程序和活动存储库。首先定义存储库装饰器将使用的缓存实例,其次在数据未存储在缓存中时在其中获取数据的实际存储库。

在调用默认构造函数时,它将创建 VelocityProvider 和 ActivitiesRepository 的实例。随后,调用另外一个构造函数,使用已经创建的实例作为参数。

5.            实现 RetrieveStates 方法。为此,复制 CachedActivitiesRepository.cs 类中的以下代码:

(代码片段 – 增强 PlanMyNight MVC 应用程序– CachedActivitiesRepository RetrieveStates)

C#

public IEnumerable<string> RetrieveStates()

{

    var cacheKey = "states";

    // retrieve states from Cache

    IEnumerable<string> data = this.cacheProvider.Get(ReferenceDataCacheContainer, cacheKey) as IEnumerable<string>;

    if (data != null)

    {

        return data;

    }

    // retrieve from Repository

    data = this.activitiesRepository.RetrieveStates();

    this.cacheProvider.Add(ReferenceDataCacheContainer, cacheKey, data, TimeSpan.FromMinutes(60));

    return data;

}

注意:请注意,该方法首先在“Reference”已命名缓存中搜索状态列表,若未找到,则从 ActivityRepository 检索,并将其存储在缓存中,以备未来请求之用。

所有实现的方法都将重复此行为。

6.            实现 Retrieve 方法。为此,复制 CachedActivitiesRepository.cs 类中的以下代码:

(代码片段 – 增强 PlanMyNight MVC 应用程序– CachedActivitiesRepository RetrieveActivity)

C#

public Activity Retrieve (string id)

{

    // retrieve from Cache; the Activity's id is used as key

    Activity data = this.cacheProvider.Get(ActivityCacheContainer, id) as Activity;

    if (data != null)

    {

        return data;

    }

    // retrieve from Repository

    data = this.activitiesRepository.Retrieve (id);

    this.cacheProvider.Add(ActivityCacheContainer, id, data, TimeSpan.FromMinutes(15));

    return data;

}

7.            实现 RetrieveActivityTypes 方法。为此,复制 CachedActivitiesRepository.cs 类中的以下代码:

(代码片段 – 增强 PlanMyNight MVC 应用程序– CachedActivitiesRepository RetrieveActivityTypes)

C#

public IEnumerable<ActivityType> RetrieveActivityTypes()

{

    var cacheKey = "activityTypes";

    // retrieve activityTypes from Cache

    IEnumerable<ActivityType> data = this.cacheProvider.Get(ReferenceDataCacheContainer, cacheKey) as IEnumerable<ActivityType>;

    if (data != null)

    {

        return data;

    }

    // retrieve from Repository

    data = this.activitiesRepository.RetrieveActivityTypes();

    this.cacheProvider.Add(ReferenceDataCacheContainer, cacheKey, data, TimeSpan.FromMinutes(60));

    return data;

}

8.            实现 RateActivity 方法。为此,复制 CachedActivitiesRepository.cs 类中的以下代码:

(代码片段 – 增强 PlanMyNight MVC 应用程序– CachedActivitiesRepository RataActivity)

C#

public void RateActivity(string activityId, byte rating)

{

    // Remove the activity from cache since it's invalid.

    this.cacheProvider.Remove(ActivityCacheContainer, activityId);

    this.activitiesRepository.RateActivity(activityId, rating);

}

注意:请注意,RateActivity 与您实现的方法具有不同的行为。

RateActivity 从缓存中删除活动,随后调用 ActivitiesRepository 的 RateActivity

方法。

这是因为缓存中的活动状态在评级后将失效,因而必须删除。

9.            实现 Search 方法。为此,复制 CachedActivitiesRepository.cs 类中的以下代码:

(代码片段 – 增强 PlanMyNight MVC 应用程序– CachedActivitiesRepository Search)

C#

public PagingResult<Activity> Search(ActivitySearchCriteria criteria)

{

    var cacheKey = Serialize(criteria);

    // retrieve search results from Cache

    PagingResult<Activity> data = this.cacheProvider.Get(SearchQueryCacheContainer, cacheKey) as PagingResult<Activity>;

    if (data != null)

    {

        return data;

    }

    // retrieve from Repository

    data = this.activitiesRepository.Search(criteria);

    this.cacheProvider.Add(SearchQueryCacheContainer, cacheKey, data, TimeSpan.FromMinutes(5));

    // add activities to cache

    foreach (var activity in data.Items)

    {

        if (!this.cacheProvider.HasKey(ActivityCacheContainer, activity.Id))

        {

            this.cacheProvider.Add(ActivityCacheContainer, activity.Id, activity, TimeSpan.FromMinutes(15));

        }

    }

    return data;

}

注意:Search 方法将搜索条件序列化为一个键,并使用它检查所请求的搜索是否已

执行。

请注意,在从 ActivitiesRepository 中检索 PagingResult 之后,所检索到的活动将存储在“Activity”已命名缓存中,以备未来请求之用。

要将搜索条件序列化为一个键,您要创建一个方法,连接使用“|”分隔的 ActivitySearchCriteria 属性。

10.          添加一个名为 Serialize 的方法。为此,复制 CachedActivitiesRepository.cs 类中的以下代码

(代码片段 – 增强 PlanMyNight MVC 应用程序– CachedActivitiesRepository Serialize)

C#

private static string Serialize(ActivitySearchCriteria criteria)

{

StringBuilder sb = new StringBuilder();

    sb.AppendFormat(CultureInfo.InvariantCulture, "{0}", criteria.ActivityTypeId ?? 0);

    if (!string.IsNullOrEmpty(criteria.StreetAddress))

    {

        sb.AppendFormat(CultureInfo.InvariantCulture, "{0}", criteria.StreetAddress);

    }

    sb.Append("|");

    if (!string.IsNullOrEmpty(criteria.State))

    {

        sb.AppendFormat(CultureInfo.InvariantCulture, "{0}", criteria.State);

    }

    sb.Append("|");

    if (!string.IsNullOrEmpty(criteria.City))

    {

        sb.AppendFormat(CultureInfo.InvariantCulture, "{0}", criteria.City);

    }

    sb.Append("|");

    if (!string.IsNullOrEmpty(criteria.Zip))

    {

        sb.AppendFormat(CultureInfo.InvariantCulture, "{0}", criteria.Zip);

    }

    sb.Append("|");

    sb.AppendFormat(CultureInfo.InvariantCulture, "{0}", criteria.StreetAddress);

    sb.Append("|");

    sb.AppendFormat(CultureInfo.InvariantCulture, "{0}", criteria.SortBy);

    sb.Append("|");

    sb.AppendFormat(CultureInfo.InvariantCulture, "{0}", criteria.Page);

    sb.Append("|");

    sb.AppendFormat(CultureInfo.InvariantCulture, "{0}", criteria.PageSize);

    return sb.ToString();

}

11.          按 CTRL + SHIFT + B 生成解决方案。

               

任务5 –更新控制器以使用 CachedActivitiesRepository

在此任务中,您将更新 Home 和 ActivitiesController,以使用 CachedActivitiesRepository 而非 ActivitiesRepository。

1.            在 Solution Explorer 中,双击 HomeController.cs 文件(位于 Controllers 文件夹下)将其打开。

2.            修改默认的构造函数,以创建新的 CachedActivitiesRepository 实现而不是创建 ActivitiesRepository。

C#

        public HomeController() :

            this(new CachedActivitiesRepository())

        {

        }

3.            在 Solution Explorer 中双击 Controllers 文件夹下的 ActivitiesController.cs 文件将其打开。

4.            修改默认的构造函数,以创建新的 CachedActivitiesRepository 实现而不是创建 ActivitiesRepository。

C#

        public ActivitiesController() :

            this(new CachedActivitiesRepository ())

        {

        }

要能够在缓存中存储 PagingResult,您必须为类添加 DataContract 属性,并为其属性添加 DataMember 属性。

5.            在 Solution Explorer 中双击 Models\Entities 文件夹下的 PagingResult.cs 文件将其打

开。

6.            为 PagingResult 类添加以下命名空间指令。

C#

using System.Runtime.Serialization;

7.            使用以下代码替换 PagingResult<T> 实现

(代码片段 – 增强 PlanMyNight MVC 应用程序– PagingResult)

C#

[DataContract]

public class PagingResult<T>

{

    public PagingResult(IEnumerable<T> items)

    {

        this.Items = new List<T>(items);

        this.ItemType = typeof(T).ToString();

    }

     [DataMember]

    public int PageSize { get; set; }

     [DataMember]

    public int TotalItems { get; set; }

     [DataMember]

    public int CurrentPage { get; set; }

    public int TotalPages

    {

        get

        {

            return (int)Math.Ceiling((decimal)this.TotalItems / this.PageSize);

        }

    }

     [DataMember]

    public ICollection<T> Items { get; private set; }

     [DataMember]

    public string ItemType { get; private set; }

}

8.            按 CTRL+SHIFT+B 生成解决方案。

               

               

下一步:

练习 1:验证

练习 1:验证

在此验证中,您将通过检查 Velocity Cache 的工作情况来检查是否已正确执行了练习的所有步

骤。

1.            以管理员身份启动 Velocity Administration 工具。导航到 Start | All Programs | Microsoft Distributed Cache | Administration Tool - Microsoft Distributed Cache。

2.            键入以下命令,检查 ActivitySearch 已命名缓存的统计信息

脚本

Get-CacheStatistics –CacheName ActivitySearch

图 4

ActivitySearch Cache Statistics

请注意,所有值都为 0。

3.            返回 Visual Studio 2010,按 CTRL + F5 在不调试的情况下启动应用程序。

4.            选择 OH 作为 State,单击 Search。

5.            在 Administrator Tool 中键入“Get-CacheStatistics –CacheName ActivitySearch”

 

图 5

ActivitySearch Cache Statistics

注意:请注意,ItemCount 已经增加到 1。

6.            返回浏览器,按CTRL + F5 强制刷新页面。

7.            在 Administrator Tool 中再次键入“Get-CacheStatistics –CacheName ActivitySearch”

 

图 6

ActivitySearch Cache Statistics

注意:请注意,MissCount 值为 1,而 RequestCount 已经增加到 2。这也表示第二个请求发现了所请求键的匹配项。

8.            您可按照相同的步骤处理其他已命名缓存,验证 Velocity 是否处理了请求而非 ActivitiesRepository

注意:如果您需要重置缓存,请使用以下命令:“Restart-CacheCluster”

               

下一步:

练习 2:使用 MVC Areas 设计应用程序结构

               

练习 2:使用 MVC Areas 设计应用程序结构

在此练习中,您将了解如何使用 MVC Areas,通过创建以使用 MVC Areas 添加到解决方案中的 LogOn Project 来设计应用程序的结构。

任务 1 - 创建 LogOn Project

在此任务中,您将创建一个新项目,将用于对访问您的应用程序的用户进行身份验证。

1.            从 Start | All Programs | Microsoft Visual Studio 2010 | Microsoft Visual Studio 2010 打开 Microsoft Visual Studio 2010。

2.            打开 %TrainingKitInstallFolder%\Labs\EnhancingAspNetMvcPlanMyNight\Source\Ex02-StructuringWithMVCAreas\Begin 文件夹下的解决方案文件 Begin.sln,生成解决方案。

注意:此外,也可继续使用完成练习 1 之后获得的解决方案

3.            创建一个新 MVC 2 Web 应用程序,名为 PlanMyNight.LogOn。

a.            为此,在解决方案资源管理器中右键单击 Begin Solution。

b.            指向 Add,并单击 New Project。

c.             选择 Visual C# | Web 下的 ASP.NET MVC 2 Web Application

d.            键入 PlanMyNight.LogOn 作为项目名称,单击 OK。

e.            在提示创建 Unit Test Project 时,选择 No。

4.            由于 PlanMyNight.LogOn 将使用 MVC Areas 部署,因而存在几个不需要的文件。从中删除以下文件:

a.            在项目的根目录下删除 Content 和 Scripts 文件夹,以及 Global.asax 文件。

b.            在 Controllers 文件夹中删除 HomeController.cs 文件。

c.             在 Views 文件夹中删除 Home 和 Shared 文件夹。

5.            接下来,继续从 PlanMyNight 项目中删除所有与登录功能相关的文件:

a.            从 Controllers 文件夹中删除 AccountController.cs 文件。

b.            从 Views 文件夹中删除 Account 文件夹和 Shared 文件夹下的 LogOn User Control。

 

图 7

项目层次结构

6.            为了保持练习简单,将使用 MVC 模板提供的帐户管理功能。为了使模板能够与 MVC Areas 一起使用,您需要更新 RedirectToAction 方法调用来包含 Area 值。为此:

a.            在 solution explorer 中双击 PlanMyNight.LogOn 项目的 Controllers 文件夹下的 AcountController.cs 文件,打开此文件。

b.            按 CTRL + H 打开查找和替换窗口。

c.             在 Find what 框中输入 return RedirectToAction("Index", "Home");

d.            在 Replace with 框中输入 return RedirectToAction("Index", "Home", new { area = "PlanMyNight" });

 

图 8

Find and Replace

e.            确保在 Look in 组合框中选中了 Current Document,单击 Replace All。共应替换三处,分别在 LogOff、LogOn 和 Register 方法中。

注意:Area 值是通过反射检索的,用于搜索将在本练习稍后的部分中注册的正确 Route 值。

 

图 9

替换三处

完成了 PlanMyNight.LogOn 项目之后,将更新 PlanMyNight MVC 应用程序以允许 Logon 功能。

7.            在 solution explorer 中双击 Views\Shared 中的 Site.Master 文件将其打开。

8.            使用以下内容替换当前 navigation “div”声明:

(代码片段 – 增强 PlanMyNight MVC 应用程序–navigation div)

ASP.NET

<div id="navigation">

    <ul>

        <li><%=Html.ActionLink("Search", "Index", "Home", new { area = "PlanMyNight" }, null )%></li>

        <li><a href="#">About</a></li>

        <%

        if (Request.IsAuthenticated) {

        %>

            <li><%=Html.ActionLink("Log Off", "LogOff", "Account", new { area = "PlanMyNight.LogOn" }, null )%></li>

        <%

        } else {

        %>

            <li><%=Html.ActionLink("Log On", "LogOn", "Account", new { area = "PlanMyNight.LogOn" }, null )%></li>

        <%

        }

        %>

    </ul>

</div>

注意:在上述代码中,您为 Search 操作链接添加区域定义,并添加第二个操作链接,显示 LogOn 或 LogOff 链接,并重定向到 PlanMyNight.LogOn 区域。

9.            在 navigation “div”  下添加 toolbar “div”:

(代码片段 – 增强 PlanMyNight MVC 应用程序– toolbar div)

ASP.NET

<% if (Request.IsAuthenticated) { %>

<div id="toolbar">

<span> Welcome <%= Html.Encode(Page.User.Identity.Name) %>!</span>

</>

<% } %>

注意:上述代码将显示一条欢迎消息,仅在用户登录后显示用户名称。

10.          最后一步是在父项目中添加对子项目的引用。为此:

a.            在 Solution Explorer 中,右键单击 PlanMyNight 项目。

b.            单击 Add Reference。

c.             在 Projects 选项卡中选择 PlanMyNight.LogOn 并单击 OK。

 

图 10

添加 PlanMyNight.LogOn 引用。

11.          按 CTRL + SHIFT + B 生成解决方案。

               

任务 2 –为 MVC Areas Project 启用自定义生成

在此任务中,您将修改项目文件,允许 MVC Areas 的自定义生成。

1.            在 Solution Explorer 中右键单击解决方案内的各项目,并选择 Unload Project。

2.            右键单击 PlanMyNight 项目,选择 Edit PlanMyNight.csproj。

 

图 11

编辑 PlanMyNight.csproj。

3.            找到以下标记:

XML

<!-- To enable MVC area subproject support, uncomment the following two lines:

4.            取消注释该标记之后的两行,以启用 MVC 区域子项目支持。

XML

<UsingTask TaskName="Microsoft.Web.Mvc.Build.CreateAreaManifest" .../>

<UsingTask TaskName="Microsoft.Web.Mvc.Build.CopyAreaManifests" .../>

5.            找到以下标记:

XML

<!-- If this is an area parent project, uncomment the following lines:

6.            取消注释此标记之后的两行。

XML

<CreateAreaManifest AreaName="$(AssemblyName)" AreaType="Parent" .../>

<CopyAreaManifests ManifestPath="$(AreasManifestDir)" CrossCopy="false" .../>

7.            保存项目并关闭文件。

8.            重新载入 PlanMyNight 项目。为此:

a.            在 Solution Explorer 中,右键单击 PlanMyNight 项目。

b.            单击 Load Project

c.             当 Visual Studio 检测到您的项目文件中有自定义生成步骤时,将显示一条警告消息。

d.            选择 Load Project Normally 并单击 OK。

9.            右键单击 PlanMyNight.LogOn 项目并选择 Edit PlanMyNight.LogOn.csproj。

10.          找到以下标记:

XML

<!-- To enable MVC area subproject support, uncomment the following two lines:

11.          取消注释该标记之后的两行,以启用 MVC 区域子项目支持。

XML

<UsingTask TaskName="Microsoft.Web.Mvc.Build.CreateAreaManifest" .../>

<UsingTask TaskName="Microsoft.Web.Mvc.Build.CopyAreaManifests" .../>

12.          找到以下标记:

XML

<!-- If this is an area child project, uncomment the following line:

13.          取消注释此标记之后的一行。

XML

<CreateAreaManifest AreaName="$(AssemblyName)" AreaType="Child" .../>

注意:这种自定义会导致某些子区域文件(如视图)在应用程序生成之前被复制到主项目中。

14.          保存项目并关闭文件。

15.          重新载入 PlanMyNight.LogOn 项目。为此:

a.            在 Solution Explorer 中,右键单击 PlanMyNight.LogOn 项目。

b.            单击 Load Project

c.             当 Visual Studio 检测到您的项目文件中有自定义生成步骤时,将显示一条警告消息。

d.            选择 Load Project Normally 并单击 OK。

16.          按 CTRL + SHIFT + B 生成解决方案。

               

任务 3 - 注册路由

1.            在 PlanMyNight.LogOn 项目中,创建一个新的静态类,名为 Routes。

a.            在 Solution Explorer 中,右键单击 PlanMyNight.LogOn 项目。

b.            指向 Add,并单击 Class。

c.             键入 Routes.cs 作为类名,单击 Add。

d.            为类添加以下命名空间指令:

C#

using System.Web.Mvc;

using System.Web.Routing;

e.            将默认类实现替换为以下代码:

(代码片段 – 增强 PlanMyNight MVC 应用程序– Routes 类)

C#

public static class Routes

{

    public const string AreaName = "PlanMyNight.LogOn";

    public static void RegisterRoutes(RouteCollection routes)

    {

        var areaContext = new AreaRegistrationContext(AreaName, routes);

        areaContext.MapRoute(

            "LogOn",

            "PlanMyNight.LogOn/Account/{action}",

            new { controller = "Account" },

            new[] { "PlanMyNight.LogOn.Controllers" });

    }

}

注意:请注意,路由被添加到一个 AreaRegistrationContext 中,而非 RouteCollection。这是由于路由被映射到 PlanMyNight.LogOn 区域。这允许拥有位于不同区域中的相同路由。

2.            修改 Global.asax 文件中的 PlanMyNight 的 RegisterRoutes 方法实现,注册 PlanMyNight.LogOn 路由。为此:

a.            在 solution explorer 中双击 Global.asax 文件。

b.            添加以下命名空间定义:

C#

using PlanMyNight.LogOn;

c.             使用以下代码替换当前 RegisterRoutes 方法实现:

(代码片段 – 增强 PlanMyNight MVC 应用程序– RegisterRoutes 方法)

C#

public static void RegisterRoutes(RouteCollection routes)

{

    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

    Routes.RegisterRoutes(routes);

    var areaContext = new AreaRegistrationContext("PlanMyNight", routes);

    areaContext.MapRoute(

        "Default",                           // Route name

        "{controller}/{action}/{id}",        // URL with parameters

        new { controller = "Home", action = "Index", id = "" },  // Parameter defaults

        new [] { "PlanMyNight.Controllers" }

    );

}

3.            按 CTRL + SHIFT + B 生成解决方案。

               

下一步:

练习 2:验证

练习 2:验证

在此验证中,您将通过检查现在允许登录站点的应用程序来检查是否已正确执行了练习的所有步骤。

1.            按 CTRL + F5 在不调试的情况下启动应用程序。

注意:请注意,应用程序的导航栏中现在有了一个 LOG ON 链接。

 

图 12

LOG ON 链接

2.            单击 LOG ON 链接。

3.            在 LOG ON 页面中,单击 Register 创建新用户。

4.            填写必填数据,创建新用户帐户。

 

图 13

注册页

注意:您可使用模拟数据创建用户帐户,输入以下数据:

     - Username:TestUser

     - Email:test@test.com

     - Password:TestPassword

     - Confirm password:TestPassword

5.            单击 Register 注册用户并登录站点。

注意:在登录到站点之后,请注意屏幕右上角显示的欢迎消息,而且 LOG ON 链接也更改为 LOG OFF

 

图 14

登录首页

下一步:

总结

总结

在本动手实验中,您了解了如何使用 Project Velocity 为 MVC 应用程序添加缓存功能。

此外,您还了解了如何使用 MVC Areas 设计应用程序的结构,并看到了如何利用它们将组件部署到应用程序中。