Yok

苦海无涯,回头是岸啊

MonoRail - 生命周期及controller/action/view详解

和传统的asp.net webform相比, MonoRail的生命周期简单多了. 一个web请求所经历的主要步骤如下:

1. MonoRailHttpHandlerFactory接收到请求后, 收集上下文, 创建MonoRailHttpHandler.
2. MonoRailHttpHandler分析请求的url, 创建相应的controller并调用相应的action(实际就是controller里的一个方法), url表示了访问的是哪个controller的哪个action. 默认情况下, 格式是/controller名称/action名称.rails. MonoRailHttpHandler会根据请求的url初始化名称相对应的controller并调用相应的action, 例如, home/index.rail对应HomeControll 如果controller继承自SmartDispatcherController, 还会将action的参数与Request的数据进行绑定.
3. Controller调用ViewEngine的Process方法, 输出html内容.

一个页面的生命周期就这样完成了, 是不是觉得很清爽呢 :)

我们再来看看在自己写的action里要做些什么:

1. 处理业务逻辑.
2. 如果需要向view输出内容的话, 把需要被view引用的对象添加到PropertyBag.
3. 如果需要对view进行选择或控制, 调用适当的和view相关的方法.

同样是这么的简单. server control没了, viewstate没了, postback也没了. 在深入了解了MonoRail之后, 你会发现, 这些东西都不是必须的.

下面给MonoRail的各种概念来个比较详细的解释, 大部分摘自MonoRail参考手册

View
默认每个action都会有一个对应的view. 当使用NVelocityViewEngine的时候, view就是一个NVelocity的模板. view文件布局规则如下
view根目录\Controller名称\action名称.vm
Controller在action执行完后, 将会调用模板引擎输出相应的内容. Velocity模板语法参考请看这里

Controller
Controller是MonoRail的核心. MonoRail有一个名为Controller的抽象类, 应用中所有Controller都要从此继承.
Controller的名称一般以Controller后缀, 而Controller的名称默认是类名去掉Controller后缀. 例如HomeController的名称是Home. 如果不

想要这种命名规则的话, 可以标记ControllerDetailsAttribute去指定名称.

下面是基类Controller的一些常用的成员和特性:

Redirect, 和HttpResponse.Redirect类似:
    Redirect( String url )
    Redirect( String controller, String action )
    Redirect( String area, String controller, String action )

CancelView() 如果不需要处理view, 或者甚至action没有对应的view, 就应该调用它停止view的执行

RenderView, 输出view:
   RenderView(String name ) 
   RenderView(String controller, String name ) 

RenderShareView(String name) :
输出在视图根目录的view. 如果一个view需要被多个controller共用, 就应该放在视图根目录.

RenderText(String name) :
输出一段文本, 实际上等同于Response.Write, 并且调用RenderText后, 原来的view的输出将会被取消.

不要忘了, Response对象还可以照常使用. 在用模板引擎输出一个view的同时, 你也可以通过Response.Write输出一些额外的内容, 例如js.

PropertyBag:
PropertyBag是基类Contorller里的一个简单的IDictionary, 被存放在HttpContext.Current.Item里. 放在PropertyBag里的对象就可以在view里被引用

Flash:
特性和PropertyBag完全一样, 只是语义上的区别, PropertyBag用于给view提供数据, Flash则是用来在Request中存放临时的数据.

Helplers:
NVelocity模板并不像aspx那样可以使用任何.NET语法, 他只允许对特定容器里对象的访问. 如果有需要借助后台的类去对界面显的内容进行处理的话(例如对数字或日期进行格式化), 可以创建对象的实例, 然后添加到Helpers集合里. 例如有一个Fomatter类, 里面有多个用于格式化的方法, 则在action里加上语句:

Helpers.Add("Formatter"new Formatter());

然后就可以在模板里使用Formatter了.

$Formatter.FormatTimeRange($dateFrom, $dateTo)

MonoRail里内置了很多Helper, 例如AjaxHelper, HtmlHelper, ValidationHelper, 在官方的sample中会常见到他们在模板里的使用. 他们是在基类Controller初始化的时候被添加到Helpers集合里的.

在view里引用对象

view要引用到的对象应添加到PropertyBag里. 在NVelocity的模板里, 可以引用以下对象
Context (IRailsEngineContext, 类似HttpContext)
Request 
Response
Session
所有Request中的元素
所有Flash中的元素
所有PropertyBag中的元素

数据绑定

这是一个能让你消除大量无聊的代码的特性, 只要controller继承自SmartDispatcherController, MonoRailHttpHandler就会根据querystring和form提交的数据, 寻找最合适的方法的重载, 并且把post的数据绑定到对应的参数. 支持所有的基本类型以及他们的数组, 还有HttpPostedFile. 参考手册上有这样的例子

<form action="CreateAccount.rails"> 
  Name: 
<input type="text" name="name" /> <br>
  Email: 
<input type="text" name="email" /> <br>
  Country: 
  
<select name="country"> 
    
<option value="44">England</option>
    
<option value="55">Brazil</option>
  
</select>
  
<br>
  
<input type="submit" value="Create" />
</form>

这样的form提交后, 对应的action的参数将会被自动绑定

public class AccountController : SmartDispatcherController
{
  
public void CreateAccount(String name, String email, int country)
  {
    
// perform your create account logic here ..
    Redirect("home""index");
  }
}

 假如存在一个Account类, 我们还可以让他直接创建Account的实例并且绑定数据, 作为参数传给action, 只需在参数加上DataBindAttribute:

public void CreateAccount([DataBind]Account account)
{
   
//
}

为了避免html元素id的命名冲突, 还可以通过Prefix属性指定前缀

<form action="CreateAccount.rails"> 
  Name: 
<input type="text" name="accName" /> <br>
  Email: 
<input type="text" name="accEmail" /> <br>
  Country: 
  
<select name="accCountry"> 
    
<option value="44">England</option>
    
<option value="55">Brazil</option>
  
</select>
  
<br>
  
<input type="submit" value="Create" />
</form>

public void CreateAccount([DataBind(Prefix="acc")]Account account)
{
   
//
}

Webform如此复杂, 主要是为了构造有层次结构的控件树, 实现事件驱动模型和维持控件postback后的状态, 而MonoRail是以controller/action/view为核心, 一个url对应的是controller的一个方法, 来自querystring, form post的数据SmartDispatcherController已经帮你处理好了, 你在action里要做的事情通常只是去处理它为你准备好的参数, 并且把view需要用到的对象放进PropertyBag里, 一切都是如此的简单

posted on 2005-11-07 16:07  Yok  阅读(6181)  评论(10编辑  收藏  举报

导航