Routing refactored

6 views
Skip to first unread message

Hamilton Verissimo

unread,
Dec 30, 2007, 12:56:34 PM12/30/07
to castle-pro...@googlegroups.com
I've changed the routing ex to:

- Support only PatternRoute rule
- Not be tied to Controller/actions
- Some great performance improvements on regexp usage

To do
- Implement ForDomain/ForSubdomain methods : the idea is to attach
routing rules per domain/subdomain if required (I need this)
- Named routes
- routing match to create urls
- Implement locking as routes might change during app's lifetime

The syntax has changed to

Simplest case:

RoutingModuleEx.Engine.Add(
new PatternRoute("/<area>/<controller>/[action]/[id]"));
RoutingModuleEx.Engine.Add(
new PatternRoute("/<controller>/[action]/[id]"));

File extensions are also supported


RoutingModuleEx.Engine.Add(
new PatternRoute("/<area>/<controller>.castle/[action]/[id]"));
RoutingModuleEx.Engine.Add(
new PatternRoute("/<controller>.castle/[action]/[id]"));


With defaults

RoutingModuleEx.Engine.Add(
new PatternRoute("/<area>/<controller>/[action]/[id]").
DefaultFor("action").Is("index"));

With restrictions:

RoutingModuleEx.Engine.Add(
new PatternRoute("/<area>/<controller>/[action]/[id]").
DefaultFor("action").Is("index").
Restrict("action").AnyOf("index", "list").
Restrict("id").ValidInteger);

--
Cheers,
hamilton verissimo
ham...@castlestronghold.com
http://www.castlestronghold.com/

chriso

unread,
Dec 31, 2007, 5:55:48 PM12/31/07
to Castle Project Development List
I noticed a limitation when I played with the first version of the
routing code:
/<area>/<controller>/<action>.<format>
Wouldn't work because it assumed that / was always the separator
between the patterns. I never got around to fixing it though, so if
you are making some changes in there it might be something to
consider.

On Dec 30, 11:56 am, "Hamilton Verissimo"
> hamm...@castlestronghold.comhttp://www.castlestronghold.com/

Hamilton Verissimo

unread,
Dec 31, 2007, 6:06:57 PM12/31/07
to castle-pro...@googlegroups.com
Interesting request. thx

Adam Tybor

unread,
Dec 31, 2007, 7:02:45 PM12/31/07
to castle-pro...@googlegroups.com
Very cool!

How can we handle nested routes like /customers/1/orders/5/edit?

RoutingModuleEx.Engine.Add(
       new PatternRoute("/<parentController>/<parentId>/<control
ler>/[id]/<action>").

       DefaultFor("action").Is("index").
       Restrict("action").AnyOf("index", "edit", "create", "delete").
       Restrict("id").ValidInteger.Or.Null
       Restrict("parentId").ValidInteger.
       Restrict("parentController").Is("customers")

I wish there was an easier way?

Dru Sellers

unread,
Dec 31, 2007, 7:35:12 PM12/31/07
to castle-pro...@googlegroups.com
Do we really need the restricts?

Restrict("action").AnyOf("index", "edit", "create", "delete")

What is that getting us?

-d

--
cheers,
-d

adam....@gmail.com

unread,
Dec 31, 2007, 7:49:07 PM12/31/07
to castle-pro...@googlegroups.com
restricts for action? probably not. i think it was more an example of
how you can use the api to put restrictions on parameters.

Hamilton Verissimo

unread,
Dec 31, 2007, 8:14:35 PM12/31/07
to castle-pro...@googlegroups.com
Yes, we need. We are basically narrowing the options for a rule. If
nothing matches, the next rule, which should be more generic, will
match.

If you dont use restrictions it gets more difficult, if not
impossible, to deal with rules that might be ambiguous.

On 12/31/07, Dru Sellers <d...@drusellers.com> wrote:
>

Hamilton Verissimo

unread,
Dec 31, 2007, 8:20:43 PM12/31/07
to castle-pro...@googlegroups.com
Your rule is invalid. You have an optional node before a required one.
That leads to a crazy number of possibilities in matching, so I rather
say it's plain invalid.

About your request... maybe:

RoutingModuleEx.Engine.Add(
new PatternRoute("/customers/<parentId>/orders/<id>/[action]").


DefaultFor("action").Is("index").

DefaultFor("controller").Is<OrderController>().


Restrict("action").AnyOf("index", "edit", "create", "delete").
Restrict("id").ValidInteger.

Restrict("parentId").ValidInteger));

Ok, not much better is it? I'm afraid a way to reuse base rules to
create compound ones might lead us to a very complex recursive
matching algorithm. As long as I dont have to write one, I'm fine with
it :-)

Felix Gartsman

unread,
Jan 16, 2008, 12:19:53 PM1/16/08
to Castle Project Development List
Can we change the extension to something else?
RoutingModuleEx.CreateMrPath has "castle" as literal.

On Dec 30 2007, 7:56 pm, "Hamilton Verissimo"
<hamm...@castlestronghold.com> wrote:
> I've changed the routing ex to:
>
> File extensions are also supported
>
> RoutingModuleEx.Engine.Add(
> newPatternRoute("/<area>/<controller>.castle/[action]/[id]"));
> RoutingModuleEx.Engine.Add(
> newPatternRoute("/<controller>.castle/[action]/[id]"));

Hamilton Verissimo

unread,
Jan 16, 2008, 12:25:49 PM1/16/08
to castle-pro...@googlegroups.com
Couldnt figure out a optimal way to do that

Felix Gartsman

unread,
Jan 16, 2008, 12:43:55 PM1/16/08
to Castle Project Development List
A hack could be a fake route default match for "useExtension".

On Jan 16, 7:25 pm, "Hamilton Verissimo"
<hamm...@castlestronghold.com> wrote:
> Couldnt figure out a optimal way to do that
>
> On 1/16/08, Felix Gartsman <garts...@gmail.com> wrote:
>
>
>
>
>
> > Can we change the extension to something else?
> > RoutingModuleEx.CreateMrPath has "castle" as literal.
>
> > On Dec 30 2007, 7:56 pm, "Hamilton Verissimo"
> > <hamm...@castlestronghold.com> wrote:
> > > I've changed the routing ex to:
>
> > > File extensions are also supported
>
> > > RoutingModuleEx.Engine.Add(
> > > newPatternRoute("/<area>/<controller>.castle/[action]/[id]"));
> > > RoutingModuleEx.Engine.Add(
> > > newPatternRoute("/<controller>.castle/[action]/[id]"));
>
> > > Cheers,
> > > hamilton verissimo
> > > hamm...@castlestronghold.comhttp://www.castlestronghold.com/
>
> --
> Cheers,
> hamilton verissimo
> hamm...@castlestronghold.comhttp://www.castlestronghold.com/

Felix Gartsman

unread,
Jan 16, 2008, 1:51:04 PM1/16/08
to Castle Project Development List
DefaultUrlBuilder.CreateUrlPartsBuilder expects routing parameters in
a dictionary entry called "params". This prevents passing anonymous
types because a key (property) cannot be a reserved word. I suggest
changing it to "routeParams" or similar.

On Dec 30 2007, 7:56 pm, "Hamilton Verissimo"
<hamm...@castlestronghold.com> wrote:
> I've changed the routing ex to:

Hamilton Verissimo

unread,
Jan 16, 2008, 2:09:25 PM1/16/08
to castle-pro...@googlegroups.com
That has bitten me as well. I'm going to change

On 1/16/08, Felix Gartsman <gart...@gmail.com> wrote:
>

Gauthier Segay

unread,
Jan 16, 2008, 6:58:35 PM1/16/08
to Castle Project Development List
Hello,

I have few points to discuss on this thread, so pick those you want to
discuss about :)

