运行文件AspNetMVCPreview2-setup.msi进行安装,安装完成后发现在VS2008里面并没有MVC模板出现。又到处Google了一遍,发现有不少人遇到这个问题,但是还没看到完全解决的办法。
目前遇到问题的基本集中在Microsoft Visual Studio 2008中文版,因为中文版所有的安装文件默认放在2052(中文编码)下面,而ASP.NET MVC是英文的,所有都放在1033下面,所以导致ASP.NET MVC模板不能载入。
知道问题的根源就好解决了,修改如下文件夹名称(x为您对应的安装盘符):
程序代码
x:\Program Files\Microsoft Visual Studio 9.0\Common7
\IDE\ItemTemplates\CSharp\Web\MVC\1033
x:\Program Files\Microsoft Visual Studio 9.0\Common7
\IDE\ItemTemplatesCache\CSharp\Web\MVC\1033
为
程序代码
x:\Program Files\Microsoft Visual Studio 9.0\Common7
\IDE\ItemTemplates\CSharp\Web\MVC\2052
x:\Program Files\Microsoft Visual Studio 9.0\Common7
\IDE\ItemTemplatesCache\CSharp\Web\MVC\2052
然后将
程序代码
x:\Program Files\Microsoft Visual Studio 9.0\Common7
\IDE\ProjectTemplates\CSharp\Web\1033
x:\Program Files\Microsoft Visual Studio 9.0\Common7
\IDE\ProjectTemplatesCache\CSharp\Web\1033
文件夹里的内容剪切到
程序代码
x:\Program Files\Microsoft Visual Studio 9.0\Common7
\IDE\ProjectTemplates\CSharp\Web\2052
x:\Program Files\Microsoft Visual Studio 9.0\Common7
\IDE\ProjectTemplatesCache\CSharp\Web\2052
文件夹中,到这里文件路径问题就解决了。
这个时候直接打开VS2008还是看不到MVC模板的,因为我们要重建一次VS2008的模板索引,方法如下:
在命令行运行
程序代码
x:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE\devenv.exe /setup
因为重建索引需要一点时间,等待大概几秒钟再打开你的VS2008就可以看到MVC项目模板了。
至此就完成了ASP.NET MVC框架在Microsoft Visual Studio 2008中文版的安装。
细细地看了一下这个框架,让我很激动,因为这个框架正是我一直在追求的MVC完全分离的开发模式,再也不用我手动地去处理以前那种令人诟病的开发模式了。
Google App Engine
Google App Engine 一直想用,但是我申请测试帐号一直没下来,只好转载一下别人的使用经验,如下:
Google 最近推出了 Google App Engine ,本想在第一时间内抢到一测试帐号,可惜未能如愿。苍天不负有心人,最终在一个马来西亚的网友(babylon2233)帮助下,才得以一睹芳容。
如果不了解什么是google 的 app engine,到官方站点了解一下吧。下面着重讲解一下如何开发一个简单的App-Engine 应用。
0.首先你要有一个可以登录 appengine.google.com 的帐号,有一个APPID,比如hello.
注意,这个APPID十分重要。
1.安装程序客户端运行环境
首先安装 Python 2.5,其次安装 App-Engine SDK 。
安装成功后,可以进入命令行下运行一下 dev_appserver.py 命令就知道是否安装成功。
2.开始编写一个最简的程序。
新建一个目录 hello
在hello目录下建立一个 app.yaml 文件,文件内容如下:
application: hello version: 1 runtime: python api_version: 1 handlers: - url: /.* script: hello.py
然后建立一个 hello.py 文件,内容如下:
print 'Content-Type: text/plain' print '' print 'hello the Google App Engine~'
3.完成了以上步骤,那么就测试一下,我们的程序是否OK。
进入命令行,输入以下命令:
dev_appserver.py hello项目所在的项目路径 eg: dev_appserver.py d:/app-demo/hello
假如以上步骤无误,那么就会在Console窗口下看到以下字样:
D:\>dev_appserver.py d:/app-demo/hi INFO 2008-04-11 16:16:42,233 appcfg.py] Checking for updates to the SDK. INFO 2008-04-11 16:16:44,015 appcfg.py] The SDK is up to date. INFO 2008-04-11 16:16:44,217 dev_appserver_main.py] Running application yong boy8 on port 8080: http://localhost:8080
4.打开你的本地浏览器,输入 http: //localhost:8080 地址,访问吧。
5.上传我们的程序到google底服务器上
进入命令行,输入类似于以下的命令:
appcfg.py update 你的程序所在的路径 eg: appcfg.py update d:/app-demo/hello
没有什么异常的话,项目上传成功。
然后打开浏览器,输入:
http://hello.appspot.com
注意,如果你也有一个google app engine 帐号,那么你的APPID,替换成hello就OK了
后记:当前Google App Engine 仅仅支持Python语言。另外没有提供独立的API文档,所有文档都需要到网上去查询,不怎么方便的。
Struts,MVC 的一种开放源码实现用这种servlet和JSP框架管理复杂的大型网站
本文介绍 Struts,它是使用 servlet 和 JavaServer Pages 技术的一种 Model-View-Controller 实现。Struts 可帮助您控制 Web 项目中的变化并提高专业化水平。尽管您可能永远不会用 Struts 实现一个系统,但您可以将其中的一些思想用于您以后的 servlet 和 JSP 网页的实现中。
简介
小学生也可以在因特网上发布 HTML 网页。但是,小学生的网页和专业开发的网站有质的区别。网页设计人员(或者 HTML 开发人员)必须理解颜色、用户、生产流程、网页布局、浏览器兼容性、图像创建和 JavaScript 等等。设计漂亮的网站需要做大量的工作,大多数 Java 开发人员更注重创建优美的对象接口,而不是用户界面。JavaServer Pages (JSP) 技术为网页设计人员和 Java 开发人员提供了一种联系钮带。
如果您开发过大型 Web 应用程序,您就理解变化这个词的含义。“模型-视图-控制器”(MVC) 就是用来帮助您控制变化的一种设计模式。MVC 减弱了业务逻辑接口和数据接口之间的耦合。Struts 是一种 MVC 实现,它将 Servlet 2.2 和 JSP 1.1 标记(属于 J2EE 规范)用作实现的一部分。尽管您可能永远不会用 Struts 实现一个系统,但了解一下 Struts 或许使您能将其中的一些思想用于您以后的 Servlet 的 JSP 实现中。
在本文中,我将以一个 JSP 文件为起点讨论该网页的优缺点,该文件中使用的元素可能是您所熟悉的。随后我将讨论 Struts,并说明它是如何控制您的 Web 项目中的变化并提高专业化水平的。最后,我将重新开发这个简单的 JSP 文件,在开发过程中我已顾及到网页设计人员和变化。
一个 JSP 文件就是一个 Java servlet
JavaServer Page (JSP) 文件只是审视 servlet 的另一种方式。JSP 文件的概念使我们能够将 Java servlet 看作一个 HTML 网页。JSP 消除了 Java 代码中经常出现的讨厌的 print() 语句。JSP 文件首先被预处理为 .java 文件,然后再编译为 .class 文件。如果您使用的是 Tomcat,则可以在 work 目录下查看预处理后的 .java 文件。别的容器可能将 .java 和 .class 文件存储在其他位置;这个位置与容器有关。图 1 说明了从 JSP 文件到 servlet 的流程。
图 1. 从 JSP 文件到 servlet 的流程
(这与 Microsoft 的 Active Server Page (ASP) 明显不同。ASP 被编译到内存中,而不是编译到一个单独的文件中。)
简单的独立 JSP 文件
在小型 JSP 应用程序中,经常会看到数据、业务逻辑和用户界面被组合在一个代码模块中。此外,应用程序通常还包含用来控制应用程序流程的逻辑。清单 1 和图 2 展示了允许用户加入一个邮件列表的一个简单 JSP 文件。
清单 1. join.jsp — 一个简单的请求和响应 JSP 文件 <%@ page language="java" %><%@ page import="business.util.Validation" %><%@ page import="business.db.MailingList" %><%String error = "";String email = request.getParameter("email");// 是否有电子邮件地址if( email!=null ) { // 验证输入... if( business.util.Validation.isValidEmail(email) ) { // 存储输入... try { business.db.MailingList.AddEmail(email); } catch (Exception e) { error = "Error adding email address to system. " + e; } if( error.length()==0 ) {%> // 重定向到欢迎页…
Enter your email to join the group
图 2. 在简单的请求和响应中,JSP 文件设置数据、控制到下一个网页的流程并创建 HTML
这个邮件列表 JSP 文件是一个独立的、自主完成所有任务的模块。未包含在这个 JSP 文件中的仅有代码是包含在 isValidEmail() 中的实际验证代码和将电子邮件地址存入数据库的代码。(将 isValidEmail() 方法分离到可重用的代码中似乎是当然的选择,但我曾见过直接嵌入网页中的 isValidEmail() 代码。单页方法的优点是易于理解,并且最初也易于构建。此外,对于各种图形化开发工具,入门也很容易。
join.jsp 的活动
显示打开的输入网页。
从表单参数中读取 email 的值。
验证 email 地址。
如果 email 地址有效:
将该地址添加到数据库中。
重定向到下一个网页。
如果 email 地址无效:
设置错误消息。
重新显示含有错误消息的 join.jsp。
单页方法的后果
HTML 和 Java 强耦合在一起
JSP 文件的编写者必须既是网页设计者,又是 Java 开发者。其结果通常要么是很糟的 Java 代码,要么是难看的网页,有时甚至 Java 代码和网页都很糟。
Java 和 JavaScript 的不足
随着网页逐渐变大,很容易想到实现一些 JavaScript。当网页中出现 JavaScript 时,这种脚本就可能与 Java 代码产生混淆。可能产生混淆的一个例子是使用客户端的 JavaScript 来验证 email 域。
内嵌的流程逻辑
要理解应用程序的整个流程,您必须浏览所有网页。试想一下拥有 100 个网页的网站的错综复杂的逻辑。
调试困难
除了很糟的外观之外,HTML 标记、Java 代码和 JavaScript 代码都集中在一个网页中还使调试变得相当困难。
强耦合
更改业务逻辑或数据可能牵涉相关的每个网页。
美学
在很大的网页中,这编码样式看起来杂乱无章。我过去进行 Microsoft ASP 开发时,我经常看到有 1000 行的网页。即使有彩色语法显示,阅读和理解这些代码仍然比较困难。
请别在我的 HTML 中加入太多的 Java 代码
在清单 1 中,不是 Java 代码中有大量的 HTML,而是在 HTML 文件中有大量的 Java 代码。从这个观点来看,除了允许网页设计人员编写 Java 代码之外,我实际上没做什么。但是,我们并不是一无所有;在 JSP 1.1 中,我们获得一种称为“标记”的新特性。
JSP 标记只是将代码从 JSP 文件中抽取出来的一种方式。有人将 JSP 标记看作是 JSP 文件的宏,其中用于这个标记的代码包含在 servlet 中。(宏的观点在很大程度上是正确的。)出于同样的原因,我不希望在 Java 代码中看到 HTML 标记,我也不希望在 JSP 文件中看到 Java 代码。JSP 技术的整个出发点就是允许网页设计人员创建 servlet,而不必纠缠于 Java 代码。标记允许 Java 程序员将 Java 代码伪装成 HTML 来扩展 JSP 文件。图 3 显示了从 JSP 网页中抽取代码并将它们放入 JSP 标记中的一般概念。
图 3. JSP 标记
清单 2 是用来说明 Struts 标记的功能的一个例子。在清单 2 中,正常的 HTML
MVC设计模式带来更好的软件结构和代码重用
模型-视图-控制器(MVC)是Xerox PARC在八十年代为编程语言Smalltalk-80发明的一种软件设计模式,至今已被广泛使用。最近几年被推荐为Sun公司J2EE平台的设计模式,并且受到越来越多的使用ColdFusion和PHP的开发者的欢迎。模型-视图-控制器模式是一个有用的工具箱,它有很多好处,但也有一些缺点。
MVC如何工作
MVC是一个设计模式,它强制性的使应用程序的输入、处理和输出分开。使用MVC应用程序被分成三个核心部件:模型、视图、控制器。它们各自处理自己的任务。
视图
视图是用户看到并与之交互的界面。对老式的Web应用程序来说,视图就是由HTML元素组成的界面,在新式的Web应用程序中,HTML依旧在视图中扮演着重要的角色,但一些新的技术已层出不穷,它们包括Macromedia Flash和象XHTML,XML/XSL,WML等一些标识语言和Web services.
如何处理应用程序的界面变得越来越有挑战性。MVC一个大的好处是它能为你的应用程序处理很多不同的视图。在视图中其实没有真正的处理发生,不管这些数据是联机存储的还是一个雇员列表,作为视图来讲,它只是作为一种输出数据并允许用户操纵的方式。
模型
模型表示企业数据和业务规则。在MVC的三个部件中,模型拥有最多的处理任务。例如它可能用象EJBs和ColdFusion Components这样的构件对象来处理数据库。被模型返回的数据是中立的,就是说模型与数据格式无关,这样一个模型能为多个视图提供数据。由于应用于模型的代码只需写一次就可以被多个视图重用,所以减少了代码的重复性。
控制器
控制器接受用户的输入并调用模型和视图去完成用户的需求。所以当单击Web页面中的超链接和发送HTML表单时,控制器本身不输出任何东西和做任何处理。它只是接收请求并决定调用哪个模型构件去处理请求,然后用确定用哪个视图来显示模型处理返回的数据。
现在我们总结MVC的处理过程,首先控制器接收用户的请求,并决定应该调用哪个模型来进行处理,然后模型用业务逻辑来处理用户的请求并返回数据,最后控制器用相应的视图格式化模型返回的数据,并通过表示层呈现给用户。
为什么要使用 MVC
大部分Web应用程序都是用像ASP,PHP,或者CFML这样的过程化语言来创建的。它们将像数据库查询语句这样的数据层代码和像HTML这样的表示层代码混在一起。经验比较丰富的开发者会将数据从表示层分离开来,但这通常不是很容易做到的,它需要精心的计划和不断的尝试。MVC从根本上强制性的将它们分开。尽管构造MVC应用程序需要一些额外的工作,但是它给我们带来的好处是无庸质疑的。
首先,最重要的一点是多个视图能共享一个模型,正如我所提及的,现在需要用越来越多的方式来访问你的应用程序。对此,其中一个解决之道是使用MVC,无论你的用户想要Flash界面或是WAP界面;用一个模型就能处理它们。由于你已经将数据和业务规则从表示层分开,所以你可以最大化的重用你的代码了。
由于模型返回的数据没有进行格式化,所以同样的构件能被不同界面使用。例如,很多数据可能用HTML来表示,但是它们也有可能要用Macromedia Flash和WAP来表示。模型也有状态管理和数据持久性处理的功能,例如,基于会话的购物车和电子商务过程也能被Flash网站或者无线联网的应用程序所重用。
因为模型是自包含的,并且与控制器和视图相分离,所以很容易改变你的应用程序的数据层和业务规则。如果你想把你的数据库从MySQL移植到Oracle,或者改变你的基于RDBMS数据源到LDAP,只需改变你的模型即可。一旦你正确的实现了模型,不管你的数据来自数据库或是LDAP服务器,视图将会正确的显示它们。由于运用MVC的应用程序的三个部件是相互对立,改变其中一个不会影响其它两个,所以依据这种设计思想你能构造良好的松偶合的构件。
对我来说,控制器的也提供了一个好处,就是可以使用控制器来联接不同的模型和视图去完成用户的需求,这样控制器可以为构造应用程序提供强有力的手段。给定一些可重用的模型和视图,控制器可以根据用户的需求选择模型进行处理,然后选择视图将处理结果显示给用户。
MVC的缺点
MVC的缺点是由于它没有明确的定义,所以完全理解MVC并不是很容易。使用MVC需要精心的计划,由于它的内部原理比较复杂,所以需要花费一些时间去思考。
你将不得不花费相当可观的时间去考虑如何将MVC运用到你的应用程序,同时由于模型和视图要严格的分离,这样也给调试应用程序到来了一定的困难。每个构件在使用之前都需要经过彻底的测试。一旦你的构件经过了测试,你就可以毫无顾忌的重用它们了。
根据我个人经验,由于我们将一个应用程序分成了三个部件,所以使用MVC同时也意味着你将要管理比以前更多的文件,这一点是显而易见的。这样好像我们的工作量增加了,但是请记住这比起它所能带给我们的好处是不值一提。
MVC并不适合小型甚至中等规模的应用程序,花费大量时间将MVC应用到规模并不是很大的应用程序通常会得不偿失。
MVC是一条创建软件的好途径
MVC设计模式是一个很好创建软件的途径,它所提倡的一些原则,像内容和显示互相分离可能比较好理解。但是如果你要隔离模型、视图和控制器的构件,你可能需要重新思考你的应用程序,尤其是应用程序的构架方面。如果你肯接受MVC,并且有能力应付它所带来的额外的工作和复杂性,MVC将会使你的软件在健壮性,代码重用和结构方面上一个新的台阶。
Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=146809
ASP.NET下MVC设计模式的实现
ASP.NET是微软最新推出的新型体系结构.NET框架的一部分,它为构造新一代动态网站和基于网络的分布式应用提供了强有力的支持。与以前的 Web 开发模型相比,ASP.NET 提供了许多重要的优点例如: 简易性;安全性;可管理性等。而且与基于过程的ASP页面技术相比,面向对象技术在ASP.NET中得到了完全实现。用传统ASP技术建立的Web应用实例中,在页面中同时实现显示,业务逻辑和流程控制,这从工程化的角度考虑,它有许多不足之处。用户界面承担着向用户显示问题模型和与用户进行操作和I/O交互的作用。用户希望保持交互操作界面的相对稳定,但更希望根据需要改变和调整显示的内容和形式。在.NET框架下ASP.NET技术结合MVC设计模式很好地解决了上述问题。
1 MVC设计模式简介
MVC由Trygve Reenskaug提出,首先被应用在SmallTalk-80环境中,是许多交互和界面系统的构成基础。MVC结构是为那些需要为同样的数据提供多个视图的应用程序而设计的,它很好的实现了数据层与表示层的分离。MVC作为一种开发模型,通常用于分布式应用系统的设计和分析中,以及用于确定系统各部分间的组织关系。对于界面设计可变性的需求,MVC(Model-View-Controller)把交互系统的组成分解成模型、视图、控制器三种部件。
视图部件把表示模型数据及逻辑关系和状态的信息以特定形式展示给用户。它从模型获得显示信息,对于相同的信息可以有多个不同的显示形式或视图。
控制器部件是处理用户与软件的交互操作的,其职责是控制提供模型中任何变化的传播,确保用户界面于模型间的对应联系;它接受用户的输入,将输入反馈给模型,进而实现对模型的计算控制,是使模型和视图协调工作的部件。
模型部件保存由视图显示,由控制器控制的数据;它封装了问题的核心数据、逻辑和功能的计算关系,它独立于具体的界面表达和I/O操作。
模型、视图与控制器的分离,使得一个模型可以具有多个显示视图。如果用户通过某个视图的控制器改变了模型的数据,所有其它依赖于这些数据的视图都应反映到这些变化。因此,无论何时发生了何种数据变化,控制器都会将变化通知所有的视图,导致显示的更新。这实际上是一种模型的变化-传播机制。模型、视图、控制器三者之间的关系和各自的主要功能,如图1所示。
2 MVC设计模式的实现
ASP.NET提供了一个很好的实现这种经典设计模式的类似环境。开发者通过在ASPX页面中开发用户接口来实现视图;控制器的功能在逻辑功能代码(.cs)中实现;模型通常对应应用系统的业务部分。在ASP.NET中实现这种设计而提供的一个多层系统,较经典的ASP结构实现的系统来说有明显的优点。将用户显示(视图)从动作(控制器)中分离出来,提高了代码的重用性。将数据(模型)从对其操作的动作(控制器)分离出来可以让你设计一个与后台存储数据无关的系统。就MVC结构的本质而言,它是一种解决耦合系统问题的方法。
2.1 视图
视图是模型的表示,它提供用户交互界面。使用多个包含单显示页面的用户部件,复杂的Web页面可以展示来自多个数据源的内容,并且网页人员,美工能独自参与这些Web页面的开发和维护。
在ASP.NET下,视图的实现很简单。可以像开发WINDOWS界面一样直接在集成开发环境下通过拖动控件来完成页面开发本。本文中介绍每一个页面都采用复合视图的形式即:一个页面由多个子视图(用户部件)组成;子视图可以是最简单HTML 控件、服务器控件或多个控件嵌套构而成的Web自定义控件。页面都由模板定义,模板定义了页面的布局,用户部件的标签和数目,用户指定一个模板,平台根据这些信息自动创建页面。针对静态的模板内容,如页面上的站点导航,菜单,友好链接,这些使用缺省的模板内容配置;针对动态的模板内容(主要是业务内容),由于用户的请求不同,只能使用后期绑定,并且针对用户的不同,用户部件的显示内容进行过滤。使用由用户部件根据模板配置组成的组合页面,它增强了可重用性,并原型化了站点的布局。
视图部分大致处理流程如下:首先,页面模板定义了页面的布局;页面配置文件定义视图标签的具体内容(用户部件);然后,由页面布局策略类初始化并加载页面;每个用户部件根据它自己的配置进行初始化,加载校验器并设置参数,以及事件的委托等;用户提交后,通过了表示层的校验,用户部件把数据自动提交给业务实体即模型。
这一部分主要定义了WEB页面基类PageBase;页面布局策略类PageLayout,完成页面布局,用于加载用户部件到页面;用户部件基类UserControlBase即用户部件框架,用于动态加载检验部件,以及实现用户部件的个性化。为了实现WEB应用的灵活性,视图部分也用到了许多配置文件例如:置文件有模板配置、页面配置、路径配置、验证配置等。
2.2 控制器
为了能够控制和协调每个用户跨越多个请求的处理,控制机制应该以集中的方式进行管理。因此,为了达到集中管理的目的引入了控制器。应用程序的控制器集中从客户端接收请求(典型情况下是一个运行浏览器的用户),决定执行什么商业逻辑功能,然后将产生下一步用户界面的责任委派给一个适当的视图组件。
用控制器提供一个控制和处理请求的集中入口点,它负责接收、截取并处理用户请求;并将请求委托给分发者类,根据当前状态和业务操作的结果决定向客户呈现的视图。在这一部分主要定义了HttpReqDispatcher(分发者类)、HttpCapture(请求捕获者类)、Controller(控制器类)等,它们相互配合来完成控制器的功能。请求捕获者类捕获HTTP请求并转发给控制器类。控制器类是系统中处理所有请求的最初入口点。控制器完成一些必要的处理后把请求委托给分发者类;分发者类分发者负责视图的管理和导航,它管理将选择哪个视图提供给用户,并提供给分发资源控制。在这一部分分别采用了分发者、策略、工厂方法、适配器等设计模式。
为了使请求捕获者类自动捕获用户请求并进行处理,ASP.NET 提供低级别的请求/响应 API,使开发人员能够使用 .NET 框架类为传入的 HTTP 请求提供服务。为此,必须创作支持 System.Web.IHTTPHandler 接口和实现 ProcessRequest() 方法的类即:请求捕获者类,并在web.config 的 <httphandlers> 节中添加类。ASP.NET 收到的每个传入 HTTP 请求最终由实现 IHTTPHandler 的类的特定实例来处理。IHttpHandlerFactory 提供了处理 IHttpHandler 实例 URL 请求的实际解析的结构。HTTP 处理程序和工厂在 ASP.NET 配置中声明为 web.config 文件的一部分。ASP.NET 定义了一个 <httphandlers> 配置节,在其中可以添加和移除处理程序和工厂。子目录继承 HttpHandlerFactory 和 HttpHandler 的设置。 HTTP 处理程序和工厂是 ASP.NET 页框架的主体。工厂将每个请求分配给一个处理程序,后者处理该请求。 例如,在全局 machine.config 文件中,ASP.NET 将所有对 ASPx 文件的请求映射到 HttpCapture类:
<httphandlers>
…
<add verb=”*” path=”*.ASPx” type=”Sys.UI.HttpCapture, Sys.UI”/>
…
</httphandlers>
2.3 模型
MVC系统中的模型从概念上可以分为两类――系统的内部状态和改变系统状态的动作。模型是你所有的商业逻辑代码片段所在。本文为模型提供了业务实体对象和业务处理对象:所有的业务处理对象都是从ProcessBase类派生的子类。业务处理对象封装了具体的处理逻辑,调用业务逻辑模型,并且把响应提交到合适的视图组件以产生响应。业务实体对象可以通过定义属性描述客户端表单数据。所有业务实体对象都EntityBase派生子类对象,业务处理对象可以直接对它进行读写,而不再需要和request、response对象进行数据交互。通过业务实体对象实现了对视图和模型之间交互的支持。实现时把”做什么”(业务处理)和”如何做”(业务实体)分离。这样可以实现业务逻辑的重用。由于各个应用的具体业务是不同的,这里不再列举其具体代码实例。
3 MVC设计模式的扩展
通过在ASP.NET中的MVC模式编写的,具有极其良好的可扩展性。它可以轻松实现以下功能:
①实现一个模型的多个视图;
②采用多个控制器;
③当模型改变时,所有视图将自动刷新;
④所有的控制器将相互独立工作。
这就是MVC模式的好处,只需在以前的程序上稍作修改或增加新的类,即可轻松增加许多程序功能。以前开发的许多类可以重用,而程序结构根本不再需要改变,各类之间相互独立,便于团体开发,提高开发效率。下面讨论如何实现一个模型、两个视图和一个控制器的程序。其中模型类及视图类根本不需要改变,与前面的完全一样,这就是面向对象编程的好处。对于控制器中的类,只需要增加另一个视图,并与模型发生关联即可。该模式下视图、控制器、模型三者之间的示意图如图2所示。
图 2 视图、控制器、模型三者之间关系的示意图
同样也可以实现其它形式的MVC例如:一个模型、两个视图和两个控制器。从上面可以看出,通过MVC模式实现的应用程序具有极其良好的可扩展性,是ASP.NET面向对象编程的未来方向。
4 MVC设计模式的优点及不足之处
4.1 MVC的优点
MVC的优点体现在以下几个方面:
(1) 可以为一个模型在运行时同时建立和使用多个视图。变化-传播机制可以确保所有相关的视图及时得到模型数据变化,从而使所有关联的视图和控制器做到行为同步。
(2) 视图与控制器的可接插性,允许更换视图和控制器对象,而且可以根据需求动态的打开或关闭、甚至在运行期间进行对象替换。
(3) 模型的可移植性。因为模型是独立于视图的,所以可以把一个模型独立地移植到新的平台工作。需要做的只是在新平台上对视图和控制器进行新的修改。
(4) 潜在的框架结构。可以基于此模型建立应用程序框架,不仅仅是用在设计界面的设计中。
4.2 MVC的不足之处
MVC的不足体现在以下几个方面:
(1)增加了系统结构和实现的复杂性。对于简单的界面,严格遵循MVC,使模型、视图与控制器分离,会增加结构的复杂性,并可能产生过多的更新操作,降低运行效率。
(2)视图与控制器间的过于紧密的连接。视图与控制器是相互分离,但确实联系紧密的部件,视图没有控制器的存在,其应用是很有限的,反之亦然,这样就妨碍了他们的独立重用。
(3)视图对模型数据的低效率访问。依据模型操作接口的不同,视图可能需要多次调用才能获得足够的显示数据。对未变化数据的不必要的频繁访问,也将损害操作性能。
(4) 目前,一般高级的界面工具或构造器不支持MVC模式。改造这些工具以适应MVC需要和建立分离的部件的代价是很高的,从而造成使用MVC的困难。
5 结束语
与软件所处理问题的内在模型相比较,用户界面是需要经常发生变化的,采用MVC设计模式可以在满足对界面要求的同时,使软件的计算模型独立于界面的构成。也可以基于此模型建立大型分布式应用程序框架。本文介绍了MVC设计模式的原理;MVC设计模式三个组成构件(模型部件、视图部件和控制部件)以及在ASP.NET环境下实现基于MVC的应用需要完成的工作;MVC设计模式的扩展;最后对MVC的优点及不足之处进行了分析。
Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=20781
ASP.NET MVC框架
【原文地址】ASP.NET MVC Framework (Part 1)
【原文发表日期】 Tuesday, November 13, 2007 3:45 AM
两个星期前, 我在博客里讨论了ASP.NET的一个新MVC(模型、视图,控制器)框架,我们将在不久的将来作为一个可选功能来支持 。该框架提供了一个结构化的模型,来加强应用中的清晰关注分离,方便你单元测试代码和支持TDD流程。它还提供了对你在应用中发布的URL的 更多的控制,也可以对从中输出的HTML提供更多的控制。
之后,我回答了来自迫切想了解更多详情的很多人的很多问题。鉴于如此高的兴趣,我觉得,写几个贴子更详细地描述如何使用这个框架,也许 更有意义些。这是我将在以后几个星期里要撰写的相关贴子的第一个。
一个简单的电子商务店面应用
我将使用一个简单的电子商务商店应用来示范ASP.NET MVC框架的工作原理。在今天的贴子里,我将实现一个产品列单,以及相关的浏览 应用场景。
具体来说,我们将建造一个网上商店,允许用户在访问该网站上的/Products/Categories网址时 浏览产品分类列表:

当用户点击上面网页上的产品分类链接时,他们将转到一个产品分类列表URL /Products/List/CategoryName 上 ,该页面列出了指定分类中的还在销售的产品:

当用户点击个别的产品时,他们将转到产品细节URL /Products/Detail/ProductID上,这个网页将显示用户选定的 产品的更多细节:

我们将使用新的ASP.NET MVC框架来实现上述的所有功能。这将会允许我们在应用的不同组件间保持“清晰的关注分离”,允许我们更轻 易地集成单元测试和测试驱动的开发。
创建一个新的ASP.NET MVC应用
ASP.NET MVC框架包含一个Visual Studio项目模板,方便你创建新的MVC web应用。选择文件->新项目菜单,选择“ASP.NET MVC Web 应用”模板,用它创建一个新web应用。
在默认情形下,当你使用该选项生成一个新应用时,Visual Studio 将为你创建一个新的解决方案,然后往里面加2个项目。第一个项目 是web项目,在其中你实现你的web应用的功能。第二个项目是个测试项目,你可以在其中编写单元测试,来测试你的应用代码:

你可以在ASP.NET MVC 框架中使用任何单元测试框架,包括NUnit, MBUnit, MSTest, XUnit以及其他的框架。VS 2008专 业版现在包含了对MSTest的内置测试项目的支持(VS 2005版本的MSTest要求你拥有Visual Studio Team System版本才能使 用),当你使用VS 2008时,默认的ASP.NET MVC 项目模块自动生成这样的测试项目。
我们还将发布可用以NUnit, MBUnit 和其他单元测试框架的项目模板,所以,如果你更喜欢那些框架的话,你可以轻松地一次点击即生 成你的应用和可以马上使用的相应的测试项目。
理解项目的目录结构
ASP.NET MVC 应用的默认目录结构有三个顶层目录:
/Controllers
/Models
/Views
你大概可以猜出来,我们建议把控制器类置于 /Controllers 目录之中,你的数据模型类置于/Models目录之中,你的视图模板置于 /Views 目录之中。
虽然ASP.NET MVC框架并不强迫你总是使用这个结构,但默认的项目模板使用这个模式,我们也把它作为结构化应用的一种比较容易的方 式向你推荐。除非你有好的理由使用另外的文件布局,我建议你使用这个默认模式。
把URL映射到Controller类
在大多数web框架(ASP, PHP, JSP, ASP.NET WebForms等等)里,到来的URL一般都映射到保存在硬盘上的模板文件。譬 如,”/Products.aspx”或者”/Products.php” URL一般都在硬盘上有个对应的Products.aspx 或Products.php 模板文 件来处理请求。当一个web应用的http请求进入web服务器时,web框架运行由硬盘上的模板文件指定的代码,然后这代码负责处理该请求。很 多时候,这代码使用Products.aspx 或 Products.php文件中的HTML 标识来帮助生成返回客户端的响应。
MVC框架一般以不同的方式把URL映射到服务器代码上。它不是将URL映射到硬盘上的模板文件,而是直接把URL映射到代码类上。这些类称为 “Controllers(控制器)”,它们负责处理到来的请求,处理用户输入和交互,执行基于输入和交互的相应的应用和数据逻辑。然后,一个 Controller类一般会调用单独的“视图”组件,该组件负责生成请求的实际的HTML输出。

ASP.NET MVC框架包括一个非常强大的URL映射引擎,在如何把URL映射到Controller类方面,该引擎提供了很多灵活性。你可以使用它 来轻松地设置routing(路径选择,路由)规则,然后ASP.NET会根据这些规则,对进来的URL进行评估,选出一个Controller来运行。然后 你也可以让routing引擎自动分析出你在URL里定义的变量,让ASP.NET自动把这些变量作为参数传给你的Controller。我将在这个系列 将来的一个贴子里,讨论涉及URL routing引擎的比较高级的场景。
映射到控制器类的默认ASP.NET MVC URL Routing规则
在默认情形下,ASP.NET MVC项目有一套预先配置好的URL routing规则,这些规则允许你不用配置什么,就可以轻松地上路。这样,使用一 套默认的基于名称的URL映射约定,你就可以开始编写代码了,这些约定是在Global.asax文件(由Visual Studio中新的ASP.NET MVC项目模板生成的)中的ASP.NET Application类中声明的。
默认的命名约定是这样的:把进来的HTTP请求的URL路径的开头部分,譬如 /Products/,映射到一个类,该类的名称遵循 UrlPathController的模式,譬如在默认情形下,一个以/Products/开头的URL 会被映射到名为 ProductsController的类上。
为建造我们的电子商务产品浏览功能,我们将在我们的项目中加一个新的“ProductsController”类 (你可以使用Visual Studio中 的“添加新项”菜单从模板中轻松地创建一个Controller类):

我们的ProductsController是从System.Web.MVC.Controller 基类继承而来,从这个基类继承而来并不是必需的,但它含有一 些我们以后可以使用的非常有用的辅助方法和功能:

在项目中定义这个ProductsController类之后,在默认情形下,ASP.NET MVC 框架就会使用它来处理所有到来的以”/Products/” 开头的URL的应用请求。这意味着,它会自动被调用来处理我们将在我们的网上商店应用中开启的”/Products/Categories”, “/Products/List/Beverages”, 和 “/Products/Detail/3″ 等URL。
在将来的贴子里,我们还将添加一个ShoppingCartController(以允许用户管理他们的购物车)以及 AccountController (允许用 户在网站上创建新的成员帐号,实现登录和退出等功能)。在向我们的项目里添加这2个新的控制器类之后,以/ShoppingCart/ 和 /Account/开头的URL就会自动地导向到这些类做处理。
注:ASP.NET MVC框架并不要求你总是使用这个命名约定模式。我们的应用默认使用这个模式的唯一原因是因为在我们使用 Visual Studio创建新的ASP.NET MVC项目时,有一个配置了这个模式的映射规则被自动地添加到了我们的ASP.NET Application 类中。如果你不喜欢这个规则,或者想使用另外的URL映射模式来对它进行定制,那么就到Global.asax中的ASP.NET Application类 中做改动。我会在以后的一个贴子讨论该怎么做,到时我也会展示一些URL routing引擎允许的一些非常酷的场景。
理解控制器的Action方法
既然我们已经在项目里创建了一个ProductsController类,我们可以开始添加逻辑来处理来到应用的”/Products/” URL了。
在本贴子的前面定义我们的电子商务店面用例时,我说过我们将在网站上实现3个场景:1) 浏览所有的产品分类, 2) 列出特定分类里的产品, 和 3) 显示特定产品的细节。我们将使用下列这些SEO友好的URL来处理这三个场景:
URL格式 行为 URL例子
/Products/Categories 浏览所有的产品分类 /Products/Categories
/Products/List/Category 列出特定分类里的产品 /Products/List/Beverages
/Products/Detail/ProductID 显示特定产品的细节 /Products/Detail/34
我们可以用几种方式在ProductsController类中编写代码来处理这三类到来的URL。一种方式是,覆盖Controller基类中的 “Execute”方法,手工编写我们自己的 if/else/切换逻辑,对照用户请求的URL,然后执行适当的逻辑来处理这个请求。
但一种容易得多的方式是,使用MVC框架中内置的功能,该功能允许我们在我们的控制器中定义“action方法”,然后由Controller基 类根据我们应用使用的URL routing规则来自动调用适当的action方法来执行。
譬如,我们可以往我们的ProductsController类里添加如下所示的三个控制器action方法,来处理上述的三个电子商务URL场景:

在项目创建时默认配置的URL routing规则会把紧随控制器名称之后的子路径当作请求的action名称来对待。所以,如果我们收到一个 /Products/Categories的URL请求,routing规则会把“Categories”作为一个action的名称来对待,Categories() 方法就 会被调用来处理这个请求。如果我们收到的是 /Products/Detail/5 URL请求,routing规则就会把“Detail””当中action的名称 ,Detail() 方法就会被调用来处理请求,等等。
注:ASP.NET MVC框架并不要求你总是使用这个action命名约定模式。如果你想使用不同的URL映射模式,到 Global.asax 文件中的ASP.NET Application类去做改动。
把URL参数映射到Controller的Action方法上
在Controller类中的action方法中可以用几个方法访问URL中的参数值。
Controller基类呈现了可以使用的Request 和Response对象。这些对象跟ASP.NET中你已经熟悉的 HttpRequest/HttpResponse对象拥有完全一样的API结构。一个非常重要的区别是,这些对象现在是基于接口(interface)的,而不 是封闭的类。具体来说,MVC 框架将发布System.Web.IHttpRequest和System.Web.IHttpResponse接口。这些对象是基于的接 口的好处是,现在非常容易mock(模仿)它们,这样,就可以方便对控制器类的单元测试。在将来的博客贴子里,我将对此进行深入的讨论。
下面是一个如何在ProductsController类的Detail action方法中使用Request API来手工获取ID查询字符串值的例子:

ASP.NET MVC 框架还支持自动将进来的URL的参数值映射成action方法的参数。在默认情形下,如果你的action方法有个参数的话 ,MVC框架会检查进来的请求的数据,看是否有个同样名称的对应的HTTP请求值。如果有的话,它会自动将其作为参数传入你的action方法。
譬如,我们可以利用这个支持来重写我们的Detail action方法来,将其简化,象下面这样:

除了从请求的查询字符串/表单集合中映射参数值外,ASP.NET MVC框架还允许你使用MVC URL route映射基础设施在核心URL本身 内嵌参数值(譬如,不是使用/Products/Detail?id=3,而是使用/Products/Detail/3 )。
当你创建一个新的MVC项目时,声明的默认的路径映射规则拥有这样的格式,“/[controller]/[action]/[id]”。这意味着,如果 URL中在控制器名称和action名称之后还有任何子路径的话,在默认情形下,它将作为一个名为“id”的参数处理,会自动地作为一个方法参数 传给我们的控制器action方法。
这意味着我们现在可以使用我们的Detail 方法来处理从URL路径(譬如/Products/Detail/3)中获取ID参数:

我可以对List action使用类似的方法,这样我们可以将分类名称作为URL的一部分传进来(譬 如:/Products/List/Beverages)。为了使得代码容易阅读,我对routing规则做了一个小变动,这样不是把参数名定为“id”,对这个 action,它被称作“category”。
下面是实现了完整URL routing和参数映射支持的ProductsController类的一个版本:

注意上面List action方法接受一个作为URL一部分的category参数,然后一个作为URL查询字符串一部分的可缺省的网页索引参数( 我们将实现服务器端分页,将使用该参数值来表示我们应该显示对应分类数据的哪一页)。
我们的MVC 框架中的可缺省的参数是通过Controller Action方法上nullable的类型参数来处理的。因为我们List action的分页 参数是个nullable的int,从语法上来说,即是int? ,如果这个参数存在于URL中,MVC框架会将其值传给对应方法,如果不存在,会传入 null。参阅我以前的关于?? null coalescing operator帖子以了解如何操作象这样传入的nullable类型参数的一个有用的技巧/诀窍。
建造数据模型对象
至此,我们有了一个 ProductsController类,内含三个action方法,准备好处理进来的web请求了。下一步将是建造一些类,来帮 我们操作数据库,从中获取处理这些请求所需的适当的数据。
在MVC世界里,“model(模型)”是负责保持状态的应用组件。在web应用中,这个状态一般都持久于数据库之中(譬如,我们也许有一个 Product 对象,用来代表我们SQL数据库里Products表中的产品数据)。
ASP.NET MVC框架允许你为获取和管理你的模型,可以使用你想要的任何数据访问模式或框架。如果你要使用ADO.NET DataSets/DataReaders (或者建于它们之上的抽象),你可以那么做。如果你更喜欢使用象NHibernate, LLBLGen, WilsonORMapper, LINQ to SQL/LINQ to Entities这样的对象关系映射器(ORM),你也绝对可以那么做。
对我们的电子商务例程,我想用随 .NET 3.5 和 VS 2008发布的内置LINQ to SQL orM 。你可以从我的还在撰写中的讨论 LINQ to SQL 的博客系列中了解其中详情,特别是一定要阅读一下其中的第一部分,第二部分,第三部分,和第四部分的帖子。
从右击VS中的MVC web项目的“Models”子目录开始,选择“添加新项”,加一个 LINQ to SQL 模型。在LINQ to SQL orM 设计器 中,我将定义三个数据模型类,分别映射到SQL Server Northwind数据库中的Categories, Products, 和Suppliers 表(阅 读我的LINQ to SQL 系列的第二部分学习该怎么做):

