Asp.net MVC 示例项目"Suteki.Shop"分析之---Controller

     在上文中,介绍了如何安装和使用Suteki,今天我们通过源码来看一下Suteki是如何使用
Controller。

     在Suteki中,其使用Abstract的方式来定义一个ControllerBase,以此作为所有Controller
的基类,下面是其Controller的类设计图:

    
    
      在该基类中定义了一些Controller中常用到的方法,比如为当前视图添加MetaDescription,
Title等:   

[Rescue( " Default " ), Authenticate, CopyMessageFromTempDataToViewData]
public   abstract   class  ControllerBase : Controller, IProvidesBaseService
{
        
private  IBaseControllerService baseControllerService;

        
///   <summary>
        
///  Supplies services and configuration to all controllers
        
///   </summary>
         public  IBaseControllerService BaseControllerService
        {
            
get  {  return  baseControllerService; }
            
set  
            { 
                baseControllerService 
=  value;

                ViewData[
" Title " =   " {0}{1} " .With(
                    baseControllerService.ShopName,
                    GetControllerName());

                ViewData[
" MetaDescription " =   " / " { 0 }/ "" .With(baseControllerService.MetaDescription);
            }
        }

        
public  ILogger Logger {  get set ; }

        
public   virtual   string  GetControllerName()
        {
            
return   "  - {0} " .With(GetType().Name.Replace( " Controller " "" ));
        }


        
public   virtual   void  AppendTitle( string  text)
        {
            ViewData[
" Title " =   " {0} - {1} " .With(ViewData[ " Title " ], text);
        }

        
public   virtual   void  AppendMetaDescription( string  text)
        {
            ViewData[
" MetaDescription " =  text;
        }

     
public   string  Message
     {
   
get  {  return  TempData[ " message " as   string ; }
   
set  { TempData[ " message " =  value; }
     }

  
protected   override   void  OnException(ExceptionContext filterContext) {
   Response.Clear();
   
base .OnException(filterContext);
  }
}

    

      当然,细心的朋友发现了该抽象类中还包括一个IBaseControllerService接口实例。
该接口的主要定义了一些网店系统信息,如店铺名称,版权信息,Email信息等,如下:

public   interface  IBaseControllerService
{
    IRepository
< Category >  CategoryRepository {  get ; }
    
string  GoogleTrackingCode {  get set ; }
    
string  ShopName {  get set ; }
    
string  EmailAddress {  get set ; }
    
string  SiteUrl {  get ; }
    
string  MetaDescription {  get set ; }
    
string  Copyright {  get set ; }
    
string  PhoneNumber {  get set ; }
    
string  SiteCss {  get set ; }
}

   

      而作为唯一一个实现了该接口的子类“BaseControllerService”定义如下:  

public   class  BaseControllerService : IBaseControllerService
{
        
public  IRepository < Category >  CategoryRepository {  get private   set ; }
        
public   string  GoogleTrackingCode {  get set ; }
        
public   string  MetaDescription {  get set ; }
        
private   string  shopName;
        
private   string  emailAddress;
        
private   string  copyright;
        
private   string  phoneNumber;
        
private   string  siteCss;

        ..
}

    
      而初始化BaseControllerService实例并将配置文件中的信息绑定到该类实例中的操作交给了Windsor,
该组件在Castle中用于实现IOC操作,其配置文件位于项目Suteki.Shop/Configuration/Windsor.config.
下面是其配置结点内容:

< component
  id
= " IBaseControllerService:test.jumpthegun.co.uk "
  service
= " Suteki.Shop.Services.IBaseControllerService, Suteki.Shop "
  type
= " Suteki.Shop.Services.BaseControllerService, Suteki.Shop "
  lifestyle
= " transient " >
  
< parameters >
    
< ShopName > Suteki Shop </ ShopName >
    
< EmailAddress > info@sutekishop.co.uk </ EmailAddress >
    
< GoogleTrackingCode > UA - 1643677 - 4 </ GoogleTrackingCode >
    
< MetaDescription > Suteki Shop  is  a  new  self service eCommerce solution. Search engine optimised and fully customisable </ MetaDescription >
    
< SiteCss > Site.css </ SiteCss >
  
</ parameters >
</ component >

    
     这类就完成了把网店的系统信息绑定到Controller中的操作,而Controller就会在其基类中将相关的
信息绑定到ViewData中,如下: 

 ViewData[ " Title " =   " {0}{1} " .With(baseControllerService.ShopName, GetControllerName());
 ViewData[
" MetaDescription " =   " / " { 0 }/ "" .With(baseControllerService.MetaDescription);

 
 
     到这里,其实大家应该发现这种对Controller的处理与我们以前所使用的PageBase方式相似,就是将
项目中所有的Page都继承自PageBase,然后在相应的Page中引用PageBase中定义的属性和方法。

     有了ControllerBase,我们看一下在相应的子Controller中是如何使用的,这里有一个例子,
ProductController(位于Suteki.Shop/Controllers/ProductController.cs): 
   

public   class  ProductController : ControllerBase
{
    
    
 
public  ActionResult Item( string  urlName)
 {
  
return  RenderItemView(urlName);
 }
    ..
    
 ActionResult RenderItemView(
string  urlName)
 {
  var product 
=  productRepository.GetAll().WithUrlName(urlName);
  AppendTitle(product.Name);
  AppendMetaDescription(product.Description);
  
return  View( " Item " , ShopView.Data.WithProduct(product));
 } 
 
}

 

      该Controller中的Action:"Item"调用了RenderItemView()就是使用了基类中的AppendTitle,
AppendMetaDescription。下面是其运行时的截图:
    
        


        
    
      除了上面所说的这种ControllerBase方式,Suteki.Shop还使用了Controller<T>方式来实现对
一些公用Action的操作,比如列表,编辑,添加记录,调整记录上下位置等。而这块实现代码被放
置在了Suteki.Common/ScaffoldController.cs和OrderableScaffoldController.cs文件中,其中
ScaffoldController为父类,其中包括列表,编辑,添加Action等。

 

Code

   

     大家请注意ScaffoldController类中的几个公共属性:   

     public  IRepository < T >  Repository {  get set ; }
    
public  IRepositoryResolver repositoryResolver {  get set ; }
    
public  IValidatingBinder ValidatingBinder {  get set ; }
    
public  IHttpContextService httpContextService {  get set ; }

   

      其中Repository是一些对数据CRUD的操作对象,下面是Repository中的一些接口成员方法:

public   interface  IRepository < T >   where  T :  class
{
    T GetById(
int  id);
    IQueryable
< T >  GetAll();
    
void  InsertOnSubmit(T entity);
    
void  DeleteOnSubmit(T entity);
    [Obsolete(
" Units of Work should be managed externally to the Repository. " )]
    
void  SubmitChanges();
}

 

      这样就可以在ScaffoldController使用统一的接口函数调用相应子类中的实现方法了。   

      而ScaffoldController的子类OrderableScaffoldController则实现了对数据集合中的某行元素
上下移动的操作:
   

public   class  OrderableScaffoldController < T >  : ScaffoldController < T >   where  T :  class , IOrderable,  new ()
{
    
public  IOrderableService < T >  OrderableService {  get set ; }

    
protected   override  ActionResult RenderIndexView( int ?  page)
    {
        var items 
=  Repository.GetAll().InOrder().AsPagination(page  ??   1 );
        
return  View( " Index " , ScaffoldView.Data < T > ().With(items));
    }

    
public   override  ActionResult New()
    {
        T item 
=   new  T
        {
            Position 
=  OrderableService.NextPosition
        };
        
return  View( " Edit " , ( object )BuildEditViewData().With(item));
    }

   [UnitOfWork]
    
public   virtual  ActionResult MoveUp( int  id,  int ?  page)
    {
        OrderableService.MoveItemAtPosition(id).UpOne();
  
return  RedirectToAction( " Index " );
    }
    [UnitOfWork]
    
public   virtual  ActionResult MoveDown( int  id,  int ?  page)
    {
        OrderableService.MoveItemAtPosition(id).DownOne();
  
return  RedirectToAction( " Index " );
    }
}

   

     注:IOrderableService的实现相对复杂一些,具体内容详见Suteki.Common/Services/OrderableService.cs.
     
     按说有了这些功能之后,只要在相应的子类中直接继承使用就可以了,但在Suteki.Shop项目中
作者又对OrderableScaffoldController进行了一个“继承式”扩展,提供了与前面所说的那个“
ControllerBase"相似的方法定义,如下:

[Authenticate, CopyMessageFromTempDataToViewData]
public   abstract   class  ShopScaffoldController < T >  : OrderableScaffoldController < T > , IProvidesBaseService  where  T :  class , IOrderable,  new ()
{
    
private  IBaseControllerService baseControllerService;

    
///   <summary>
    
///  Supplies services and configuration to all controllers
    
///   </summary>
     public  IBaseControllerService BaseControllerService
    {
        
get  {  return  baseControllerService; }
        
set
        {
            baseControllerService 
=  value;
            ViewData[
" Title " =   " {0}{1} " .With(
                baseControllerService.ShopName,
                GetControllerName());
        }
    }

    
public   virtual   string  GetControllerName()
    {
        
return   "  - {0} " .With(GetType().Name.Replace( " Controller " "" ));
    }
}

   

     而ShopScaffoldController这个抽象类有三个子类,如下图:
  
    


      因为这三个Controller的功能需求相似,而相应的Action实现也在基类“ScaffoldController”
中实现,所以相应的类代码基本上就没有什么了。只不过在这几个子类中都被绑定了UnitOfWork过滤
器(UnitOfWorkFilter),其代码如下Suteki.Common/Filters/UnitOfWorkAttribute.cs

public   class  UnitOfWorkAttribute : FilterUsingAttribute
{
 
public  UnitOfWorkAttribute() :  base ( typeof  (UnitOfWorkFilter))
 { }
}

public   class  UnitOfWorkFilter : IActionFilter
{
 
private   readonly  IDataContextProvider provider;

 
public  UnitOfWorkFilter(IDataContextProvider provider)
 {
  
this .provider  =  provider;
 }

 
public   void  OnActionExecuting(ActionExecutingContext filterContext)
 {}

 
public   void  OnActionExecuted(ActionExecutedContext filterContext)
 {
  var context 
=  provider.DataContext;

  
if  (filterContext.Controller.ViewData.ModelState.IsValid)
  {
   context.SubmitChanges();
  }
 }
}

    
      其核心功能就是在对用户提交的数据进行有效验证后调用DataContext的SubmitChanges()方法
(注:该逻辑被放在了OnActionExecuted方法中实现)来保存修改,这种做法在以往的MVC示例子没有
看到过,呵呵,不过这种做法还有待研究。
      好了,今天的内容就先到这里了,在下一篇中,将来讨论一下该项目中对MVC框架中Filter的用
法。

      原文链接: http://www.cnblogs.com/daizhj/archive/2009/05/12/1451955.html

      作者: daizhj,代震军,LaoD

      Tags: mvc

      网址: http://daizhj.cnblogs.com/


  
   
   
   
   
   
   

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
完整版:https://download.csdn.net/download/qq_27595745/89522468 【课程大纲】 1-1 什么是java 1-2 认识java语言 1-3 java平台的体系结构 1-4 java SE环境安装和配置 2-1 java程序简介 2-2 计算机中的程序 2-3 java程序 2-4 java类库组织结构和文档 2-5 java虚拟机简介 2-6 java的垃圾回收器 2-7 java上机练习 3-1 java语言基础入门 3-2 数据的分类 3-3 标识符、关键字和常量 3-4 运算符 3-5 表达式 3-6 顺序结构和选择结构 3-7 循环语句 3-8 跳转语句 3-9 MyEclipse工具介绍 3-10 java基础知识章节练习 4-1 一维数组 4-2 数组应用 4-3 多维数组 4-4 排序算法 4-5 增强for循环 4-6 数组和排序算法章节练习 5-0 抽象和封装 5-1 面向过程的设计思想 5-2 面向对象的设计思想 5-3 抽象 5-4 封装 5-5 属性 5-6 方法的定义 5-7 this关键字 5-8 javaBean 5-9 包 package 5-10 抽象和封装章节练习 6-0 继承和多态 6-1 继承 6-2 object类 6-3 多态 6-4 访问修饰符 6-5 static修饰符 6-6 final修饰符 6-7 abstract修饰符 6-8 接口 6-9 继承和多态 章节练习 7-1 面向对象的分析与设计简介 7-2 对象模型建立 7-3 类之间的关系 7-4 软件的可维护与复用设计原则 7-5 面向对象的设计与分析 章节练习 8-1 内部类与包装器 8-2 对象包装器 8-3 装箱和拆箱 8-4 练习题 9-1 常用类介绍 9-2 StringBuffer和String Builder类 9-3 Rintime类的使用 9-4 日期类简介 9-5 java程序国际化的实现 9-6 Random类和Math类 9-7 枚举 9-8 练习题 10-1 java异常处理 10-2 认识异常 10-3 使用try和catch捕获异常 10-4 使用throw和throws引发异常 10-5 finally关键字 10-6 getMessage和printStackTrace方法 10-7 异常分类 10-8 自定义异常类 10-9 练习题 11-1 Java集合框架和泛型机制 11-2 Collection接口 11-3 Set接口实现类 11-4 List接口实现类 11-5 Map接口 11-6 Collections类 11-7 泛型概述 11-8 练习题 12-1 多线程 12-2 线程的生命周期 12-3 线程的调度和优先级 12-4 线程的同步 12-5 集合类的同步问题 12-6 用Timer类调度任务 12-7 练习题 13-1 Java IO 13-2 Java IO原理 13-3 流类的结构 13-4 文件流 13-5 缓冲流 13-6 转换流 13-7 数据流 13-8 打印流 13-9 对象流 13-10 随机存取文件流 13-11 zip文件流 13-12 练习题 14-1 图形用户界面设计 14-2 事件处理机制 14-3 AWT常用组件 14-4 swing简介 14-5 可视化开发swing组件 14-6 声音的播放和处理 14-7 2D图形的绘制 14-8 练习题 15-1 反射 15-2 使用Java反射机制 15-3 反射与动态代理 15-4 练习题 16-1 Java标注 16-2 JDK内置的基本标注类型 16-3 自定义标注类型 16-4 对标注进行标注 16-5 利用反射获取标注信息 16-6 练习题 17-1 顶目实战1-单机版五子棋游戏 17-2 总体设计 17-3 代码实现 17-4 程序的运行与发布 17-5 手动生成可执行JAR文件 17-6 练习题 18-1 Java数据库编程 18-2 JDBC类和接口 18-3 JDBC操作SQL 18-4 JDBC基本示例 18-5 JDBC应用示例 18-6 练习题 19-1 。。。
完整版:https://download.csdn.net/download/qq_27595745/89522468 【课程大纲】 1-1 什么是java 1-2 认识java语言 1-3 java平台的体系结构 1-4 java SE环境安装和配置 2-1 java程序简介 2-2 计算机中的程序 2-3 java程序 2-4 java类库组织结构和文档 2-5 java虚拟机简介 2-6 java的垃圾回收器 2-7 java上机练习 3-1 java语言基础入门 3-2 数据的分类 3-3 标识符、关键字和常量 3-4 运算符 3-5 表达式 3-6 顺序结构和选择结构 3-7 循环语句 3-8 跳转语句 3-9 MyEclipse工具介绍 3-10 java基础知识章节练习 4-1 一维数组 4-2 数组应用 4-3 多维数组 4-4 排序算法 4-5 增强for循环 4-6 数组和排序算法章节练习 5-0 抽象和封装 5-1 面向过程的设计思想 5-2 面向对象的设计思想 5-3 抽象 5-4 封装 5-5 属性 5-6 方法的定义 5-7 this关键字 5-8 javaBean 5-9 包 package 5-10 抽象和封装章节练习 6-0 继承和多态 6-1 继承 6-2 object类 6-3 多态 6-4 访问修饰符 6-5 static修饰符 6-6 final修饰符 6-7 abstract修饰符 6-8 接口 6-9 继承和多态 章节练习 7-1 面向对象的分析与设计简介 7-2 对象模型建立 7-3 类之间的关系 7-4 软件的可维护与复用设计原则 7-5 面向对象的设计与分析 章节练习 8-1 内部类与包装器 8-2 对象包装器 8-3 装箱和拆箱 8-4 练习题 9-1 常用类介绍 9-2 StringBuffer和String Builder类 9-3 Rintime类的使用 9-4 日期类简介 9-5 java程序国际化的实现 9-6 Random类和Math类 9-7 枚举 9-8 练习题 10-1 java异常处理 10-2 认识异常 10-3 使用try和catch捕获异常 10-4 使用throw和throws引发异常 10-5 finally关键字 10-6 getMessage和printStackTrace方法 10-7 异常分类 10-8 自定义异常类 10-9 练习题 11-1 Java集合框架和泛型机制 11-2 Collection接口 11-3 Set接口实现类 11-4 List接口实现类 11-5 Map接口 11-6 Collections类 11-7 泛型概述 11-8 练习题 12-1 多线程 12-2 线程的生命周期 12-3 线程的调度和优先级 12-4 线程的同步 12-5 集合类的同步问题 12-6 用Timer类调度任务 12-7 练习题 13-1 Java IO 13-2 Java IO原理 13-3 流类的结构 13-4 文件流 13-5 缓冲流 13-6 转换流 13-7 数据流 13-8 打印流 13-9 对象流 13-10 随机存取文件流 13-11 zip文件流 13-12 练习题 14-1 图形用户界面设计 14-2 事件处理机制 14-3 AWT常用组件 14-4 swing简介 14-5 可视化开发swing组件 14-6 声音的播放和处理 14-7 2D图形的绘制 14-8 练习题 15-1 反射 15-2 使用Java反射机制 15-3 反射与动态代理 15-4 练习题 16-1 Java标注 16-2 JDK内置的基本标注类型 16-3 自定义标注类型 16-4 对标注进行标注 16-5 利用反射获取标注信息 16-6 练习题 17-1 顶目实战1-单机版五子棋游戏 17-2 总体设计 17-3 代码实现 17-4 程序的运行与发布 17-5 手动生成可执行JAR文件 17-6 练习题 18-1 Java数据库编程 18-2 JDBC类和接口 18-3 JDBC操作SQL 18-4 JDBC基本示例 18-5 JDBC应用示例 18-6 练习题 19-1 。。。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值