.castle extension in literal in the source:
that's not a visible issue (url wise, or even for the code client), I
successfully used the routing module with my custom extensions by
mapping .castle as well in iis and the web.config
a way to remove the literal from the source could be to lookup the
extension for the first httphandler declared and default to
the .castle literal if nothing is found (ie: in unit tests, web.config
doesn't exists)

supporting . in pattern nodes:
I try to update the patch on the MR-394 (WithDot restriction) when
jira get-up,
that's something I need to handle in my projects, anyone else is
interested in this being supported? we can follow up to the thread in
users group: http://groups.google.com/group/castle-project-users/browse_frm/thread/d654e983135d90d1

use (wrong?) of property getters in the public interface of
restriction/route builder:
I suppose the design came from an initial sketch: "code should look
like this", but I think it lead to inconsistencies:
having RestrictionConfigurer.ValidInteger property with side effect is
intriguing and restricting, refactoring will also allow overloads
ValidInteger().Between().And() or ValidInteger(int inclusiveMin, int
inclusiveMax)

anyway, the current end result is that MonoRail now have a nice and
easy to use way to declare pattern routes that surely match what is
coming with ms mvc (mvc for web should be called mcv) and the domain/
subdomain stuff is surely a good addie too, thanks for all of that.

Gauthier Segay

Jan Limpens

unread,
Jan 29, 2008, 5:23:15 PM1/29/08
to Castle Project Development List
What is the difference between <> and [] words?

Lee Henson

unread,
Jan 29, 2008, 5:26:01 PM1/29/08
to Castle Project Development List
<Required> [Optional]

Jan Limpens

unread,
Jan 30, 2008, 2:52:51 PM1/30/08
to Castle Project Development List
It seems (and if I am correct Hamilton mentions this as well) that
named patterns are not yet implemented.
Is there any other way you could tell your app, which pattern to
choose?

Let's say there are a few quite similar routes

new PatternRoute("ThemeByName", "/themes/[Name]")
.DefaultForController().Is<ThemesController>()
.DefaultForAction().Is("FindDetailByName");

new PatternRoute("GroupByName", "/groups/[Name]")
.DefaultForController().Is<ProductGroupsController>()
.DefaultForAction().Is("FindProductGroupByName");

new PatternRoute("ProductByName", "/products/[Name]")
.DefaultForController().Is<ProductsController>()
.DefaultForAction().Is("FindProductByName");

then, on the view, assuming that both a ProductGroup and a Theme have
a Name property

${Url.Link(group.Name, {'named':'GroupByName', 'params':group})}
${Url.Link(theme.Name, {'named':'ThemeByName', 'params':theme})}

both render as "Theme", because that is what comes first.

Any ideas?

Adam Tybor

unread,
Jan 30, 2008, 4:27:38 PM1/30/08
to Castle Project Development List
There was a change couple weeks ago that makes Defaults act as
restrictions if you pass in a parameter for them. So to disambiguate
the routes pass in the name of the controller.

Hamilton Verissimo

unread,
Jan 30, 2008, 4:34:44 PM1/30/08
to castle-pro...@googlegroups.com
I dont know how far Chris has gone with his implementation. I'm
concerned about starting anything on this, and stepping somebody toes.
So for now I'm going to wait a little more before fixing this.

There are hacks, though

Gauthier Segay

unread,
Jan 30, 2008, 5:32:42 PM1/30/08
to Castle Project Development List
Hello all,

Does anyone would mind reviewing my proposed patch for supporting '.'
in routing pattern nodes:

http://support.castleproject.org/browse/MR-394

I'm currently relying on the proposed patch on a project that need
support for it which will go live soon and feel unsecure because there
wasn't any feedback on my request.

For the matter I'm unsure that the current implementation (without the
patch) is right about performing splits on dots on anything that is'nt
the last node of the route.

IMHO dot is not a route node separator or at least it shouldn't be
given the same importance as slash, does extension on folder name is
relevant anywhere? I assume it is for the last part of the url, but
not for the middle part.

I hope to get you valuable feedback.

Thanks

On Jan 30, 10:34 pm, "Hamilton Verissimo"
<hamm...@castlestronghold.com> wrote:
> I dont know how far Chris has gone with his implementation. I'm
> concerned about starting anything on this, and stepping somebody toes.
> So for now I'm going to wait a little more before fixing this.
>
> There are hacks, though
>
> On 1/30/08, Jan Limpens <jan.limp...@gmail.com> wrote:
>
> > It seems (and if I am correct Hamilton mentions this as well) that
> > named patterns are not yet implemented.
> > Is there any other way you could tell your app, which pattern to
> > choose?
>
> > Let's say there are a few quite similar routes
>
> > new PatternRoute("ThemeByName", "/themes/[Name]")
> > .DefaultForController().Is<ThemesController>()
> > .DefaultForAction().Is("FindDetailByName");
>
> > new PatternRoute("GroupByName", "/groups/[Name]")
> > .DefaultForController().Is<ProductGroupsController>()
> > .DefaultForAction().Is("FindProductGroupByName");
>
> > new PatternRoute("ProductByName", "/products/[Name]")
> > .DefaultForController().Is<ProductsController>()
> > .DefaultForAction().Is("FindProductByName");
>
> > then, on the view, assuming that both a ProductGroup and a Theme have
> > a Name property
>
> > ${Url.Link(group.Name, {'named':'GroupByName', 'params':group})}
> > ${Url.Link(theme.Name, {'named':'ThemeByName', 'params':theme})}
>
> > both render as "Theme", because that is what comes first.
>
> > Any ideas?
>
> --
> Cheers,
> hamilton verissimo
> hamm...@castlestronghold.comhttp://www.castlestronghold.com/

Hamilton Verissimo

unread,
Jan 30, 2008, 5:43:06 PM1/30/08
to castle-pro...@googlegroups.com
Sure, got lots of things on my plate and to make things worst I got
sick. I'll check it tonight, promise.

James Curran

unread,
Jan 30, 2008, 5:46:39 PM1/30/08
to castle-pro...@googlegroups.com
Could you clarify the usage for the new method, ie, in the ticket, you showed a routing definition which fails.  How would it be written using your patch?  And what would a similar definition using the other method (WithoutDot) match?
 
--
Truth,
   James

Gauthier Segay

unread,
Jan 30, 2008, 7:26:28 PM1/30/08
to Castle Project Development List
Thanks,

I'm aware that issues stacking-up and this one is flagged minor, I'm
not expecting this issue to be priorized in anyway but was just
seeking some feedback from the group.

I wish you get better soon :)

On Jan 30, 11:43 pm, "Hamilton Verissimo"
<hamm...@castlestronghold.com> wrote:
> Sure, got lots of things on my plate and to make things worst I got
> sick. I'll check it tonight, promise.
>
> hamm...@castlestronghold.comhttp://www.castlestronghold.com/

Gauthier Segay

unread,
Jan 30, 2008, 7:30:00 PM1/30/08
to Castle Project Development List
I just posted a comment in the issue, also the test case which is
embedded in the patch could help to disambiguate your point.

Let me know if it does.

Best regards

On Jan 30, 11:46 pm, "James Curran" <james.cur...@gmail.com> wrote:
> Could you clarify the usage for the new method, ie, in the ticket, you
> showed a routing definition which fails. How would it be written using your
> patch? And what would a similar definition using the other method
> (WithoutDot) match?
>
> --
> Truth,
> James

Gauthier Segay

unread,
Jan 31, 2008, 2:33:53 AM1/31/08
to Castle Project Development List
About Ken Egozi's last comment on the issue about the extension
stripping:

Do you mean that with extension stripped, a route like that

/<controller>/<id>/<action>

should match both

/controllername/id.with.dot/actioname.castle
and
/controllername/id.with.dot/actioname

do you think that extension stripping optionally need to apply on
every node (setting it up on each node like current restrictions) or
only the last one (thus by default and set at the routing engine level
rather than at the route level)?

Thanks

Ken Egozi

unread,
Jan 31, 2008, 2:37:49 AM1/31/08
to castle-pro...@googlegroups.com
/<controller>/<id>/<action>
would match either
controllername/id.with.dot/actioname.castle
or
/controllername/id.with.dot/actioname

depending on engine level setting.

since on a specific deployment (an application on an IIS) you'd either have star-mapping or not, so your site would either use .castle or not. doesn't make sense to support both on the same site, and it makes things much more easier and simpler
--
Ken Egozi.
http://www.kenegozi.com/blog
http://www.musicglue.com
http://www.mamaherb.com
http://www.gotfriends.co.il

Peter Morris

unread,
Jan 31, 2008, 4:19:13 AM1/31/08
to castle-pro...@googlegroups.com
NVelocity is the default view engine and has many more examples than Brail.
I have read though that Brail is more powerful, allowing OOP etc if I should
decide I need it.

Is there a strong general consensus to use one over the other? If so which
one and why?


Thanks

Pete

Ken Egozi

unread,
Jan 31, 2008, 4:29:03 AM1/31/08
to castle-pro...@googlegroups.com
Please refer to the following link which might help you decide:

http://www.castleproject.org/MonoRail/documentation/trunk/viewengines/comparisson.html


Markus Zywitza

