探索ASP.NET中Tailspin TravelUI层奥秘

2013 年 4 月 22 日5240

在这里我们将从一个实例为大家分析ASP.NETMVC2中的TailspinTravelUI层,51CTO也向您推荐专访微软MVP衣明志:走进ASP.NETMVC2框架开发。以便于大家更好的理解ASP.NETMVC。

  TailspinTravel是一个旅游预订的应用程序示例,最新版本采用ASP.NETMVC2技术构建,主要使用DataAnnotations验证,客户端验证和ViewModels,还展示了许多VisualStudio2010,.NETFramework4,和WindowsServerAppFabric的技术,参看ASP.NETMVC2示例TailspinTravel。

  TailspinTravel设计的技术比较多,今天我们来看看界面(UI)上的技术,在UI层上来说主要采用的技术是ASP.NETMVC2和ASP.NETDynamicData框架。从功能上来分为向普通用户提供的前台页面和管理员使用的后台界面,前台页面主要实现的是旅游活动日程安排,航班,酒店,租车这几部分采用的ASP.NETMVC2技术,管理员用的后台管理页面使用的是ASP.NETDynamicData开发的,这两种技术在网站里的应用有示范作用,对于管理员使用的后台的访问量不可能很大,网站的主要流量是普通用户使用的前台页面,组合使用这两个框架,可以加快网站的开发。

  组合这两种技术,就会碰到一些的问题,第一个问题就是ASP.NET动态数据(DynamicData)默认情况下,动态数据放在web应用的动态数据目录(DynamicData)里,该目录创建在根目录处。你的应用需要移动的不同的位置。在TailspinTravel里面是“admin”目录,动态数据就在这个目录下,然后在Globa.asax.cs文件里

  varmetaModel=newMetaModel();metaModel.RegisterContext(contextFactory,newContextConfiguration{ScaffoldAllTables=true});metaModel.DynamicDataFolderVirtualPath="~/Admin/DynamicData/"

  改变admin/Dynamicdata下文件的内容的引用到新的路径((~/admin/Dynamicdata)

  例如:

  A、修改List.aspx和ListDetails.aspx的注册指令的src属性。

  B、修改List.aspx和母版页的img的src属性。

  C、任何自定义的必须使用新路径的内容。

  ASP.NET4.0有个新特性叫做“自动启动应用程序”,自动启动,先行初始化web应用,而不必等待外部客户端访问web服务器时才启动的能力。这可以有助于你给第一个访问者提供一个更快的回复体验,避免撰写定制脚本来“预热(warmup)”服务器和准备好任何数据缓存。它可用于任何类型的ASP.NET应用,包括基于ASP.NETWebForms和ASP.NETMVC的应用。不过要求在IIS7.5(随Windows7和WindowsServer2008R2发布)上运行ASP.NET4时使用。这个自动启动特性提供了一个可控制的方式来启动一个应用工作进程,初始化ASP.NET应用,然后接受HTTP请求。具体参看ScottGuthrie的文章VS2010和.NET4.0系列之《自动启动ASP.NET应用》篇,TailspinTravel有个类Microsoft.Samples.Tailspin.Web.Infrastructure.ApplicationPreloader,就是用这个特性预先加载应用程序的缓存。

  下面我们来具体分析前台和管理后台:

  前台采用ASP.NETMVC2开发,比较简单,主要是使用ViewModels,HtmlHelper,输出缓存,避免CSRF攻击,查询方法中使用PartialView,以及jQuery和ASP.NETAjax配合的相关内容,可以参考Asp.netMVC2使用经验,性能优化建议学习。

  下面重点来说明一下管理后台的DynamicData的结构,先可以阅读一下ScottGuthrie的文章新的ASP.NET动态数据支持:

  ASP.NET动态数据在进行创建和更新数据时还会对所录入的数据进行验证,这种验证既发生在客户端也发生在服务器端。

  必填字段验证。如果字段不允许为NULL,则录入时必须录入数据。不过这里还有待改进,不允许为NULL,也就成了不允许零长度字符串,而实际应用中NULL和零长度字符串是两回事。纵然不够完美,也已经为我们减轻不少工作量了。

  长度验证。如果字段类型为nvarchar(10),那么就不允许超过10个字符;如果字段类型不是nvarchar(10),而是varchar(10),此时六个汉字也会通过验证,只是无法入库罢了,会返回错误。

  类型验证。比如字段是日期类型,则只允许录入日期。

  ASP.NET动态数据具有自动格式功能:比如bit类型的字段显示为一个多选框,而标识字段不会在插入数据时显示出来。

  ASP.NET动态数据还具有自动识别表关联的功能:比如产品表与产品类别表进行了关联,那么我们在录入产品数据的时候,ASP.NET动态数据会自动以下拉列表的形式显示产品类别。此功能非常不错。

  在网站或者应用程序模板中有两个DynamicData模板,一个是"DynamicData实体模板(DynamicDataEntities)"它是使用ADO.netEntity作为数据模型的,另一个是"DynamicData模板",他是使用LINQTOSQL来作为数据模型。TailspinTravel是以EntityFramework作为数据模型的。

  DynamicData也使用了Routing:

  routes.Add(newDynamicDataRoute("Admin//"){Constraints=newRouteValueDictionary(new{action="List|Edit|Details|Insert"}),Model=metaModel});

  routes.Add的参数为一个DynamicDataRoute对象,而该DynamicDataRoute对象有一个参数为"Admin//.aspx",另外还为该对象指定了两个属性值Constraints和Model。把一个继承自Route的DynamicDataRoute添加到Routing规则表中。

  Constraints=newRouteValueDictionary(new{action="List|Details|Edit|Insert"})

  这句表示约束,这里表示action只能是List、Details、Edit、Insert中的一个。

  可以看出,这四个Aciton是对应着DynamicData/PageTemplates文件夹中的四个页面文件。在那文件夹中还有一个ListDetails.aspx页面文件,是用于"合并页模式",就是所有的操作都会在一页中完成。TailspinTravel并没有启用这个功能。DynamicData文件夹的名称都是“DynamicData”。

  上面的、可不可以改成我们自己想要的名字呢?

  不行的,我们可以看到,上面使用的是DynamicDataRoute类,而不是Route类,DynamicDataRoute继承于Route,Table和Action属性是DynamicDataRoute特有的。

  DynamicData/Content/GridViewPager.ascx分页控件。

  DynamicData/Content/FilterUserControl.ascx在显示表中的数据时,该控件显示在表头,用以过滤表中的内容,比如可以只列表产品目录为“实用工具”的产品。

  DynamicData/CustomPages文件夹。自定义网页模板文件夹,可用以替换DynamicData/PageTemplates文件夹中的默认模板。

  DynamicData/FieldTemplates文件夹。包含各种类型的字段在查看和创建、编辑时所呈现的控件。

  DynamicData/PageTemplates文件夹。包含在进行查看、编辑时的页面模板。

  DynamicData还有一个快速开发的基础是脚手架,脚手架是一种机制,通过脚手架,我们不必再为每一个表的增加、查看、修改做不同的页面,因为脚手架会自动生成这些页面。TailspinTravel对所有表都启用脚手架,对所有表启用脚手架表示公开了整个数据模型:

  metaModel.RegisterContext(contextFactory,newContextConfiguration{ScaffoldAllTables=true});

  还可以对特定表启用脚手架功能,这时就要将上面的ScaffoldAllTables=false,然后给模型类打标签[System.ComponentModel.DataAnnotations.ScaffoldTable(true)]

  自动生成的网站需要我们调整的页面,需要创建自定义的页面可以把它放在DynamicData/CustomPages文件夹,在DynamicData/CustomPages/下新建一个文件夹,名称为FlightBookings,这个名称一定要与Tailspin.edmx中的相应表的分部类名称一样。然后将DynamicData/PageTemplates/下的文件复制到DynamicData/CustomPages/FlightBookings/。

  更改新模板文件中的类名。

  比如将类名称List改为DynamicDataTest.FlightBookingsList。

  [MetadataType(typeof(CarRentalMetadata))]publicpartialclassCarRental{[ScaffoldTable(false)]privateclassCarRentalMetadata{[DisplayName("Pickup")]publicobjectRentalStart{getset}[DisplayName("Return")]publicobjectRentalEnd{getset}[DisplayName("PickupPlace")][Required(ErrorMessage="Pleasespecifywhereyouprefertopickupthevehicle.")]publicobjectPickupPlaceId{getset}[DisplayName("Returnplace")][Required(ErrorMessage="Pleasespecifywhereyouprefertoreturnthevehicle.")]publicobjectReturnPlaceId{getset}[DisplayName("Vehicle")][Required(ErrorMessage="Pleasespecifythevehicletype.")]publicobjectVehicleTypeId{getset}}}还可以用UIHint,DataType

  使用DisplayName更改界面的显示,DisplayName只能用于类、方法、属性、索引、事件

  改变字段模板

  [MetadataType(typeof(FlightMetadata))]publicpartialclassFlight{publicFlight(){this.Id=Guid.NewGuid();}[DisplayName("Flights")]privateclassFlightMetadata{[ScaffoldColumn(false)]publicobjectId{getset}[Required]publicobjectAirplaneType{getset}[UIHint("Time")]publicobjectDepartureTime{getset}[UIHint("Time")][DataType(DataType.Time)]publicobjectArrivalTime{getset}[DisplayName("DepartureAirport")]publicobjectDepartureAirport{getset}[DisplayName("ArrivalAirport")]publicobjectArrivalAirport{getset}}}DynamicData

  非常的灵活,TailspinTravel用来对付管理后台的开发方面具有非常高的效率,在前台使用MVC2保证性能,在UI界面的开发方面非常值得借鉴的一种模式。

0 0