定义完LINQ to SQL 数据模型类之后,然后我还将添加一个新NorthwindDataContext部分类到我们的Models目录中:

在这个类中,我将定义几个辅助方法封装一些LINQ表达式,这些表达式是用来从数据库中获取独特的Category对象,获取指定分类的所有 Product 对象,以及基于指定的ProductID获取单独的 Product对象:

这些辅助方法将方便我们在ProductsController类中干净利索地获取所需的数据模型对象 (而不用在Controller类中编写LINQ 表达式):

至此,我们就有了为完成我们的ProductsController功能所需的所有的数据代码和对象。
完成ProductsController类的实现
基于MVC的应用中的控制器类负责处理到来的请求,处理用户输入和交互,并且基于这些输入和交互执行适当的应用逻辑(获取和更新储存在 数据库中的模型数据等等)。
控制器一般不对请求生成特定的HTML响应。生成HTML响应的任务是为应用中的“视图”组件所拥有,这些视图是通过独立于控制器的 单独的类或模板实现的。视图的目的是完全注重于封装表现层的逻辑,不应该包含任何应用逻辑或数据库数据获取的代码的(所有的应用逻辑应当 为Controller来处理)。
在一个典型的MVC web流程中,控制器action方法负责处理进来的web请求,使用传入的参数值执行适当的应用逻辑代码,从数据库中获 取或更新数据模型对象,然后选择使用一个“视图”来显示返回给浏览器的界面响应。作为选择适当的视图来显示的一部分,控制器会明确地以参数 的形式向“视图”传入视图所需的所有的数据和变量,以使后者显示适当的响应:

你也许在想,象这样分开Controller和View有什么好处呢?为什么不把它们放在同一个类里呢?象这样分割应用的主要动机在于帮助你 加强应用/数据逻辑与你的界面生成代码间的分离。这可以在隔离你的界面显示逻辑的情形下,极大地方便你单元测试你的应用/数据逻辑。它还有 助于使得你的应用更好维护,因为它妨碍了你无意中把应用/数据逻辑加到你的视图模板里的可能。
在实现我们ProductsController类的三个控制器action方法时,我们将根据进来的URL参数值从数据库中获取适当的模型对象,然 后选择一个“视图”组件来显示适当的HTML响应。我们将使用Controller基类的一个RenderView() 方法来指定我们想要使用的视图,以 及明确地把我们要视图在显示响应时使用的特定数据传入该方法。
下面是我们的ProductsController实现的最终结果:

注意,我们的action方法的代码行数目很小(每个方法只有2行),部分原因是因为URL参数分析逻辑完全是由MVC框架为我们做的(给我们 省了很多行代码),还有部分原因是因为产品浏览场景从业务逻辑的角度来说相当简单(涉及的action方法都是只读的显示场景)。
但总的来说,你经常会发现你有的都是些有时被称为“瘦控制器”的东西,即控制器方法充满了相当简短的action方法(少于10行代码)。这 经常是好的迹象,表明你非常干净地封装了你的数据逻辑,也非常好地分隔了你的控制器逻辑。
单元测试ProductsController
你也许会感到惊奇,我们要做的下一步居然是测试我们的应用逻辑和功能。你也许会问,这怎么可能呢?我们还没有实现我们的视图呢,我们 的应用目前并不显示一个HTML tag。其实呢,使得MVC方法有魅力的部分原因就是我们可以完全独立于视图/Html生成逻辑来测试 Controller和Model 逻辑。在下面你将看到,我们甚至可以在创建视图前单元测试这些对象。
为单元测试我们在编写的ProductsController类,我们将往测试项目里加一个ProductsControllerTest类,这个测试项目是 在我们使用Visual Studio创建我们的ASP.NET MVC应用时,默认添加到我们的解决方案里的:

然后我们将定义一个简单的单元测试,测试我们的ProductsController的 Detail action方法:

ASP.NET MVC 框架是特地设计来促成轻松的单元测试的。框架中的所有的核心API和契约都是接口,提供了大量的扩展点以促成轻松的 对象注入和定制(包括使用象Windsor, StructureMap, Spring.NET, 和ObjectBuilder这样的IOC容器的能力)。开发人员将 能够使用内置的mock类,或者使用任何.NET 类型mock框架来模拟他们自己的MVC相关对象的测试版本。
在上面的单元测试中,你可以看到一个例子,我们是如何在调用 Detail() action 方法之前,往我们的ProductsController里 注入了一个伪(dummy)“ViewFactory”实现的。这么做的话,我们就覆盖了默认的ViewFactory,否则的话,默认的ViewFactory会创 建和显示我们的视图。我们可以使用这个测试ViewFactory实现来做隔离,只对我们ProductController的Detail action的行为 进行测试(而不必调用实际的视图来做测试)。注意我们是如何在Detail() action方法被调用之后,使用了三个 Assert 语句来核实该方 法的正确的行为确实发生了(具体地说,该方法获取了正确的Product对象,然后将它传给了适当的视图)。
因为我们可以mock和模拟MVC框架中的任何对象(包括 IHttpRequest 和 IHttpResponse 对象),你不用再在web服务的环境 里运行单元测试,我们可以在常规的类库里创建我们的ProductsController对象,然后对它直接测试。这可以极大地加快单元测试的运行速 度,以及简化对它们的配置和运行。
如果我们使用 Visual Studio 2008 IDE,我们还可以轻易地跟踪我们运行测试的结果(这个功能现在已经成为VS 2008 专业版 的一部分):

我想你会发现ASP.NET MVC 框架极大地方便了测试的编写,而且促成了非常好的TDD流程。
使用视图显示界面
我们完成了我们电子商务应用的产品浏览部分的应用+数据逻辑的实现和测试,现在我们需要实现相关的HTML界面。

我们将通过实现“视图”来实现,这些视图将使用我们ProductsController的action方法在调用RenderView() 方法时提供的 跟视图有关的数据对象,来显示适当的界面:

在上面的代码例子里,RenderView方法的“Categories”参数表示我们要显示的视图名称,第二个参数是我们要传给视图对象并要视 图对象据此显示适当HTML界面的分类对象的列表。
ASP.NET MVC框架支持使用任何模板引擎(包括象NVelocity, Brail,以及你自己想要编写的任何模板引擎)来帮助生成界面。在默 认情形下, ASP.NET MVC 框架使用ASP.NET中现有的ASP.NET 页面 (.aspx), 母版页 (.master), 和用户控件 (.ascx) 。
我们将使用内置的ASP.NET 视图引擎来实现我们的电子商务应用的界面。
定义Site.Master文件
因为我们将要在网站上建造很多页面,我们先来定义一个母版页,用以封装整个网站公用的HTML布局/样式。我们将在我们项目的 \Views\Shared 目录里创建一个名为“Site.Master”的文件:

我们可以引用一个外部的CSS样式文件来封装整个网站的所有样式,然后使用母版页来定义网站总的布局,以及指定我们要具体页面填充相关内容 的内容placeholder 区域。在做的时候,我们也可以使用VS 2008 中的新设计器的所有的酷功能,包括HTML分割视图设计器,编著CSS和嵌套母版页支持等。

理解/Views目录结构
在默认情形下,当你使用Visual Studio创建新的ASP.NET MVC 项目时,它会在“Views”根目录下生成一个“Shared”子目录。 这是存放应用中为多个控制器所共享的母版页,用户控件和视图的推荐使用的地点。
在建造为特定个别控制器所用的视图时,默认的 ASP.NET MVC 约定是,把它们存放在\Views 根目录的子目录里。在默认情形下,子目 录的名字应该对应于控制器的名字。譬如,因为我们正编写的Controller类叫“ProductsController”,在默认情形下,我们将在 \Views\Products 子目录里存放跟它相关的特定视图:

当我们在一个特定的Controller中调用 RenderView(string viewName)方法时,MVC框架会自动地首先在 \Views\ControllerName 目录里寻找对应的.aspx 或 .ascx视图模板,如果它找不到适当的视图模板,然后它会在 \Views\Shared目录寻找。
创建一个Categories视图
我们可以在 Visual Studio 中 Products 目录上使用“添加新项”菜单选项,然后选择“MVC视图网页”项模板,为我们的 ProductsController 创建一个“Categories”视图。这会生成一个新的.aspx 页面,我们可以将它跟我们的 Site.Master 母 版页相关联,来得到总的外观(就象母版页一样,你会得到即见即所得设计器的支持):

在使用MVC模式建造应用时,你要把你的视图代码尽可能地保持简洁,确认视图代码纯粹是用来显示界面。应用和数据获取逻辑应该只在 Controller类里编写。然后Controller类就可以在调用RenderView 方法时选择把所需的数据对象传递给视图。譬如,在下面,我们的 ProductsController 类的 Categories action方法中,我们把 一个Category对象的List集合传给了Categories视图:

MVC视图页默认是从System.Web.Mvc.ViewPage 基类继承而来的,该基类提供了可为我们构建界面时所用的许多特定于MVC的辅助 方法和属性。ViewPage的其中一个属性名叫“ViewData”,通过它,你可以访问Controller作为参数传给 RenderView() 方法的特 定于视图的数据对象。
从你的视图里,你可以后期绑定或以强类型的方式访问“ViewData”。如果你的视图是从ViewPage继承而来,那么ViewData属性是个后期 绑定的字典。如果你的视图是从基于泛型的ViewPage
譬如,如下所示的我的Categories视图的后台类是从ViewPage

这意味着在我的视图代码里操作ProductsController.Categories() 提供的List

显示Categories视图:
如果你还记得本帖子最前面的截图的话,我们要在我们的 Categories 视图里显示产品分类列表:

我可以在我的Categories视图实现里用2种方式编写这个HTML界面生成代码:1) 在.aspx 文件里使用行内代码, 或者 2) 在.aspx 文件中使用服务器控件,然后在后台代码里使用数据绑定。
显示方法1:使用行内代码
目前的ASP.NET 网页, 用户控件和母版页支持使用 <% %> 和 <%= %>的句法来在html 标识内嵌入显示代码。我们 可以在Categories 视图里使用这个技巧,轻松地编写一个foreach循环,来生成HTML分类列表:

VS 2008在源码编辑器内为VB和C#提供完整的代码intellisense。这意味着,在对传入视图的Category模型对象操作时,我们将得 到intellisense:

VS 2008还为行内代码提供了完整的调试器支持(允许我们在调试器对视图中的代码设置断点以及动态检查任何东西):

显示方法2:使用服务器端控件
ASP.NET网页,用户控件和母版页还提供对使用声明式服务器端控件封装HTML界面生成的支持。不是象上面那样使用行内代码,我们可以使用 .NET 3.5中新的

注意上面 ListView 控件封装了显示值列表的情形,还负责处理列表中没有任何东西的情形(

重要注意事项:在MVC世界里,我们只想要把显示代码放在我们视图的后台代码里,不包括任何应用或数据逻辑。注意上面我们只有把强类型的 Category对象的ViewData集合赋值给ListView控件的逻辑。我们的ProductsController控制器类才是实际从数据库获取 Category对象列表的责任者,不是视图。
我们视图模板的ListView服务器端控件版本然后就会生成跟上面行内代码版本完全一样的HTML。因为我们在页面里没有

Html.ActionLink方法
你也许注意到的一件事情是,在上面视图代码片断中行内代码以及服务器端控件两个版本中对一个Html.ActionLink 方法的调用:
Html对象是 ViewPage 基类的一个辅助属性,ActionLink方法是它的一个辅助方法,它方便你动态地生成连回到控制器的action 方法的HTML超链接。如果你看一下上面生成的HTML输出图,你可以看到一些由该方法生成的一些HTML输出例子:
Beverages
我使用的Html.ActionLink方法的签名是这样的:
string ActionLink(string text, object values);
第一个参数表示要显示的超链接的内容(譬如这里是文字),第二个参数是个匿名对象 ,它代表用以生成实际URL的一串值,你可以认为它是生成字典的一个比较干净的方式。我会在将来讨论URL routing引擎的博客帖子 里仔细讨论这个参数的运用情形。但简而言之,你可以使用URL routing系统既处理进来的URL,也可以用它来生成你可以在返回的HTML输出 的URL。如果我们的routing规则是象这样的:
/
那么在ProductController的Category视图里编写这样的代码时:
<%= Html.ActionLink("Click Me to See Beverages", new { action="List", category="Beverages" } %>
ActionLink方法就会使用你应用的URL映射规则,换进你的参数,生成这样的输出:
Click Me to See Beverages
这方便了在你应用中生成URL和到你的控制器的AJAX回调。它也意味着你可以在一个地方更新你的URL routing规则,你整个应用中的代码 会在对进来的URL的处理和外出的URL的生成过程中自动采用新的变化。
重要注意事项: 为加强可测试性,目前的MVC框架并不支持你视图中针对服务器端控件的postback事件,取而代之的是,ASP.NET MVC应用生成超链接和对 控制器action的AJAX回调,然后只使用视图(以及其中的任何服务器端控件)显示输出。这有助于确保你的视图逻辑保持在最小限度,只注重于 显示,以及你可以单元测试你的Controller类,独立于你的视图,核实所有的应用和数据逻辑行为。我在将来的帖子里会对此做更深入的讨论。
结语
这第一个贴子非常长,但希望它对新的ASP.NET MVC框架中所有不同的组件是如何组合在一起的,如何使用它打造常见的现实世界场景的 应用提供了一个相当广泛的综览。 ASP.NET MVC的第一个公开预览版将在几个星期内发布,你将能够使用它来做我上面描述的一切。
虽然很多MVC固有的概念(特别是关注分离的观念)对该贴子的很多读者来说是比较新的,但希望本贴子展示了我们正在开发的ASP.NET MVC实 现是如何很干净地嵌合到现有的ASP.NET, .NET, 和 Visual Studio框架中的。你可以使用.ASPX, .ASCX 和 .MASTER文件以 及ASP.NET AJAX创建你的ASP.NET MVC 视图。今天ASP.NET中的非界面功能,譬如表单认证, Windows认证, 成员,角色, Url授 权, 缓存, Session 状态, 用户信息,健康监测, 配置,编译,本地化以及 HttpModules/HttpHandlers 都是完全支持MVC模型 的。
如果你不喜欢MVC模型,或者发现它对你的开发风格来说并不自然的话,你完全不必强用它的。它完全只是提供选项,并不替代现有的 WebForms Page Controller 模型。WebForms和MVC这2个模型在以后都会得到完全支持和改进。如果你想的话,你甚至可以建造一 个应用,部分使用WebForms编写,部分使用MVC编写。
如果你喜欢上面贴子里的东西的话(或者感兴趣想进一步了解的话),留意一下我这段时间的博客。我将进一步讨论MVC概念,使用它们来进一步建 造我们的电子商务应用,展示更多的MVC特性。
希望本文对你有所帮助,
Scott
十个习惯让你精通新的开发技术
这篇文章,是从我的《高效开发人员的五个特征》一文中抽出的一个观点。从我自身的事业和习惯中,我考虑了很多方式怎么样才能有效地学习。
1. 要看书。在成千上万的编程图书中,可能很大一部分根本毫无用处。但是仍然有很多图书对你的(编程)能力有很大的提升。我一直坚持,相比在网络上查找很多有用信息,在同类图书中查找要来得更容易更快捷。阅读技术图书可心更好地抓住核心内容。对于理论,架构和设计等方面来说,图书也一样很有帮助。只不过要找到高质量的、权威的信息,就不如网络上可供查找的范围广。
2. 读代码。这也是我很喜欢的一种方式。如果我并没有几年的专业编程工作经验,在学习之初我并不会去读很多复杂的代码。如果我要是早些开始学习,我将是一个比现在更好的程序员。但是,开始时我会从一些开源项目里,去学习那些源代码(当然,这些代码不能与我的工作有关,也不是我自己写的)。要从自己会使用到的,或者自己感兴趣的程序开始这项工作。我是从 Paint.net 这个网站里开始学习的,而且已经积累了很多关于 .NET 的编程技术。
读别人的代码可以为你提供更多不同的工作思路,这比你完全凭自己思考得到的工作方式要多。
3. 写代码。谨记,要写大量的代码。从根本上来讲,最好的学习方法就是实践。如果不写代码,你根本不能把(某种语言中)内在的东西学习透彻。学习之初,可以从一些技术指南和图书中照搬一些尽量简单的程序。当然,这种照搬是要自己完全手工输入,而不是复制和粘贴,这两种之间的效果差别是很大的。这种方法的主旨就在于,使知识内在化,并思考其用法,而不是盲目照抄。学习过程中,要时常查找新的 API 调用方法,这其实是简单的事情。
最重要的是,要写一个你自己的程序,不管它是一个简单的游戏,或者是一个参与开源项目的程序,还是一个公为你自己使用的简单插件。用不同的方式来写程序,尽量尝试使用新的技术,新的技巧,新的设计方式。一定要让现在的项目比以往的项目更好。想要成一个优秀的开发者,这一点是核心。
4. 与其他开发者交流。像 Apple,微软,Google 等大公司一样的新闻描述的一样,(与其他开发者交流)可以让你解决一些复杂的问题。虽然这并不能让你感觉到自己已经成一个团队或是社区的成员,但是这种方法可以让你接触到更多不同的想法。
不同类型的项目要求不同的设计方法,代码技术,开发流程和设计思想。如果你工作在一个小团队里,你不必与太多的人接触,只要在用户群会议中找到一些人(来讨论)即可。如果这样还不行的话,参与到在线论坛中与其他人讨论(这时你需要更努力地寻找高质量的讨论内容)。
6. 教会别人。相对于仅仅读代码之类的工作,教其他人学习可以让你更深入地学习某个技术,这种方法有着非凡的效果。教会别人某个技术,同样也会让你更专注于这种技术,并且可以比别人更深层次地理解它。同样你也会面对一些问题。
“如果你不能向一个六岁的儿童解析清楚一个概念,那么其实是你并没有完全理解它。”Albert Einstein说。
教学场景可以是无穷无尽的:与工作搭档一对一交流,休息碰面,非正式周会,学习茶会,教室,讨论发表会,等等。每周在相同理念开发者之间举办一次30分钟的非正式会议怎么样?每周,让几个人来就他们想要更深入了解话题,向大家传授这些技术知识,并且展开讨论。如果你知道你将要向团队成员们传授正学学习的知识,你是不是更想要了解这项技术的每个细节呢?
6. 收听网络电台。如果你有空闲的时间,可以订阅网络电台节目。我现在最喜欢的编程节目就是 .Net Rocks。这个节目还会做一些视频节目,叫做 dnrTV 。这样会让你即时捕捉到最新最好的技术。一个人是不能学习到所有知识的,而网络电台刚是一个学习了解广泛知识的途径。
7. 阅读博客。博客远远比阅读者要多,但是其中有一些却是极其优秀的。我这里不并不是要推荐博客,因为网络上已经有了足够多的博客。这是与真正在开发你所喜欢和使用的软件的开者联系的好方法。
8. 学习新的语言。即使你已经在 C(++,#) / JAVA 等语言上有很好的造诣,仍然有很多其他可以解决问题的编程语言。学习新的语言,是对你已有思维方式的挑战。这不仅仅是另一种语言,更是对思维的重新架构。的确,所有的语言最后都会被编译成汇编程序,但是这并不意味着高级语言毫无价值。
9. 学习不正确的方式。除了要学习应该怎么做,还要学习不应该怎么做。经常阅读 Dailywtf.com ,学习你并不知道的经验与教训。学习适当的面向对象设计方式,代码写作方式,和必须要写的代码等,是很好的方式,但是如果不细心的话也容易养成不良习惯。学习认识不正确的思路是负责项目开发至关重要的一环。
维基百科对很多觉的不正确方式有十分透彻的分类。
10. 要谦虚。
学习,意味着:
*
用更好的知识代替不完美的知识
*
增长你所不知道的知识
只有承认自己有所不足,才能有学习的动力。归根到底,就是谦虚,不对吗?如果你开始认为你已经掌握了所有需要的知识,那么你就危险了。真正的学习是如饥似渴地追逐知识并使其内在化,这需要很大的努力。我们都知道这一点,但是要必须时常不断地提醒自己。
c#远程获取网页内容
using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.IO;
namespace thief
{
class Program
{
static void Main(string[] args)
{
try {
WebClient MyWebClient = new WebClient();
MyWebClient.Credentials = CredentialCache.DefaultCredentials;//获取或设置用于对向Internet资源的请求进行身份验证的网络凭据。
Byte[] pageData = MyWebClient.DownloadData("http://www.chinaaspx.com");//从指定网站下载数据
string pageHtml = Encoding.Default.GetString(pageData); //如果获取网站页面采用的是GB2312,则使用这句
//string pageHtml = Encoding.UTF8.GetString(pageData); //如果获取网站页面采用的是UTF-8,则使用这句
Console.WriteLine(pageHtml);//在控制台输入获取的内容
using (StreamWriter sw = new StreamWriter("c:\\test\\ouput.html"))//将获取的内容写入文本
{
sw.Write(pageHtml);
}
Console.ReadLine(); //让控制台暂停,否则一闪而过了
}
catch(WebException webEx) {
Console.WriteLine(webEx.Message.ToString());
}
}
}
}
30 分钟教会你Flex和java沟通
http://coenraets.org/testdrive/flex4j/index.htm
30 Minutes Flex Test-Drive for Java Developers
By Christophe Coenraets
Last update: September 6th, 2006
Update (1/12/2007): I put together a Tomcat-based Test Drive Server that includes these samples running out-of-the box. Read this post for more info.
The objective of this test-drive is to give you, in a very short amount of time, an understanding of how Flex works and what it can do. This test-drive consists of a series of samples kept as concise as possible (typically between 10 and 50 lines of code) to clearly expose features of interest. The samples focus primarily on using Flex with a Java back-end. The intended audience is Java developers with no prior knowledge of Flex.
A few things to know before you start…
1. The Flex programming model is made of:
* MXML, an XML language used to declaratively lay out the user interface of your application.
* ActionScript, an ECMAScript compliant, object-oriented programming model. With some syntactical differences, ActionScript looks and feels similar to Java, and supports the same object-oriented constructs: packages, classes, inheritance, interfaces, strong (but also dynamic) typing etc.
* An extensive set of class libraries. The online API documentation is available here in a Javadoc-like format.
2. The Flex source code (.mxml and .as files) is compiled into Flash bytecode (.swf) that is executed at the client-side by the Flash virtual machine.
There are different ways you can use the Flex compiler (mxmlc):
* From the command line
* As part of an ant script
* Using FlexBuilder: the compilation process is integrated in the IDE
* Using the web compiler (available with the Flex Data Services). This is similar to the JSP compilation model: The first time an application is requested it is compiled into bytecode, which is then cached to serve subsequent requests.
You typically don't use the web compiler in a production environment. However, we are using it in this test-drive to minimize the number of components to install on your machine (all you will need to install is a war file).
3. The Flex product line includes:
* The Flex SDK which is free and includes the Flex libraries, the compiler (mxmlc), the Debugger, and the documentation.
* Flex Data Services (FDS), an optional set of server-side components deployed in your J2EE application server. FDS includes a Java RPC service (sample 3), publish/subscribe messaging (samples 6 and 7), and data management services (sample 8). FDS is free for a single-CPU deployment (FDS Express), and is licensed per CPU when deployed on multiple CPUs.
* FlexBuilder, an optional IDE for Flex development. Built as an Eclipse plug-in, FlexBuilder includes a design view and a code view, code hinting, visual Debugging, etc. FlexBuilder is licensed on a per developer basis.
* Optional charting components licensed on a per developer basis.
You can develop and deploy Flex applications entirely for free using the SDK and the IDE of your choice. I will highlight the examples in this test-drive that require the Flex Data Services.
Installing the Test Drive Files
Since we will be using the Flex Data Services, you need a J2EE server, or, at a minimum, a Servlet container.
1. Download the testdrive war file.
* If you use an application server that implements the full J2EE stack (IBM Websphere, BEA Weblogic, JBoss, JRun, etc.), download the version below. It includes the Flex Data Services, the sample applications, and an embedded HSQLDB database to support the samples.
Proceed to license and download
* If you use Tomcat 5.5.x, download the version below. It includes the Flex Data Services, the sample applications, an embedded HSQLDB database to support the samples, and JOTM (an open source implementation of the Java Transaction API required by the data management services wich are used in sample 8).
Proceed to license and download
* If you use Tomcat 5.0.x, download the version below. It includes the Flex Data Services, the sample applications, an embedded HSQLDB database to support the samples, and JOTM (an open source implementation of the Java Transaction API required by the data management services wich are used in sample 8):
Proceed to license and download
Note: the only difference between the 5.5.x and 5.0.x version is the configuration of JOTM in META-INF\context.xml (the way you configure UserTransaction has changed in Tomcat 5.5).
2. Deploy testdrive.war in your application server
3. Access http://localhost:8080/testdrive (change the host name and port number as appropriate).
Sample 1: Accessing data using HTTPService
Run the sample:
1. Access http://localhost:8080/testdrive/sample1/SampleXML.mxml
Notice that there is a delay the first time you access an application in this test-drive. This is because we are using the web compiler which compiles your application into bytecode the first time it is accessed (similar to the JSP compilation model). Subsequent requests to the same application will be much faster since the application is already compiled. In a production environment, you would typically deploy precompiled applications.
Note: Depending on your configuration, you may need to increase the heap size of your application server's JVM to use the web compiler. This would not be required in a production environement since you typically don't use the web compiler. If you get a java.lang.OutOfMemoryError exception while trying to access a sample for the first time, you must increase your heap size.
2. Click “Get Data”: The DataGrid is populated with XML data returned by catalog.jsp
3. Also notice some of the built-in DataGrid features:
* Sortable columns (click on a column header)
* Moveable columns (click on a column header and, with the mouse button pressed, move the column to a new position)
Code walkthrough:
Open the following files in a code editor:
* testdrive/sample1/SampleXML.mxml
* testdrive/sample1/catalog.jsp
Using HTTPService, you can send HTTP requests to a server, and consume the response. Although the HTTPService can be used to consume different types of responses, it is typically used to consume XML. You can use the HTTPService with any kind of server-side technology: JSP, Servlet, ASP, Ruby on Rails, PHP, etc. You specify the target service in the url property of HTTPService.
Flex provides sophisticated data binding capabilities. You can bind the value of a property to the value of another property, or to an expression in general. In this example, the dataProvider property of the DataGrid is bound (using the curly braces notation) to the lastResult property of the HTTPService.
HTTPService calls are asynchronous. The result event is triggered on the HTTPService when the data becomes available to the client application. The fault event is triggered if an error occurs at the server-side, or if the network becomes unavailable. (See sample 5, for an example of coding result and fault event handlers).
By default, the XML document retrieved from the server is deserialized into an object graph. This allows you to navigate through the result using the dot notation. You can also get the result as an XML document by specifying resultFormat=”e4x” on the HTTPService. In that case, you can parse the document using E4X (ECMAScript for XML).
More info:
* Both HTTP and HTTPS are supported
* Instead of using the url property to specify a hardcoded URL, you can specify a logical name in the destination property. You then map this logical name to an actual URL in WEB-INF\flex\proxy-config.xml. In this example, you could replace url=”catalog.jsp” with destination=”catalog” (open WEB-INF\flex\proxy-config.xml to see how the catalog destination is configured). As another example, to get the headlines from the New York Times, specify destination=”news”, and change the DataGrid data binding to: dataProvider=”{srv.lastResult.rss.channel.item}”.
Sample 2: Accessing data using Web Services
Run the sample:
1. Access http://localhost:8080/testdrive/sample2/SampleWebService.mxml
2. Click “Get Data”: The DataGrid is populated with data returned by the ProductWS web service hosted on my blog.
Code walkthrough:
Open the following file in a code editor:
* testdrive/sample2/SampleWebService.mxml
Access the wsdl file for the web service used in this example:
* http://coenraets.org/services/ProductWS?wsdl
Using the WebService tag, you can invoke SOAP-based web services deployed in your application server or on the internet. Objects returned by a web service are automatically deserialized into ActionScript objects. Similarly ActionScript objects passed as arguments to a web service operation are serialized according the wsdl description.
Notice that we also added DataGrid column definitions (using DataGridColumn) in this example.
More Info:
* Flex supports both RPC-encoded and document-literal web services
* Like HTTPService, WebService calls are asynchronous: You can code result and fault event handlers
* Like when using HTTPService, you can use a logical name instead of a hardcoded URL to identify the service, and map the logical name in WEB-INF\flex\proxy-config.xml.
Sample 3: Accessing data using Java RPC
Run the sample:
1. Access http://localhost:8080/testdrive/sample3/SamplePOJO.mxml
2. Click “Get Data”: The DataGrid is populated with data returned by the getProducts() method of the ProductService Java class.
Code walkthrough:
Open the following files in a code editor:
* sample3\SamplePOJO.mxml
* WEB-INF\src\flex\testdrive\store\ProductService.java
* WEB-INF\flex\remoting-config.xml
Using RemoteObject, you can directly invoke methods of Java objects deployed in your application server, and consume the return value. The return value can be a value of a primitive data type, an object, a collection of objects, an object graph, etc.
The value of the destination property of RemoteObject is a logical name that is mapped to a fully qualified java class in remoting-config.xml.
Java objects returned by server-side methods are deserialized into either dynamic or typed ActionScript objects. In this example, we don't have an explicit ActionScript version of the Product Java class. Product objects are therefore deserialized into dynamic objects. In sample 5, we work with an explicit Product class in ActionScript.
More info:
* Like HTTPService and WebService, RemoteObject calls are asynchronous. You use the result and fault events of the RemoteObject to handle results and errors (see sample 5).
Sample 4: Flex Programming Model 101
Run the sample:
1. Access http://localhost:8080/testdrive/sample4/MasterDetail.mxml
2. Click a phone in the list: the details for the selected phone appear in the right panel
Code walkthrough:
Open the following files in a code editor:
* sample4\MasterDetail.mxml
* sample4\Thumb.mxml
* sample4\ProductView.mxml
Like in any other object-oriented programming language, a Flex application is made of a collection of classes. Using Flex, you can create classes using MXML or ActionScript. You typically create view classes in MXML, and Model and Controller classes in ActionScript.
When you create an mxml file, you are actually creating a class. The root node of the mxml document indicates the class you extend. For example, creating a file named MasterDetail.mxml with an
public class MasterDetail extends Application {
}
Similarly, creating a file named ProductView.mxml with a
public class ProductView extends Panel {
}
Once you have defined a class, you can use it programatically or declaratively (as a tag in MXML) without the need for an additional descriptor file. Public properties are automatically available as tag attributes. For example, in MasterDetail.mxml, we define the
Also notice the support for CSS style sheets.
Sample 5: Updating Data
Run the sample:
1. Access http://localhost:8080/testdrive/sample5/SampleUpdate.mxml
2. Select a phone
3. Modify some data in the right panel. For example, the price.
4. Click Update: changes are sent to the back-end and persisted in the database by the ProductService class.
Code walkthrough:
Open the following files in a code editor:
* sample5\SampleUpdate.mxml
* sample5\ProductForm.mxml
* sample5\Product.as
* WEB-INF\src\flex\testdrive\store\ProductService.java
* WEB-INF\flex\remoting-config.xml
In Product.as we use the [RemoteClass(alias=”flex.testdrive.store.Product”)] annotation to map the ActionScript version of the Product class (Product.as) to the Java version (Product.java). As a result, Product objects returned by the getProducts() method of ProductService are deserialized into instances of the ActionScript Product class. Similarly, the instance of the ActionScript Product class passed as an argument to the update method of the RemoteObject is deserialized into an instance of the java version of the Product class at the server-side.
Sample 6: Publish/Subscribe Messaging (Data Push Use Case)
Run the sample:
In this example, a Java component publishes simulated real time values to a message queue. The Flex client subscribes to that queue and displays the values in real time.
1. To start the feed component at the server-side: access http://localhost:8080/testdrive/sample6/startfeed.jsp.
(You can stop the feed by accessing http://localhost:8080/testdrive/sample6/stopfeed.jsp)
2. Open a browser and access http://localhost:8080/testdrive/sample6/FeedClient.mxml
3. Click the “Subscribe to 'feed' destination” button: Pushed values appear in the text field
Code walkthrough:
Open the following files in a code editor:
* sample6\FeedClient.mxml
* WEB-INF\src\flex\testdrive\feed\Feed.Java
* WEB-INF\flex\messaging-config.xml
Flex supports publish/subscribe messaging through the Flex Message Service (part of the Flex Data Services). The Flex Message Service manages a set of destinations that Flex clients can publish and subsribe to. Flex provides two components, Producer and Consumer, that you use to respectively publish and subscribe to a destination. To subscribe to a destination, you use the subscribe() method of the Consumer class. When a message is published to a destination you subscribed to, the message event is triggered on the Consumer.
In Feed.java, the Flex Java API (MessageBroker, AsyncMessage) is used to publish messages to the Flex destination. The Javadoc documentation for the Java API is available here. Another option to exchange messages bewteen Flex and Java applications is to map Flex destinations to JMS topics, essentially allowing a Flex client to publish and subscribe to JMS topics. In addition to JMS, the Flex Message Service adapter architecture allows you to integrate with any kind of messaging system.
Flex destinations are configured in messaging-config.xml. You can configure a destination to deliver the messages using a real-time protocol or using polling.
Additional resources:
Check out the portfolio viewer sample for a more complete example of data push.
Sample 7: Publish/Subscribe Messaging (Collaboration Use Case)
Run the sample:
1. Open http://localhost:8080/testdrive/sample7/Chat.mxml in two different browser windows
2. Type a message in one of the chat clients and click “Send”: the message appears in the two chat clients
Code walkthrough:
Open the following files in a code editor:
* sample7\Chat.mxml
* WEB-INF\flex\messaging-config.xml
This sample builds on the concepts and APIs introduced in the previous example. To publish a message from a client, you use the send() method of the Producer class.
The messaging and real time infrastructure available in Flex enables collaboration and data push applications to be built in a scalable and reliable manner while preserving the lightweight web deployment model.
Additional resources:
Check out the Google Map collaboration sample.
Sample 8: Data Management Services
Testing persistence:
1. Open a browser and access http://localhost:8080/testdrive/sample8/SampleDataService.mxml
2. Click a DataGrid cell, modify the data in that cell, and press Enter
3. Click the Refresh button in your browser: Notice that the new value appears in the cell indicating that the data has been successfully persisted.
Testing data synchronization across clients:
1. Open the same application in a second browser window
2. Resize the two browser windows so that you can see both at the same time on your screen
3. Modify data in one browser, and press Enter: notice that the update is automatically pushed to the other client
Code walkthrough:
Open the following files in a code editor:
* sample8\SampleDataService.mxml
* sample8\Product.as
* WEB-INF\src\flex\testdrive\store\ProductAssembler.java
* WEB-INF\src\flex\testdrive\store\ProductService.java
* WEB-INF\flex\data-management-config.xml
In addition to the RPC services described in samples 1, 2, and 3, the Flex Data Management Services provide an innovative and highly productive approach to synchronize data across tiers and between clients. The Flex Data Management Services consist of a client-side API and server-side services:
At the client-side, “managed objects” keep track of changes made to the data, and notify the back-end of these changes. In SampleDataService.mxml, all you have to do is:
* Define a DataService pointing to the “product” destination defined in data-management-config.xml
* Invoke the DataService's fill() method to populate the “products” array
* Bind the DataGrid to the products array
You don't have to keep track of changes made to the data, nor do you have to invoke remote services to notify the back-end of the changes (create, update, delete) made at the client side.
At the server-side, the Data Service receives the list of changes and passes it to your server-side persistence components. The Data Service also pushes the changes to other clients. In this example, the “product” DataService configured in data-management-config.xml uses the java-dao adapter, indicating that we will take care of the persistence code with our own Java classes (another option is to use the Hibernate adapter). There is no specific contract imposed on the Java class that provides the persistence implementation: You map methods such as fill and sync to actual methods in an assembler class (in this case: ProductAssembler). In the assembler class, you typically delegate the actual persistence implementation to existing persistence classes (in this case: ProductService).
Sample 9: Data Visualization
Run the sample :
1. Access http://localhost:8080/testdrive/sample9/Dashboard.mxml
2. Click on any data point on the line chart, the column chart at the bottom of the screen is updated to display a product breakdown for the selected month.
Code walkthrough:
Open the following files in a code editor:
* sample9\Dashboard.mxml
Flex provides and extensive library of charting components such as LineChart and PieChart used in this example. Other charting components include ColumnChart, BarChart, AreaChart, BubbleChart, CandlestickChart, PlotChart, HLOCChart.
Flex charting components work like the other data aware components: you use the dataProvider property to bind a chart to data.
Because they leverage vector graphics, charting components can be redrawn and animated at the client-side, helping the end-user to better understand data trends and transitions.
Additional resources:
* Dashboard sample on adobe.com
* Ely Greenfield's Chart Sampler
* Interactive bubble chart, another charting component example from Ely
Sample 10: Rich Media
Run the sample:
1. Access http://localhost:8080/testdrive/sample10/SampleMedia.mxml
2. Click on a question in the list: a video appears, adding a rich media experience to this traditional “FAQ” application.
Code walkthrough:
Open the following files in a code editor:
* sample10\SampleMedia.mxml
* sample10\questions.mxml
HTTPService is used to retrieve an XML document that contains the list of questions, video links, and cuepoints.
The source attribute of the VideoDisplay component is bound to the selectedItem in the List, so that the “answer video” automatically starts palying when a question is clicked.
The cuepoint event is used on VideoDisplay to synchronize the captions (the captions are not part of the video, but where read from the XML document).
Also notice how the resizeEffect is used on the Panel component, to animate the panel when it is resized.
Finally the applications has two view states: the default state and the “videoPlaying” state. View states allow you to declaratively (using MXML) represent different states of the applications. In this simple case, the Panel is expanded in the videoPlaying state to reveal the VideoDisplay component.
Appendix A: Data Access and Rendering Performance
To test data retrieval and rendering:
1. Access http://localhost:8080/testdrive/appendixa/Perf.mxml
2. Specify a number of rows to retrieve
3. Click “Get Data”
4. Watch the number of milliseconds it took to retrieve and render the data
To test client-side sorting:
1. Specify 20000 rows
2. Click “Get Data”
3. Click on a column header to sort 20000 rows at the client-side
Code walkthrough:
Open the following files in a code editor:
* sample11\Perf.mxml
* WEB-INF\src\flex\testdrive\census\CensusService.java
* WEB-INF\flex\remoting-config.xml
At the client-side, we use RemoteObject to remotely invoke the getItems method on the CensusService class deployed in the application server. The CensusService class accesses the embedded HSQLDB database and returns the number of rows requested. Using RemoteObject, the data is transferred in a binary format over HTTP.
Appendix B: Creating Custom UI Components
Run the sample:
1. Access http://localhost:8080/testdrive/appendixb/Store.mxml
2. Modify the price range using the slider: filtered items are animated in and out of the list to help the user visualize the products affected by the filter
Code walkthrough:
Open the following files in a code editor:
* sample12\Store.mxml
* sample12\AnimatedTileList.as
Although many Flex applications are built entirely using the UI components available in the Flex framework, you can create custom UI components by extending classes in the Flex framework. AnimatedTileList.as provides an example of a class that extends Canvas to provide an animated version of the TileList component.
Summary and Next Steps
This test-drive has provided you with a first experience of Flex, primarily focused on Java integration. However, we have just scratched the surface, and there are many other online resources focusing on the different aspects of the product. flex.org is a great place to start to become familiar with these resources. The developer experience is an important aspect of Flex. So also make sure you download FlexBuilder to start building your own Flex projects.
Don't hesitate to send me your questions/comments on this test-drive and any suggestion to improve it. Thanks! christophe at coenraets dot org.
Eclipse+SVN+Flex Builder集成开发环境安装的视频!
阿银录制的环境安装视频:
地址:
http://www.cnflex.org/video/IDEInstall/IDEInstall1.html
Mikel