人无信不立/2008-04-26 22:30

MonoRail学习笔记五:定制服务实现自定义功能

在上一篇MonoRail学习笔记四:MonoRail基本流程分析 中我提到,MonoRail中可以自定义一些服务。比如可以定义自己的Url解析类,来实现http://localhost:***/index.rails 等http://localhost:***/*.rails 的效果。
具体步骤如下:
1、修改web.config文件,在monorail节中加入以下定义
    <services>
      
<service id="UrlTokenizer" type="TestSiteNVelocity.CustomUrlTokenizer, TestSiteNVelocity" />
    
</services>

2、编写自己的CustomUrlTokenizer
这里为了方便,我直接复制默认的Castle.MonoRail.Framework.Services.DefaultUrlTokenizer类,将复制好的类放入TestSiteNVelocity,改名为CustomUrlTokenizer,然后在此基础上修改。
当然,这个类中有很多方法,也就可以自定义很多功能,为了实现http://localhost:***/*.rails 的效果,我们只需要修改ExtractAreaControllerAction方法。
原方法:
        private void ExtractAreaControllerAction(string rawUrl, out string area, out string controller, out string action)
        
{
            
string[] parts = rawUrl.Split('/');

            
if (parts.Length < 2)
            
{
                
throw new UrlTokenizerException("Url smaller than 2 tokens");
            }


            action 
= parts[parts.Length - 1];

            
int fileNameIndex = action.IndexOf('.');

            
if (fileNameIndex != -1)
            
{
                action 
= action.Substring(0, fileNameIndex);
            }


            controller 
= parts[parts.Length - 2];

            area 
= string.Empty;

            
if (parts.Length - 3 == 0)
            
{
                area 
= parts[parts.Length - 3];
            }

            
else if (parts.Length - 3 > 0)
            
{
                StringBuilder areaSB 
= new StringBuilder();

                
for(int i = 0; i <= parts.Length - 3; i++)
                
{
                    
if (parts[i] != null && parts[i].Length > 0)
                    
{
                        areaSB.Append(parts[i]).Append(
'/');
                    }

                }


                
if (areaSB.Length > 0)
                
{
                    areaSB.Length 
-= 1;
                }


                area 
= areaSB.ToString();
            }

        }

修改后的方法:
        private void ExtractAreaControllerAction(string rawUrl, out string area, out string controller, out string action)
        
{
            
string[] parts = rawUrl.Split('/');

            action = parts[parts.Length - 1];

            int fileNameIndex = action.IndexOf('.');

            if (fileNameIndex != -1)
            {
                action = action.Substring(0, fileNameIndex);
            }


            if (parts.Length < 2)
            {
                controller = "servlet"; ;
                area = "";

                return;
            }


            controller 
= parts[parts.Length - 2];

            area 
= string.Empty;

            
if (parts.Length - 3 == 0)
            
{
                area 
= parts[parts.Length - 3];
            }

            
else if (parts.Length - 3 > 0)
            
{
                StringBuilder areaSB 
= new StringBuilder();

                
for(int i = 0; i <= parts.Length - 3; i++)
                
{
                    
if (parts[i] != null && parts[i].Length > 0)
                    
{
                        areaSB.Append(parts[i]).Append(
'/');
                    }

                }


                
if (areaSB.Length > 0)
                
{
                    areaSB.Length 
-= 1;
                }


                area 
= areaSB.ToString();
            }

        }
红色标示的为修改部分
其实意思很简单,就是当访问http://localhost:***/*.rails 形式的页面时,默认的controller类为ServletController类
接下来就可以按常规方式编写ServletController类和view部分

这样之后当我们访问http://localhost:***/index.rails时,调用的就是ServletCOntroller类的Index方法,当访问http://localhost:***/bag.rails 时,调用的就是ServletCOntroller类的Bag方法 ......

当然我们也同样可以定义
    [DefaultAction("Index")]
     public class ServletController : Controller
让所有未定义的http://localhost:***/*.rails访问调用ServletController的Index方法

这篇文章只是涉及了自定义服务的很小的一个点,我们还可以自定义:
ControllerFactory
ViewComponentFactory
ResourceFactory
EmailSender
EmailTemplateService
UrlBuilder
ValidatorRegistry

等很多服务,来实现特定效果
posted @ 2007-10-22 10:07 永春 阅读(2252) 评论(9)  编辑 收藏 所属分类: MonoRail

  回复  引用    
#1楼 2007-10-22 11:58 | oyeah [未注册用户]
来实现http://localhost:***/index.rails 等http://localhost:***/*.rails 的效果。

这是个什么效果啊?

  回复  引用  查看    
#2楼 [楼主]2007-10-22 12:29 | GSpring      
@oyeah
MonoRail默认是不支持一级目录的,即http://ip/*.rails,只支持http://ip/*/*.rails这种二级目录的形式
  回复  引用  查看    
#3楼 2007-10-22 20:51 | 橘子&猪      
@GSpring
MonoRail要支持一级目录其实挺简单的,只要在MonoRail的配置节下增加
<defaultUrls>
<add url="a.rails" controller="b" action="c" areas="d" />
</defaultUrls>

即可.

当你访问 http://localhost:xxx/a.rails时MonoRail会为你定向到 控制器b的c动作
  回复  引用  查看    
#4楼 [楼主]2007-10-23 08:36 | GSpring      
@橘子&amp;猪
你提到的是一种方式
不过如果有很多一级目录的话就要配置很多了

另:我主要是以这个为例说一下定制服务-_-
  回复  引用  查看    
#5楼 2007-10-23 08:51 | 猪怕壮      
--引用--------------------------------------------------
橘子&amp;猪: @GSpring
MonoRail要支持一级目录其实挺简单的,只要在MonoRail的配置节下增加
&lt;defaultUrls&gt;
&lt;add url=&quot;a.rails&quot; controller=&quot;b&quot; action=&quot;c&quot; areas=&quot;d&quot; /&gt;
&lt;/defaultUrls&gt;

即可.

当你访问 <a href="http://localhost:xxx/a.rails时MonoRail会为你定向到" target="_new">http://localhost:xxx/a.rails时MonoRail会为你定向到</a> 控制器b的c动作
--------------------------------------------------------
哎,这我还是第一次见,学习了
  回复  引用  查看    
#6楼 2007-10-23 10:33 | 橘子&猪      
@GSpring
哈哈,了解!

@猪怕壮

俺们都是猪...
  回复  引用  查看    
#7楼 2007-10-27 16:41 | 千里不辞远      
学习了
  回复  引用    
#8楼 2007-12-05 16:44 | 且歌 [未注册用户]
顶!按楼主的方法改好了。

一点小问题, if (parts.Length < 2)应该是 if (parts.Length < 3)

标题  
姓名  
主页
Email (只有博主才能看到) 
验证码 *  看不清,换一张 [登录][注册]
内容(请不要发表任何与政治相关的内容)  
  登录  使用高级评论  新用户注册  返回页首  恢复上次提交      


相关链接: