SmartDispatcherAction

1 view
Skip to first unread message

Ayende Rahien

unread,
Oct 25, 2007, 3:23:33 AM10/25/07
to castle-pro...@googlegroups.com

Ken Egozi

unread,
Oct 25, 2007, 4:27:22 AM10/25/07
to castle-pro...@googlegroups.com
in short, I think there is a room for adding smartDispatch capabilities to the DynamicAction, but i don't like the "standalone action" thing.
why?

my view on that as I tried to post it as a comment on Adam's blog:
The idea is nice.
Might be useful, but on another scenarios.
Inheritance does make sense in your scenario, as both controllers share behavior and semantics.
So I'd use the inheritance thing, but a bit differently (from the top of my head, in pseudo):
class BaseController<T> ...
{
   protected virtual InternalIndex(...)..
}
class ProductsController : BaseController<Product>
{
   public void Index(...) { InternalIndex(...); }
}
etc.
>> "ProductsController and CategoriesController no longer "speak" to me"
so now, the controller "speaks" to you.

Now about DynamicActions being "second class citizens", Id say that your idea can be served as en enhancement to the DActions.

however not in the way you've introduced as it would make the whole thing dependant on routing.

MR should be simple.

when I tell a newbie that url->Area/Controller/Action, the last thing I need to tell him is "except ...".

>> "What were our controllers doing? They were really just organizing our actions"
Well - controllers don't "do".  Actions "do".

Lee Henson

unread,
Oct 25, 2007, 5:12:07 AM10/25/07
to Castle Project Development List
It's effectively "decoration" of controllers with actions, and useful
for those situations where pulling that shared logic upwards in an
inheritance chain would cause an unpleasant growth of classes. I'm
guessing you lose the ability to apply attributes to those actions
too, like DefaultAction, PrincipalPermission etc?

The SmartDispatcherAction might be easier to implement after
refactoring towards IController.

> >http://adamesterline.com/2007/10/24/ror-based-mvc-web-frameworks-frie...

Ken Egozi

unread,
Oct 25, 2007, 5:17:32 AM10/25/07
to castle-pro...@googlegroups.com
Yeah. but i see it as an evolution of DynamicAction rather than as a new thing.

So the controllers would exist, and have a new-kind-of-dynamic-action-named-index associated with an attribute,
and the url would be  /products/index,  without relying on "external" routing rule.

Ayende Rahien

unread,
Oct 25, 2007, 6:16:53 AM10/25/07
to castle-pro...@googlegroups.com
Hm, but why would I want several controllers for the same action?
It seems reasonable to me that we would have action as a first class concept

Ken Egozi

unread,
Oct 25, 2007, 6:33:09 AM10/25/07
to castle-pro...@googlegroups.com
it brakes the convention of url->action mapping.

the only thing I can think of is to use is:

site.com/area/controller/action.rails  =  action() in Controller within an area
site.com/controller/action.rails  =  action() in Controller
site.com/action.rail = some first class Action.

but what if you want to group actions into an area?

youre trying to introduce something does not fit in the paradigm. it would rely on routing, so it'd make the simple things complicated.

if this action is supposed to work in conjunction with a controller, then set it up as a DAction in that controller.
if it has no other context, then create a "CommonController" and throw that action in.

Lee Henson

unread,
Oct 25, 2007, 6:40:30 AM10/25/07
to Castle Project Development List
I think Adam is making the point that this might be useful for actions
which are very similar, and that can be generalised to a sufficient
extent. You wouldn't do this for "non-generic" actions.

On Oct 25, 11:16 am, "Ayende Rahien" <aye...@ayende.com> wrote:
> Hm, but why would I want several controllers for the same action?
> It seems reasonable to me that we would have action as a first class concept
>

> On 10/25/07, Ken Egozi <egoz...@gmail.com> wrote:
>
>
>
>
>
> > Yeah. but i see it as an evolution of DynamicAction rather than as a new
> > thing.
>
> > So the controllers would exist, and have a
> > new-kind-of-dynamic-action-named-index associated with an attribute,
> > and the url would be /products/index, without relying on "external"
> > routing rule.
>

> > > > > Looks like a nice idea.- Hide quoted text -
>
> - Show quoted text -

Adam Esterline

unread,
Oct 25, 2007, 3:28:51 PM10/25/07
to Castle Project Development List
What I was suggesting is not really a new idea... Struts was doing
this 8 years ago (but in an ugly way).

Controllers with actions as methods make good demos, but don't
facilitate good code reuse. In my last project,
we tried to make use of your below suggestion.

class BaseController<T>

We had 5 actions that could be reused across several controllers.
You can only imagine the number of "template" methods
that a child controller needed to implement to facilitate reuse of
those 5 actions. To add to the problems, some of the child
controllers only needed to reuse some of the
actions. We ended up having some of the "template" methods return
default values in the base class so that not every child controller
had to override them. Talk about unclear... which template methods
go with what actions? Which one do I need to implement?
BaseController really breaks down when you
want to reuse more than one action.

We were lead down the path of BaseController<T> because that is what
the framework encourages. After we realized BaseController<T> was a
nightmare we aggressively moved
to DynamicActions. Our controllers ended up having a constructor
with a bunch of dynamic action creations. After seeing this evolve,
we thought our controllers were really not
doing anything... other than organizing our actions.

What if routing had a nice syntax/dsl?

RoutingEngine.Add("products" delegate(Foo foo)
{
foo.Add(new Route("<name>", new IndexAction(new
ProductRepository())
foo.Add(new Route("list", new ListAction(new ProductRepository())
});

Not sure this is the best code, but you get the idea. You could
structure your "Routes" such that they are grouped by "concepts/
controllers".

Hopefully this explains, a little better, my point of view.

AE

> >http://adamesterline.com/2007/10/24/ror-based-mvc-web-frameworks-frie...

Ken Egozi

unread,
Oct 26, 2007, 1:48:33 AM10/26/07
to castle-pro...@googlegroups.com
On 10/25/07, Adam Esterline <ad...@esterlines.com> wrote:
After we realized BaseController<T> was a
nightmare we aggressively moved
to DynamicActions.    Our controllers ended up having a constructor
with a bunch of dynamic action creations.  

So it's not the DActions are not good, the implementation details isn't nice enough, so we might need to think how to improve that.

  After seeing this evolve,
we thought our controllers were really not
doing anything... other than organizing our actions.

That's what controllers do.  the executable code in a controller (aka public method) is an action, so all over your application, the controllers are logical groups of actions. If  you do have an "all around" action that does not belong to an existing controller, you'd create a new controller for that action.

What if routing had a nice syntax/dsl?

RoutingEngine.Add("products" delegate(Foo foo)
{
    foo.Add(new Route("<name>", new IndexAction(new
ProductRepository())
    foo.Add(new Route("list", new ListAction(new ProductRepository())
});

the RoutingEngine  is not for routing from Url to CLR.
it's for routing (or actually re-writing) an arbitrary Url  to  standard rails url.

plus - this couples the framework tightly to a specific RoutingEngine implementation, thus introducing a compulsory complication that is not supposed to be there, breaking Convention-Over-Configuration.

I'm not saying that it's bad. It might be great for your needs. but I cannot see it as part of the framework


Not sure this is the best code, but you get the idea.   You could
structure your "Routes" such that they are grouped by "concepts/
controllers".

instead of "routes" and "concepts", use "actions" and "controllers" - and it's baked in 

Hopefully this explains, a little better, my point of view.

Me too ;) 

Adam Esterline

unread,
Oct 26, 2007, 7:46:23 AM10/26/07
to Castle Project Development List
> So it's not the DActions are not good, the implementation details isn't nice
> enough, so we might need to think how to improve that.

I would agree. In MonoRail, DActions are the only way to handle the
problem
I described above. DAs need more "niceness". I am sure this could
be done now
by coding a SmartDispatcherAction that implements the IDynamicAction
interface.

I really want to stress that Controllers with public action/methods
leads developers
into making bad design decisions. I did it. You suggested it.
The framework
leads you down a bad path. Without actions being a first class
concept this will continue.

Controllers with public action/methods make great demos and simple
quick applications.
When developing non-simple applications that need to be DRY, it fails.

> the RoutingEngine is not for routing from Url to CLR.
> it's for routing (or actually re-writing) an arbitrary Url to standard
> rails url.
>
> plus - this couples the framework tightly to a specific RoutingEngine
> implementation, thus introducing a compulsory complication that is not
> supposed to be there, breaking Convention-Over-Configuration.
>
> I'm not saying that it's bad. It might be great for your needs. but I cannot
> see it as part of the framework

I don't really see it as being tightly coupled. Your actions no
nothing about
the routing engine. I can agree to disagree.

AE

On Oct 26, 12:48 am, "Ken Egozi" <egoz...@gmail.com> wrote:

Ken Egozi

unread,
Oct 26, 2007, 7:53:01 AM10/26/07
to castle-pro...@googlegroups.com
But the only way to activate the action is though a route. how else would you construct a url that will activate a "standalone" action?

anyway - if the action needs re-use then DAction is a good design choice imho.

and setup the DAction on the needed controllers (instead of setting it up in the route rule as you've suggested).
I do not see the bad design here.

Adam Esterline

unread,
Oct 26, 2007, 9:22:24 AM10/26/07
to Castle Project Development List
I agree that DAction are a good design choice. But... DActions are
not the encouraged by the framework.
That is my only point.

On Oct 26, 6:53 am, "Ken Egozi" <egoz...@gmail.com> wrote:
> But the only way to activate the action is though a route. how else would
> you construct a url that will activate a "standalone" action?
>
> anyway - if the action needs re-use then DAction is a good design choice
> imho.
>
> and setup the DAction on the needed controllers (instead of setting it up in
> the route rule as you've suggested).
> I do not see the bad design here.
>

Ken Egozi

unread,
Oct 26, 2007, 9:28:39 AM10/26/07
to castle-pro...@googlegroups.com
Ok. so what would you have liked to see changed in the DAction API in order to make'em more encouraged?


On 10/26/07, Adam Esterline < ad...@esterlines.com> wrote:

josh robb

unread,
Oct 26, 2007, 10:10:15 AM10/26/07
to castle-pro...@googlegroups.com
> Controllers with public action/methods make great demos and simple
> quick applications.
> When developing non-simple applications that need to be DRY, it fails.

Adam - I scanned your blog post - but didn't see a specific example of
this type of problem.

I'm curious about why/how you think this is causing you DRY problems.

I've used public method per controller setups on a number of projects
and not once come across this kind of problem.

Would you mind sharing an example of a type of action which shouldn't
be bound to a controller?

j.

Adam Esterline

unread,
Oct 26, 2007, 10:30:04 AM10/26/07
to Castle Project Development List
> Would you mind sharing an example of a type of action which shouldn't
> be bound to a controller?

Any action that needs to be shared across controllers. The example
in the blog post shows an example of sharing actions across
controllers using public methods. You end up with a base controller
that exposes protected template methods. This is not a good way to
reuse actions. It works "OK" for reusing one action, but totally
falls apart when trying to reuse more than one action on a controller.

Did you never try to reuse actions, across controllers, in your
projects? If so, how did you do it? This is really the problem I
am trying to expose. How are users of RoR based MVC Frameworks
reusing actions across controllers? I think the frameworks encourage
users to reuse code in a bad way (Template Method Pattern).

I wish I could show you our code, but I cannot. I will work up a
better example this weekend that will show the problem better.

josh robb

unread,
Oct 26, 2007, 10:43:22 AM10/26/07
to castle-pro...@googlegroups.com
> Did you never try to reuse actions, across controllers, in your
> projects?

No. I've never had a situation where I could (where the code wasn't
trivial). I think that the problem is that the index action example is
so trvial I don't see the problem.

If you're having to create 10 different index actions which are all
that simple - then I'm inclined to think there's a problem somewhere
else. This could be because I'm primarily thinking of public internet
web apps rather than Lob type apps. (My LOB SaaS app is WebForms :( ).

> How are users of RoR based MVC Frameworks
> reusing actions across controllers? I think the frameworks encourage
> users to reuse code in a bad way (Template Method Pattern).

This seems like a pretty unusual requirement. For scaffolding type
things (early stages) people use scaffolding. Once they've got past
that the actions usually are very specific to the controller and use
cases they're working within.

> I wish I could show you our code, but I cannot. I will work up a
> better example this weekend that will show the problem better.

Even just a different example would help - as I said above - I'm not
aware of lots of people having this kind of problem so maybe you've
struck a whole new usecase.

I for one am curious to understand this better.

j.

josh robb

unread,
Oct 26, 2007, 10:44:27 AM10/26/07
to castle-pro...@googlegroups.com
Oh - just so I'm clear - I'm all for making dynamic actions nicer and
SmartDispatcherAction sounds interesting . I'm just curious about
whats driving this.

Adam Esterline

unread,
Oct 26, 2007, 10:48:43 AM10/26/07
to Castle Project Development List
I am looking for ideas too. At present time, I am not sure "first
class actions" can be encouraged with the current frameworks. They
are all centered around controllers with public methods.

Do you have any ideas?

I still get the feeling you and I are not on the same page. I wish
we could talk face-to-face. This would be easier.

On Oct 26, 8:28 am, "Ken Egozi" <egoz...@gmail.com> wrote:
> Ok. so what would you have liked to see changed in the DAction API in order
> to make'em more encouraged?
>

Tanner Burson

unread,
Oct 26, 2007, 11:05:53 AM10/26/07
to castle-pro...@googlegroups.com
I think the problem that people are having is simply that an action is "defined" (commonly associated) as a unique process that occurs inside your application.  I too have a hard time imagining a case where I'd want to share an action between controllers.  If I found the need to run the same action in multiple controllers, I'd either re-factor that action into a new controller, and call it from the others as necessary or pull the logic from the action into the service layer.  That said though, I agree with Josh, and would love to see an example of an action needing to be re-used, that was more complicated than just a render of a template.

On 10/26/07, Adam Esterline <ad...@esterlines.com> wrote:



--
===Tanner Burson===
tanner...@gmail.com
http://www.tannerburson.com

Ayende Rahien

unread,
Oct 26, 2007, 11:22:07 AM10/26/07
to castle-pro...@googlegroups.com
I do have this need actually.
I usually push things to a base class, or a set of base classes, but it is gets painful after a while.
I will have a post about it shortly.

Ayende Rahien

unread,
Oct 26, 2007, 11:23:44 AM10/26/07
to castle-pro...@googlegroups.com
Searching.
I have several places where I need to do searching, and interact with the results in interesting ways.
It can be printing, export to excel, paging, saving results or queries.
All of the above except the initial search is shared.

Ken Egozi

unread,
Oct 26, 2007, 11:24:39 AM10/26/07
to castle-pro...@googlegroups.com
I'm sure you would.

I'd like (in your examination that you'd present at that post) to show how you can solve your problem within the current toolset, and to refer to DActions and how (maybe) extending them might fit your needs.

Adam Esterline

unread,
Oct 26, 2007, 11:48:11 AM10/26/07
to Castle Project Development List
We actually reused the searching.

Our app needed to allow the same kinds of searches across entities.
ByZip, ByCityState... The searching actions had complicated
rendering logic that we did not want to rewrite. Example:

Entity entity = repos.FindByZip(zip);
if(entity == null) {
look_for_zip_in_other_regions
if( found_in_other_regions ) RenderView("other_region_error_page");
else {
look_for_zip_in_a_parent_company_db
if( found_in_parent_compnay_db )
RenderView("parent_error_page");
else RenderView("unknow_zip")
}
}
else {
PropertyBag["Entity"] = entity;
RenderView("show_entity");
}

If you want to see the code in action check out sothebyshomes.com.
Look at the top at the "Quick Search". There are several entities
that need to support the same kinds of searches with the same kinds of
error handling in each. You can actually see some of the error
handling in practice.

http://sothebyshomes.com/nyc

Quick search by Area and give the zip code of 90210 (california).
After doing this you will see the other region error page. This
search by Area is present in Properties for Sale, Properties for Rent,
Agents, Offices.

We started by implementing these with public methods in controllers
with a base class. Each of the shared search functionality needed
several template methods to satisfy it's requirements. After just a
few search types, this becomes really ugly and painful. What made
it worse is not all entities should inherit all search types. You
can only imagine. I wish I could release the version of our base
controller before we started cleaning it up (I asked, but got no).

Does this example help?

On Oct 26, 10:23 am, "Ayende Rahien" <aye...@ayende.com> wrote:
> Searching.
> I have several places where I need to do searching, and interact with the
> results in interesting ways.
> It can be printing, export to excel, paging, saving results or queries.
> All of the above except the initial search is shared.
>

> On 10/26/07, Tanner Burson <tanner.bur...@gmail.com> wrote:
>
>
>
> > I think the problem that people are having is simply that an action is
> > "defined" (commonly associated) as a unique process that occurs inside your
> > application. I too have a hard time imagining a case where I'd want to
> > share an action between controllers. If I found the need to run the same
> > action in multiple controllers, I'd either re-factor that action into a new
> > controller, and call it from the others as necessary or pull the logic from
> > the action into the service layer. That said though, I agree with Josh, and
> > would love to see an example of an action needing to be re-used, that was
> > more complicated than just a render of a template.
>

> > tanner.bur...@gmail.com
> >http://www.tannerburson.com

Ayende Rahien

unread,
Oct 26, 2007, 2:50:16 PM10/26/07
to castle-pro...@googlegroups.com

Ayende Rahien

unread,
Oct 26, 2007, 5:11:49 PM10/26/07
to castle-pro...@googlegroups.com
Guys, are you aware of this?
http://hammett.castleproject.org/?p=73

Ken Egozi

unread,
Oct 26, 2007, 5:20:48 PM10/26/07
to castle-pro...@googlegroups.com
As I said - DActions are very good solution.

Only caveat is the lack of SmartDispatcher syntax, which makes you use Query[], manual binder, etc, and also makes testing a bit strange.

I'm going to put a bit thinking about a way to make it a bit nicer to the eye.

Ayende Rahien

unread,
Oct 26, 2007, 5:25:41 PM10/26/07
to castle-pro...@googlegroups.com
IDynamicAction I was familiar with, IDyanmicActionProvider I was not.

That is like having mixins!

We can certainly create SmartAction implementation, that would do it for you.
Then, instead of routing, you would put this logic in the dynamic action provider.

Ken Egozi

unread,
Oct 26, 2007, 5:40:53 PM10/26/07
to castle-pro...@googlegroups.com
the problem with SmartDispatcherAction is:

a.
public void Create([DataBind("what.prefix?")] WhichType instance)
{
}
would the Binder play nicely with generics?

b.
Say a controller need to 'override' one of the actions. how do we do that?
implement that excplicitly, and allow call for dynamic[ActionName].Invoke() instead of base.Create()?

Ayende Rahien

unread,
Oct 26, 2007, 5:53:36 PM10/26/07
to castle-pro...@googlegroups.com
For how this should work, I think that I have a solution:

http://www.ayende.com/Blog/archive/2007/10/26/Model-View-Action.aspx

Ayende Rahien

unread,
Oct 26, 2007, 5:54:27 PM10/26/07
to castle-pro...@googlegroups.com
For binding, I would suggest this:

public class SearchAction : SmartDispatcherAction
{
       public string Name { get; set; }

       public override void Execute()
       {

Adam Esterline

unread,
Oct 29, 2007, 12:58:48 PM10/29/07
to Castle Project Development List
Ayende's post got me thinking this weekend...

I was going to post on my blog about my thoughts, but I thought I
would run it by this discussion first and summarize on my blog.

First, Is the problem more clear now with Ayende's post and my last
post to this discussion?

In Ayende's blog post he talked about liking the "controller" because
it was easy to group CRUD operations together. I agree, to a
degree, with his use case for controllers, but I think this is a minor
use case and should not be the focus of a Web MVC Framework.
Controllers, especially on the web, have always bugged me because they
go against the OO principle; "An object should do one thing and one
thing well". This flaw really comes to light when trying to reuse
functionality across controllers.

CRUD Controllers

I am not sure I agree with using controllers for CRUD. How often are
simple CRUD only controllers used? CRUD usually ends up having some
amount of business rules. Don't those business rules need to be
used across entities? Why not have a CreateAction that is used
across products and categories? Just a thought. Not sure if it
could work that way in practice.

Ken's Challenge

> I'd like (in your examination that you'd present at that post) to show how
> you can solve your problem within the current toolset, and to refer to
> DActions and how (maybe) extending them might fit your needs.

I think my problem can be solved with a naming change. Assuming the
following interface exists (it does in MS MVC):

public interface IController {
public void Execute(IRequest request)
}

It is then up to the individual implementations of the controller
interface to implement more advanced features
(smartdispatcher, ...). If you look closely at this interface, it is
the command pattern that I need to solve the problems I described. I
would like to see the name of this interface be IAction. We could
then have different implementations of this interfaces for the other
scenarios; SmartDispatcherAction, ControllerAction, ...
(ControllerAction would be an Action that works the way the current
set of controllers work.)

The purpose of all of this is to encourage the use of Actions. The
main focus of the framework should be Actions. The controller would
not be the main concept. This sounds like a radical change, but I
think it, once the controller is an interface, it is really just a
naming change. Names make all of the difference.

None of these thoughts are new... What I described is basically
Struts. Routing was an ugly, XML mess in Struts. We now know that
XML is the wrong way to implement a DSL.

Thoughts?

> On 10/26/07, Ken Egozi <egoz...@gmail.com> wrote:
>
>
>
> > I'm sure you would.
>
> > I'd like (in your examination that you'd present at that post) to show how
> > you can solve your problem within the current toolset, and to refer to
> > DActions and how (maybe) extending them might fit your needs.
>
> > On 10/26/07, Ayende Rahien <aye...@ayende.com> wrote:
>
> > > I do have this need actually.
> > > I usually push things to a base class, or a set of base classes, but it
> > > is gets painful after a while.
> > > I will have a post about it shortly.
>

Steve Gentile

unread,
Oct 29, 2007, 1:23:22 PM10/29/07
to castle-pro...@googlegroups.com
Just to try to grasp your email:

Statement: How do actions related to controllers

You mention CRUD operations, etc...  I say next, CRUD for what?

Let's say 'Employees'

So, employees has a set of actions right?

EmployeesController is still there, but now each action with it's rules is implemented.

Action: GetCurrentEmployees
Action: AddNewEmployee
Action: UpdateEmployee

In other words, we'd keep the IController and each action would implement an IAction?

Do we have a Strategy pattern here where we inject the actions?

Employee : IController
{
    IAction CurrentEmployees;
}

just me thinking outloud

Lee Henson

unread,
Oct 29, 2007, 2:01:48 PM10/29/07
to Castle Project Development List
public interface IController
{
void SetActions(params IAction[] actions);
}

?

Steve Gentile

unread,
Oct 29, 2007, 2:23:34 PM10/29/07
to castle-pro...@googlegroups.com
that looks better  :)

Adam Esterline

unread,
Oct 29, 2007, 2:40:33 PM10/29/07
to Castle Project Development List
Your Actions would be more generic.

GetCurrentAction
CreateAction
UpdateAction

That way you could share them across entities; Employees,
Managers, ...

Adam Esterline

unread,
Oct 29, 2007, 2:42:33 PM10/29/07
to Castle Project Development List
The base IController interface should not know anything other than
Excecute. Why would it need to know about Actions or anything
else? Those details should be left to the individual
implementations.

Ayende Rahien

unread,
Oct 29, 2007, 2:57:36 PM10/29/07
to castle-pro...@googlegroups.com
You can't do that. Over generalism
The problem is that you assume that this is pure CRUD. But what happens when you are dealing with business roles as well?
Who can update an employee is different than who can update the manager's direct reports.

Ayende Rahien

unread,
Oct 29, 2007, 2:59:15 PM10/29/07
to castle-pro...@googlegroups.com
I gave the CRUD example because it was easy. But any set of related functionality deserve the same treatment.
To give you a simple example, I have a controller that is in charge of generating documents. You can search for a document by type, enter relevant data and then generate it
This all belongs to a single controller, and it is much easier than if I needed to deal with three different classes.
The cases for actions exists, but they are rarer than what you seem to thnk

On 10/29/07, Adam Esterline <ad...@esterlines.com> wrote:

Adam Esterline

unread,
Oct 29, 2007, 3:11:34 PM10/29/07
to Castle Project Development List
You may be right. I don't do much development on CRUD type
applications. Mostly readonly web sites. Readonly web sites tend
to be highly action driven (same searches across many entities as an
example).

If the interface for a controller is:

public class IController
{
public void Execute(IRequest request);
}

then, first class actions and controllers can be implemented. The
details about how individual controller/actions work are left to the
individual implementations.

On Oct 29, 1:59 pm, "Ayende Rahien" <aye...@ayende.com> wrote:
> I gave the CRUD example because it was easy. But any set of related
> functionality deserve the same treatment.
> To give you a simple example, I have a controller that is in charge of
> generating documents. You can search for a document by type, enter relevant
> data and then generate it
> This all belongs to a single controller, and it is much easier than if I
> needed to deal with three different classes.
> The cases for actions exists, but they are rarer than what you seem to thnk
>

Ken Egozi

unread,
Oct 29, 2007, 3:20:43 PM10/29/07
to castle-pro...@googlegroups.com
My problem is with the mapping.
i know how url relates to Area/Controller/Action.

I cannot see Direct call to a first-class action fit here.

And I do not want to rely on 'special' routings.  the whole thing should be Simple.

I might consider that if the specified Action is not found on the given controller, then an IAction should be invoked and be associated with the Controller.
And that's exactly DAction with better/easier syntax.

However, IController != IAction.
They serve different purposes, and it would make an over-generalized, non-simple solution.

I stick with my opinion of improving the DAction thing (auto-registering DAction to controller if said action is not on the controller, supplying with a SmartDispatcerAction impl, etc.)

Prove me wrong.

On 10/29/07, Adam Esterline <ad...@esterlines.com> wrote:

Steve Gentile

unread,
Oct 29, 2007, 3:39:36 PM10/29/07
to castle-pro...@googlegroups.com
Something more like this?

public interface IController
    {
        void Execute();
        void SetActions(IList<IAction> actions);
        //void AddAction(IAction action);
        //void RemoveAction(IAction action);
    }

IController c = IoC.Resolve<IController>("Examples.MyController");
c.Execute();

where

public class MyController : IController
    {
        private IList<IAction> actions;

        public MyController() { }
        public MyController(IList<IAction> actions) //inject
        {
            this.actions = actions;
        }
        public void SetActions(IList<IAction> setactions) //override
        {
            this.actions = setactions;
        }
...
}


<component
                id="Examples.MyController"
                service ="Examples.IController, Examples"
                type="Examples.MyController, Examples">
                <parameters>
                    <actions>
                        <array type="Examples.IAction, Examples">
                            <item>${Examples.MyAction}</item>
                            <item>${Examples.MyOtherAction}</item>
                        </array>
                    </actions>
                </parameters>
            </component>

Ayende Rahien

unread,
Oct 29, 2007, 4:14:46 PM10/29/07
to castle-pro...@googlegroups.com
Adam,
Consider the following requirements:
* Searching for customers should return only those that have products in your division
* Searching for employees should return all results
* Searching for orders should return only those that have been marked by one of the members of your team.

Those aren't really reusable

On 10/29/07, Adam Esterline <ad...@esterlines.com> wrote:

Adam Esterline

unread,
Oct 29, 2007, 4:18:10 PM10/29/07
to Castle Project Development List
Everything can be accomplished with the current framework (adding
SmartDispatcherAction would be nice). Our controllers ended up
looking like this:

public class MyController
{
public MyController()
{
DynamicActions["Index"] = new IndexAction(new
MyRepository());
DynamicActions["byZip"] = new ZipAction(new MyRepository());
...
...
}
}

No methods in the controller. This seems to be an uncommon case
(more so than I thought). When we saw this pattern emerging is
seems like the controller is not really "pulling its weight". Which
prompted my post. If no one else sees a problem with the above
code... maybe I am just being picky.

On Oct 29, 2:20 pm, "Ken Egozi" <egoz...@gmail.com> wrote:
> My problem is with the mapping.
> i know how url relates to Area/Controller/Action.
>
> I cannot see Direct call to a first-class action fit here.
>
> And I do not want to rely on 'special' routings. the whole thing should be
> Simple.
>
> I might consider that if the specified Action is not found on the given
> controller, then an IAction should be invoked and be associated with the
> Controller.
> And that's exactly DAction with better/easier syntax.
>
> However, IController != IAction.
> They serve different purposes, and it would make an over-generalized,
> non-simple solution.
>
> I stick with my opinion of improving the DAction thing (auto-registering
> DAction to controller if said action is not on the controller, supplying
> with a SmartDispatcerAction impl, etc.)
>
> Prove me wrong.
>

Ayende Rahien

unread,
Oct 29, 2007, 4:20:25 PM10/29/07
to castle-pro...@googlegroups.com
You are not picky, it is just that this use case is not a core one.
It _is_ a valid use case, and I would like to make it easier to use.
I would love to get a patch for smart actions, for instance.

On 10/29/07, Adam Esterline <ad...@esterlines.com> wrote:

Adam Esterline

unread,
Oct 29, 2007, 4:40:38 PM10/29/07
to Castle Project Development List
I agree on the surface, but I think that it depends.

Consider If they all shared the same edge rules.

* All Searches should display the detail page if only one result is
returned.
* All Searches should show a results not found page if no results are
found.

Given these rules... I might try and find a way to use DynamicActions
so that rules are not duplicated.

On Oct 29, 3:14 pm, "Ayende Rahien" <aye...@ayende.com> wrote:
> Adam,
> Consider the following requirements:
> * Searching for customers should return only those that have products in
> your division
> * Searching for employees should return all results
> * Searching for orders should return only those that have been marked by one
> of the members of your team.
>
> Those aren't really reusable
>

Ayende Rahien

unread,
Oct 29, 2007, 4:54:35 PM10/29/07
to castle-pro...@googlegroups.com
Okay, in this scenario, template controller is what I would take.
decorator actions will be very painful, I think

On 10/29/07, Adam Esterline < ad...@esterlines.com> wrote:

Ken Egozi

unread,
Oct 29, 2007, 5:56:49 PM10/29/07
to castle-pro...@googlegroups.com
Template controller would have been my approach I guess, too.

And as for Adam's example - well, the controllers are not "empty".

consider you've had a full implementation of Index() on Controller1 and Controller2.
you've just DRY-ed that method out to be IDymanicAction, leaving the "shell" in the controller.

my first sketch:

IController
{

}


class MyController
{
   Actions =

Ken Egozi

unread,
Oct 29, 2007, 6:03:08 PM10/29/07
to castle-pro...@googlegroups.com
sorry, cut out.

IController
{
  void Execute();
}

IDynamicAction
{
   void Execute()
}

IDynamicActionsAware
{
   bool HasAction(Type actionType);
   bool HasAction(string Name);
   SetActions(IEnumerable? params?)
}

MyController : IController, IDynamicActionsAware
{
    ...

Adam Esterline

unread,
Oct 29, 2007, 6:16:49 PM10/29/07
to Castle Project Development List
Interesting. I seems like I am the only one who likes DynamicActions
for "templating". It seems like an easy action to write.

public interface IUserSearchRepository
{
public IList SearchByUser(User user);
}

All your requirements seem to be centered around a User. The
employee repos would just ignore this parameter.

public class SearchAction : IDynamicAction
{
private IUserSearchRepository repos;
public SearchAction(IUserSearchRepository repos, string
onItemView)...

public void Execute()
{
User user = GetUser();
IList items = repos.SearchByUser(user);
if(items.Empty) RenderView("no_results_found");
if(items.Length == 1) RenderView(oneItemView);
else Render("list");
}
}

Then in my controllers I would create and register the dynamic action
with the correct instances passed into the constructor. I really
don't like using inheritance. It really starts to fall apart when
you need to reuse more than one behavior.

On Oct 29, 3:54 pm, "Ayende Rahien" <aye...@ayende.com> wrote:
> Okay, in this scenario, template controller is what I would take.
> decorator actions will be very painful, I think
>

patrick...@gmail.com

unread,
Oct 29, 2007, 8:05:01 PM10/29/07
to Castle Project Development List
This is a very interesting discussion. However I believe this is being
way over thinked. Most actions are very similar but I tend to find
they are always unique in some way. Therefore no matter how ideal it
may seem to concentrate identical code in one place, it is not
typically viable. Firstly, although the excellent framework castle
provides does simplify our work, that doesn't mean we should stop
there.

For example why should this...

public void Index(string code)
{
Product product = Product.FindByCode(code);
if(product == null)
{
PropertyBag["UnknownSearchTerm"] = code;
RenderView("common/unknown_quick_search");
}
PropertyBag["Product"] = product;
RenderView("display_product");
}

not be...

public void Index (string code)
{
PropertyBag ["product"] = Product.FindByCode (code);

if (PropertyBag ["product"] == null)
Redirect ("notfound");
}

Secondly I believe Hamilton rightly focuses on making Castle easy to
use and KISS strategy for Castle users. What is being discussed here
is an advanced solution that I believe should be avoided most of the
time in favour of code readability and maintainability. Why should we
even try to reuse the above? What if I need to add business rules and
specific logic later in development? Invariably it is completely
different for each object in the data model.

Whatever is decided should not affect the simplicity of what already
exists.

These are only my humble thoughts and I have to admit I have never
found a need (yet) to use dynamic actions.

P

Ken Egozi

unread,
Oct 30, 2007, 2:49:24 AM10/30/07
to castle-pro...@googlegroups.com
>>> Whatever is decided should not affect the simplicity of what already
exists.

+1+1+1+1+1
Reply all
Reply to author
Forward
0 new messages