unread,
Jan 31, 2008, 4:34:52 AM1/31/08
to castle-pro...@googlegroups.com
I used both in my last projects. Both have their weaknesses.
NVelocity has problems with embedded logic (choose as pro/con due to
your liking) and dictionary and array access (must use get_item).
With Brail it is harder to find syntax errors. Also there are an awful
lot of brace/parenthesis/brackets to take care of, which calls for an
editor with matching support (this means, not VS2005 in HTML mode...).
What I like very much with brail, is that you can abbreviate helper
call (${Form.XXX} instead of $FormHelper.XXX). That saves a lot of
typing with typical pages.

BTW: AspView is promising too, though I didn't use it so far.

-Markus

Ken Egozi

unread,
Jan 31, 2008, 4:46:59 AM1/31/08
to castle-pro...@googlegroups.com
for me, AspView works best, because:
a. it works really well in VS + Resharper environment (full intellisense support)
also let's be enjoy intellisense on CodeGenerator powered sitemap, and the StaticSiteMap.

b. I like the idea of deploying a simple CompiledViews.dll to production, leaving the Views folder out altogether
   I know it's achievable with other engines using embedded resources, but I like the nice separation - no need to recmopile all site when I do a quick notepad change to a template - just run vcompile and get the new Compiledviews.dll

c. I believe that of all three, AspView has now the most easier to extend codebase, so I can get many bugfixes and features added by many people (thx Lee, Gauthier, James, Felix and many others)

Ben Lovell

unread,
Jan 31, 2008, 9:00:39 AM1/31/08
to castle-pro...@googlegroups.com
You can do that with NV too.

Colin Ramsay

unread,
Jan 31, 2008, 9:12:16 AM1/31/08
to castle-pro...@googlegroups.com
Isn't it independent of the view engine, as it's an overload of the Helper attribute which you put on your controller class?

Ken Egozi

unread,
Jan 31, 2008, 9:17:02 AM1/31/08
to castle-pro...@googlegroups.com
i guess colin's right.

Victor Kornov

unread,
Jan 31, 2008, 10:44:44 AM1/31/08
to castle-pro...@googlegroups.com
Ken, seems like you forgot to mention weaknesses of AspView, if there
are any, of course :)

I have not tried it yet, but a concern for me is that it's inherently
less flexible, no?
I'm judging here by my experience with regular WebForms in that matter.
I was kind of annoyed to manually declare all the properties i may
need in the template.

Ken Egozi

unread,
Jan 31, 2008, 10:51:49 AM1/31/08
to castle-pro...@googlegroups.com
It's not a competition of which's better.

Anyway, personally I find it more productive to use AspView on my real-life projects, otherwise I wouldn't have used that.

Im not declaring any properties on AspView as I'm using the dictionary adapter integration.
since anyway I have an interface per-view, i need no extra coding, and still gets intellisense etc.

the main down-side is that AspView is in contrib and not in the main castle bundle, so at times it might be a bit slow to be updated to the trunk, but not im much, as for my day-to-day work I use both trunks, and I update regularly.

Also, without resharper, the experience is somewhat less perfect, however that's true for VS as a whole ...

Victor Kornov

unread,
Jan 31, 2008, 10:59:42 AM1/31/08
to castle-pro...@googlegroups.com
One more thing, does AspView work in Medium trust?
Brail isn't and it limits choices for shared hosting.

matt r

