人无信不立/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 永春 阅读(2579) 评论(10)  编辑 收藏 网摘 所属分类: 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会为你定向到" target="_new">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会为你定向到" target="_new">http://localhost:xxx/a.rails时MonoRail会为你定向到</a>" 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)

  回复  引用    
#9楼2009-04-21 09:56 | springsky[未注册用户]
学习分享中····
顺便问下 DefaultUrlTokenizer 在哪里啊?




发表评论

昵称: [登录] [注册]

主页:

邮箱:(仅博主可见)

评论内容:

  登录  注册

[使用Ctrl+Enter键快速提交评论]

0 932768




相关文章:

相关链接: