基于WebForm的Front Controller模式框架
经过一段时间努力终于把WebForm下的Front Contoller模式初型完成;虽然框架和MonoRail是基于同一种模式,但有最大的区别就是该框架的Controller是依赖于接口完全脱离Asp.net相关的特性;使用者可以在Controller中专注于业务逻辑的处理,对于页面的输出和控制由接口的实现者去完成,这样Controller就可以得到更好灵活性。框架的另一特点就是接口成员数据自动绑定和自动切入Controller功能的透明性,使用者并不用理会这些只要简单的配置一下Controler和View程序集即可。由于组件提供以上方便功能,即使在使用时没有传统WebForm的事件区动和视图状态管理的同时也能达到方便快速的开发效果。
框架还是初型阶段,但在简单的使用上已经相当好的效果。下面通过简单的例子来看下这个框架在开发中有多方便。
登陆例程:
制定登陆相关接口和处理的Controller
public interface ILogin
{
string UserName
{
get;
set;
}
string PassWord
{
get;
set;
}
}
[HFSoft.MVC.FormMapper("~/FrmLogin.aspx")]
public void Login(Views.ILogin login)
{
//..
}
根据接口描述创建相关的Aspx页面:
<form method="post" action="FrmLogin.aspx" >
<div>
<table>
<tr>
<td style="width: 100px">
用户名</td>
<td style="width: 100px">
<input id="Text1" name="username" type="text" value="<% context.ToValue(login.UserName); %>" /></td>
</tr>
<tr>
<td style="width: 100px">
登陆</td>
<td style="width: 100px">
<input id="Text2" name="password" type="text" value="<% context.ToValue(login.PassWord); %>" /></td>
</tr>
<tr>
<td style="width: 100px">
</td>
<td style="width: 100px">
<input id="Submit1" type="submit" value="登陆" /></td>
</tr>
</table>
</div>
</form>
在新建Aspx文件时和传统的Aspx文件有所不同:
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm1.aspx.cs" Inherits="MVC_Sample1.WebForm1" %>
<%@ Page Language="C#" AutoEventWireup="true" Inherits="HFSoft.MVC.FormContext" %>
对于页面在接收请求后是如果创建相关接口实例、绑定数据成员和切入到相关Controller中都是对使用者透明的(使用者唯一要做的就是配置实现接口对象的程序集)。
数据查询例程:
这个例程的接口描述相对复杂一点,因为接口某一成员是对象类型。即使是这样框架也能够进行数据绑定和对象创建。
public interface ICustomerView
{
IList<NorthWind.Entities.Customers> Customers
{
get;
set;
}
CustomerFilter Filter
{
get;
set;
}
}
public class CustomerFilter
{
private string mCompanyName;
public string CompanyName
{
get
{
return mCompanyName;
}
set
{
mCompanyName = value;
}
}
}
[HFSoft.MVC.FormMapper("~/FrmCustomerView.aspx")]
public void CustomerView(Views.ICustomerView view)
{
view.Customers = view.Filter.GetExpression().List<NorthWind.Entities.Customers>();
}
框架提供以属性标记的方式合保证成员对象的创建和绑定,因此接口实现者必通过属性的方式来标记成员。标记过程也是非常方便和简单:
private CustomerFilter mFilter;
[HFSoft.MVC.Bind("filter")]
public CustomerFilter Filter
{
get
{
return mFilter;
}
set
{
mFilter = value;
}
}
页面代码
<form id="form1" action="FrmCustomerView.aspx" method ="post" >
<div>
<table>
<tr>
<td>
<table>
<tr>
<td style="width: 100px">
公司名称</td>
<td style="width: 100px">
<input id="Text1" name="filter.companyName" value="<% context.ToValue(view.Filter.CompanyName); %>" type="text" /></td>
<td style="width: 100px">
地区</td>
<td style="width: 100px">
<input id="Text2" name="filter.region" value="<% context.ToValue(view.Filter.Region); %>" type="text" /></td>
</tr>
<tr>
<td style="width: 100px">
城市</td>
<td style="width: 100px">
<input id="Text3" name="filter.city" value="<% context.ToValue(view.Filter.City); %>" type="text" /></td>
<td style="width: 100px">
</td>
<td style="width: 100px">
<input id="Submit1" type="submit" value="查询" /></td>
</tr>
</table>
</td>
</tr>
<tr><td>公司名称</td><td>地区</td><td>城市</td></tr>
<%
foreach (NorthWind.Entities.Customers item in view.Customers)
{
%>
<tr><td><%context.ToValue(item.CompanyName); %></td><td><%context.ToValue(item.Region); %></td><td><%context.ToValue(item.City); %></td></tr>
<% }%>
</table>
</div>
</form>
以上例程中输入控件虽然不是服务控件,但都可以在提效后得到保存;这归功于框架的绑定功能,由于接口成员和页面元素值的自动绑定,使得在提交后可以通过当前接口重新得到信息。
框架还在不断完善中,正在构想加入Controller执行拦载功能接口,错误处理拦载接口等功能;有兴趣或有意见的朋友多提一下意见。