unread,
Jan 31, 2008, 12:15:47 PM1/31/08
to Castle Project Development List
I'm curious about the "new" plans for the routingmoduleex -- when you
mention that it will support "named" routes, does that mean like the
previous named routes, nvelocity-style: Url.For("%
{named='thename'}") ? I really miss that functionality and have gone
back to rolling my own routing engine. I'd be glad to submit some
patches to bring that back to trunk, but I'd hate to overlap if others
are already doing the work or intending something different...

Hamilton Verissimo

unread,
Jan 31, 2008, 12:18:58 PM1/31/08
to castle-pro...@googlegroups.com
On 1/31/08, matt r <robinso...@gmail.com> wrote:
> I'm curious about the "new" plans for the routingmoduleex -- when you
> mention that it will support "named" routes, does that mean like the
> previous named routes, nvelocity-style: Url.For("%
> {named='thename'}") ?

Yep.

Hamilton Verissimo

unread,
Jan 31, 2008, 12:22:22 PM1/31/08
to castle-pro...@googlegroups.com
That's arbitrary. As an user I want to set where the extension is.

/home.c/edit/1 (should work)

Gildas

unread,
Feb 4, 2008, 5:29:51 AM2/4/08
to Castle Project Development List
Hi,

Thanks for this guide :)

Just a little question : in your blog, you mentioned an utility class
which registered standards routes for controllers automatically.

With all the refactoring, this class doesn't work any more. I could
work a bit to get a new one myself but I was wondering whether you
already have one that you could share ?

Thanks !

Gildas

On 30 déc 2007, 18:56, "Hamilton Verissimo"
<hamm...@castlestronghold.com> wrote:
> I've changed the routing ex to:
>
> - Support only PatternRoute rule
> - Not be tied to Controller/actions
> - Some great performance improvements on regexp usage
>
> To do
> - Implement ForDomain/ForSubdomain methods : the idea is to attach
> routing rules per domain/subdomain if required (I need this)
> - Named routes
> - routing match to create urls
> - Implement locking as routes might change during app's lifetime
>
> The syntax has changed to
>
> Simplest case:
>
> RoutingModuleEx.Engine.Add(
> new PatternRoute("/<area>/<controller>/[action]/[id]"));
> RoutingModuleEx.Engine.Add(
> new PatternRoute("/<controller>/[action]/[id]"));
>
> File extensions are also supported
>
> RoutingModuleEx.Engine.Add(
> new PatternRoute("/<area>/<controller>.castle/[action]/[id]"));
> RoutingModuleEx.Engine.Add(
> new PatternRoute("/<controller>.castle/[action]/[id]"));
>
> With defaults
>
> RoutingModuleEx.Engine.Add(
> new PatternRoute("/<area>/<controller>/[action]/[id]").
> DefaultFor("action").Is("index"));
>
> With restrictions:
>
> RoutingModuleEx.Engine.Add(
> new PatternRoute("/<area>/<controller>/[action]/[id]").
> DefaultFor("action").Is("index").
> Restrict("action").AnyOf("index", "list").
> Restrict("id").ValidInteger);

Hamilton Verissimo

unread,
Feb 4, 2008, 10:57:50 AM2/4/08
to castle-pro...@googlegroups.com
That doesnt make sense anymore. Now controller, area and action are
parameters, instead of hard coded entries.

Jan Limpens

unread,
Feb 7, 2008, 2:08:36 PM2/7/08
to Castle Project Development List
On Jan 30, 7:27 pm, Adam Tybor <adam.ty...@gmail.com> wrote:
> So to disambiguate the routes pass in the name of the controller.

new PatternRoute(name, "/themes/[Name]")
.DefaultForController().Is("ThemesController")
.DefaultForAction().Is("FindDetailByName");

does just the same thing as the generic Is<T>

Am I missing something?

Jan

Adam Tybor

unread,
Feb 7, 2008, 3:28:16 PM2/7/08
to Castle Project Development List
Yeah, your missing it. Keep the default on the rule, specify the
controller parameter when you generate the url.

Pass in the name of the controller as a parameter when you are
generating the url. This will ensure that the parameter value matches
the default value, if it doesn't it skips to the next rule. Without
explicitly using the parameter it skips the validation check so it
just returns the first rule added to the route collection.

Here is the test case that won't match because the Controller's
default is companies and we are explicitly passing in
controller=people.

I added the patch quite some time ago for this exact situation.

PatternRoute route = new PatternRoute("/people/<id>/edit").
DefaultForAction().Is("edit").
DefaultForController().Is("companies").
Restrict("id").ValidInteger;

Assert.IsNull(route.CreateUrl("localhost", "",
DictHelper.Create("controller=people", "action=edit", "id=1")));

Jan Limpens

unread,
Feb 18, 2008, 3:22:15 PM2/18/08
to Castle Project Development List
That's great and working!

As a follow up...

I will have URLs such as
http://shop.com/grupos-de-produtos/2374/a-string-stripped-of-accents-and-with-spaces-converted-to-dashes
for the sake of good search engine rankings

new PatternRoute(name, "/grupos_de_produto/<Id>/[Name]")
--> how could I hook into the link creation, so that I can transform
"Name" with some extension, Filter, whatever, before it is rendered to
the screen? I tried an extension method for this, but as it seems it
is not found.

Any suggestions?

Jan

Hamilton Verissimo

unread,
Feb 18, 2008, 7:26:57 PM2/18/08
to castle-pro...@googlegroups.com
You can either create a custom IUrlBuilder or, what I usually do,
create a custom helper to generate those special urls. The helper ends
up using UrlHelper anyway.

Jan Limpens

unread,
Feb 19, 2008, 2:46:40 PM2/19/08
to Castle Project Development List
I ended up subclassing DefaultUrlHelper and overrode the 4 BuildUrl()
methods, found there.
I registered the new service in web.config/monorails/services, thus
unknowingly using the default ctor. So the pattern engine was not
passed to it and did not do its job.

How would a config look like where I pass references to these
services?
<service id="UrlBuilder"
interface="Castle.MonoRail.Framework.Services.IUrlBuilder,
Castle.MonoRail.Framework"
type="xxx.Services.CustomUrlBuilder, xxx">
<serverUtil>?</serverUtil>
<routingEng>?</routingEng>
</service>

Or should I do this in global.asax / elsewhere / differently?

Thanks for all the help!
Jan

On Feb 18, 9:26 pm, "Hamilton Verissimo"
<hamm...@castlestronghold.com> wrote:
> You can either create a custom IUrlBuilder or, what I usually do,
> create a custom helper to generate those special urls. The helper ends
> up using UrlHelper anyway.
>
> On 2/18/08, Jan Limpens <jan.limp...@gmail.com> wrote:
>
>
>
>
>
> > That's great and working!
>
> > As a follow up...
>
> > I will have URLs such as
> >http://shop.com/grupos-de-produtos/2374/a-string-stripped-of-accents-...
> > for the sake of good search engine rankings
>
> > new PatternRoute(name, "/grupos_de_produto/<Id>/[Name]")
> > --> how could I hook into the link creation, so that I can transform
> > "Name" with some extension, Filter, whatever, before it is rendered to
> > the screen? I tried an extension method for this, but as it seems it
> > is not found.
>
> > Any suggestions?
>
> > Jan
>
> --
> Cheers,
> hamilton verissimo
> hamm...@castlestronghold.comhttp://www.castlestronghold.com/

Hamilton Verissimo

unread,
Feb 19, 2008, 3:06:11 PM2/19/08
to castle-pro...@googlegroups.com
On 2/19/08, Jan Limpens <jan.l...@gmail.com> wrote:
> How would a config look like where I pass references to these
> services?
> <service id="UrlBuilder"
> interface="Castle.MonoRail.Framework.Services.IUrlBuilder,
> Castle.MonoRail.Framework"
> type="xxx.Services.CustomUrlBuilder, xxx">
> <serverUtil>?</serverUtil>
> <routingEng>?</routingEng>
> </service>

That should work. Just remove the interface attribute, it's not
necessary for a built in service.

> Or should I do this in global.asax / elsewhere / differently?

You can do through the global.asax

Hamilton Verissimo

unread,
Mar 15, 2008, 11:08:03 AM3/15/08
to castle-pro...@googlegroups.com
Implemented now.
You refer to them using the "route" key

${Url.Link(group.Name, {'route':'GroupByName', 'params':group})}

On 1/30/08, Jan Limpens <jan.l...@gmail.com> wrote:
>
> It seems (and if I am correct Hamilton mentions this as well) that
> named patterns are not yet implemented.
> Is there any other way you could tell your app, which pattern to
> choose?
>
> Let's say there are a few quite similar routes
>
> new PatternRoute("ThemeByName", "/themes/[Name]")
> .DefaultForController().Is<ThemesController>()
> .DefaultForAction().Is("FindDetailByName");
>
> new PatternRoute("GroupByName", "/groups/[Name]")
> .DefaultForController().Is<ProductGroupsController>()
> .DefaultForAction().Is("FindProductGroupByName");
>
> new PatternRoute("ProductByName", "/products/[Name]")
> .DefaultForController().Is<ProductsController>()
> .DefaultForAction().Is("FindProductByName");
>
> then, on the view, assuming that both a ProductGroup and a Theme have
> a Name property
>
> ${Url.Link(group.Name, {'named':'GroupByName', 'params':group})}
> ${Url.Link(theme.Name, {'named':'ThemeByName', 'params':theme})}
>
> both render as "Theme", because that is what comes first.
>
> Any ideas?
>
> >
>

Reply all
Reply to author
Forward
0 new messages