the idea is cool, and I'm also facing the same composability issues
however, It does raise questions (where does filters come in? how do you
bind incoming parameters? how do you enforce ordering (say you want part B
to run after part A since you *know* that it uses a subset of data that Part
A uses, and assuming a request-level-cache is in place, you'll be able to
spare an out-of-process call that way)

I'm thinking about tackling that problem differently:
- have the request map to a controller action (using existing routing
rules), (and of running the auth-filter pre action and the "set layout
params" after action, etc.)
- in the controller, ask the container to resolve all handlers, and supply
them with the current context (as IDictionaries) and ask them to run
    -  Async controllers are one more benefit I can use here by not
re-inventing the process mechanism
- use the DictionaryAdapterFactory to access query+form parameters in the
handlers, and to set property-bag values

that way I do not need to bend monorail into anything, and I gain a
"monorail free" way of composing stuff, which can be useful if I expose some
functionality through other means (WCF, direct API calls, whatever)

On Mon, Mar 22, 2010 at 7:29 AM, John Simons <[email protected]>wrote:

> Actually WebCall and Handles are interfaces, sorry for the confusion.
> (I'm not too keen on the use of 'I' for interfaces any more, that can
> be a different discussion)
>
> public interface WebCall{}
> public interface Handles<T> where T: WebCall
> {
>   void Handle(T command);
> }
>
> Cheers
> John
>
> On Mar 22, 4:13 pm, Alex Henderson <[email protected]> wrote:
> > I'm not sure that inheritance of commands (which are bound to form
> > parameters etc.) is a good mechanism for determining handlers for a
> request,
> > this limits your ability to compose things easily (you run up against the
> > limitations of single inheritance etc.).
> >
> > Also would this be the mechanism used in place of things like filters -
> so
> > effectively a handler of the base command class "WebCall" would behave
> like
> > a BeforeAction filter (kinda).   If so, isn't ordering of handlers then
> > going to become an issue to implementing things like security,
> > authentication etc. filters.
> >
> > Interesting discussion though.
> >
> > Cheers,
> >
> >  - Alex
> >
> > On Mon, Mar 22, 2010 at 2:45 PM, John Simons <[email protected]
> >wrote:
> >
> > > Sorry I did a very simplistic example.
> > > So here is something a bit more complex, and with a few more smarts.
> >
> > > Lets say that as part of displaying /Products/List we also display on
> > > the same screen a shopping cart + product specials + recommended
> > > products, actually lets say that we do this for any url that is part
> > > of the Products "area" (/Products/*).
> >
> > > The way we do this using the Controller/Action is something like this:
> > > public void List(){
> > >  PropertyBag["cart"] = GetCart();
> > >  PropertyBag["recommended"] = Recommended();
> > >  PropertyBag["specials"] = Specials();
> > >  PropertyBag["productsList"] = GetProductsList();
> > > }
> >
> > > public void Search(){
> > >  PropertyBag["cart"] = GetCart();
> > >  PropertyBag["recommended"] = Recommended();
> > >  PropertyBag["specials"] = Specials();
> > > }
> >
> > > public void ComingSoon(){
> > >  PropertyBag["cart"] = GetCart();
> > >  PropertyBag["recommended"] = Recommended();
> > >  PropertyBag["specials"] = Specials();
> > >  PropertyBag["comingSoon"] = ComingSoon();
> > > }
> >
> > > And yes I know you can do a bit of refactoring here or use Filters,
> > > but the point is that an action method has a lot of responsibilities
> > > with this model.
> > > Also, remember that your controllers tend to not just have one single
> > > action method but many (this can make the Controllers quite large
> > > classes!).
> >
> > > The way I would do this using Handles is (Note: I'm using inheritance
> > > to work out what handles to execute):
> >
> > >       public class ProductsListWebCall : ProductsWebCall{
> >
> > >       }
> >
> > >       public class ProductsWebCall : WebCall {
> >
> > >       }
> >
> > >        public class ProductsListHandler :
> > > Handles<ProductsListWebCall>
> > >        {
> > >                public IEngineContext EngineContext { get; set; }
> > >                public IControllerContext ControllerContext { get;
> > > set; }
> >
> > >                public void Handle(ProductsListWebCall webCall)
> > >                {
> > >                         ControllerContext.PropertyBag["productsList"]
> > > = GetProductsList();
> > >                }
> > >        }
> >
> > >        public class ProductsSpecialsHandler :
> > > Handles<ProductsWebCall>
> > >         {
> > >                public IEngineContext EngineContext { get; set; }
> > >                public IControllerContext ControllerContext { get;
> > > set; }
> >
> > >                 public void Handle(ProductsWebCall webCall)
> > >                {
> > >                        ControllerContext.PropertyBag["specials"] =
> > > Specials();
> > >                }
> > >        }
> >
> > >        public class ProductsRecommendedHandler :
> > > Handles<ProductsWebCall>
> > >         {
> > >                public IEngineContext EngineContext { get; set; }
> > >                public IControllerContext ControllerContext { get;
> > > set; }
> >
> > >                 public void Handle(ProductsWebCallwebCall)
> > >                {
> > >                        ControllerContext.PropertyBag["recommended"]
> > > =Recommended();
> > >                }
> > >        }
> >
> > >        public class CartHandler : Handles<WebCall>
> > >         {
> > >                public IEngineContext EngineContext { get; set; }
> > >                public IControllerContext ControllerContext { get;
> > > set; }
> >
> > >                 public void Handle(WebCall webCall)
> > >                {
> > >                        ControllerContext.PropertyBag["cart"] =
> > > GetCart();
> > >                }
> > >        }
> >
> > > The advantage I get from using this model is hopefully total
> > > separation of concerns on my handlers.
> >
> > > I will write a post about this, with sample code that I hope will
> > > clarify a lot of the unanswered question in this thread.
> >
> > > Cheers
> > > John
> >
> > > On Mar 22, 12:16 pm, Henry Conceição <[email protected]>
> > > wrote:
> > > > For me, it appears to be just a rename. What we used to call
> > > > controller, is now called handler.  With the downside that now I'm
> > > > obligated to implement an extra class honoring the web call contract.
> > > > But perhaps I didn't get the big picture...
> >
> > > > Cheers,
> > > > Henry Conceição
> >
> > > > On Sun, Mar 21, 2010 at 9:38 PM, John Simons <
> [email protected]>
> > > wrote:
> > > > > Jan,
> > > > > My line of thought at the moment is why have a controller at all?
> > > > > See Chad Myers post on it:
> > > > >
> http://www.lostechies.com/blogs/chad_myers/archive/2009/06/18/going-c.
> > > ..
> >
> > > > > I have been hacking MR to bend it the way I want, so far I'm able
> to
> > > > > convert a request into a command (using convention over
> configuration)
> > > > > and execute that command with a simple interface.
> > > > > Eg.
> > > > > Assume a request comes in for /Products/List
> > > > > I then convert this request into ProductsListWebCall
> > > > > And then I go to my container and do the following:
> > > > >                        var webCallHandlers =
> > > > > windsorContainer.ResolveAll<Handles<TWebCall>>(new { EngineContext
> =
> > > > > engineContext,  ControllerContext = context});
> > > > >                        var webCall =
> > > Activator.CreateInstance<TWebCall>();
> >
> > > > >                        foreach (var handler in webCallHandlers)
> > > > >                        {
> > > > >                                handler.Handle(webCall);
> > > > >                        }
> > > > > And the Handle interface is:
> > > > >    public interface Handles<T> where T: WebCall
> > > > >    {
> > > > >                void Handle(T command);
> > > > >    }
> >
> > > > >        public interface WebCall
> > > > >        {
> > > > >        }
> >
> > > > > As u can see I'm also injecting the ControllerContext and
> > > > > EngineContext so that in the Handler I can do this:
> > > > >         public class ProductsListHandler :
> > > > > Handles<ProductsListWebCall>
> > > > >        {
> > > > >                public IEngineContext EngineContext { get; set; }
> > > > >                public IControllerContext ControllerContext { get;
> set;
> > > }
> >
> > > > >                public void Handle(ProductsListWebCall webCall)
> > > > >                {
> > > > >                        ControllerContext.PropertyBag["message"] =
> > > "Hello from handler";
> > > > >                }
> > > > >        }
> >
> > > > > Sorry about the formatting of the code, I'll try to write a blog
> post
> > > > > about it soon.
> >
> > > > > Cheers
> > > > > John
> >
> > > > > On Mar 16, 1:26 pm, Jan  Limpens <[email protected]> wrote:
> > > > >> From my point of view, I hope nobody minds my late involvement in
> this
> > > > >> discussion, MR's future should concentrate less in features and
> more
> > > > >> in architecture.
> >
> > > > >> After all, functionality like the one provided by
> > > > >> SmartDispatcherController should be (and mainly is) provided as an
> > > > >> aspect.
> >
> > > > >> The aforementioned functionality to render multiple controller
> actions
> > > > >> into a single view inverts the mvc paradigm and is no good idea in
> my
> > > > >> point of view. The view should not be able to make such decisions,
> > > > >> that's the controllers job.
> > > > >> The controller how it is today is a point of very low cohesion and
> one
> > > > >> of the points that should be implemented in a very different way.
> > > > >> Fortunately, with the availability of DynamicActions, the
> controller
> > > > >> could actually become the aspect providing Action-registration
> node,
> > > > >> it ought to be, imho.
> > > > >> This would make reuse much more efficient and would allow for
> better
> > > > >> composibility. Imagine, one has (fake MEF style)
> >
> > > > >> public class MyController {
> >
> > > > >>    [Import]
> > > > >>    public void MyAction {
> > > > >>    }
> >
> > > > >> }
> >
> > > > >> [Export("MyController.MyAction")]
> > > > >> public class MyActionContent : DynamicAction{
> > > > >> //impl
> >
> > > > >> }
> >
> > > > >> [Export("MyController")]
> > > > >> public class MyActionLayout : DynamicAction{
> > > > >> //impl
> >
> > > > >> }
> >
> > > > >> this would solve composition pretty well - on the controller side.
> >
> > > > >> On the view side, I completely dig OpenRasta's codec and content
> > > > >> negotiation paradigm. It is sad, MR does not offer such a clean
> > > > >> implementation.
> >
> > > > >> Composite UI is much more difficult to envision, in my eyes,
> because,
> > > > >> contrary to WebForms, we do not have externally programmable views
> (we
> > > > >> can not say "Body.Insert(new Whatever())"). But from a separation
> of
> > > > >> concerns point of view, this is a good thing, probably. Still all
> > > > >> frameworks offering composite GUIs have this somewhere. The
> problem
> > > > >> is, that a view in a composite world cannot know of what parts it
> > > > >> consists, but probably the solution ought to be similar to the
> > > > >> controller: the view as a registration point for sub views based
> on
> > > > >> some conventions.
> >
> > > > >> <% SubViews
> > > > >>    .For(v => v.ForNode = "contentNode")
> > > > >>    .With(v => viewData.GetData(v))
> > > > >>    .OrderedBy(v => layout.ApplyOrder(v)) %>
> >
> > > > >> Composition is a big deal (I'd love to read hammett's take on
> this,
> > > > >> but both of his blogs seem abandoned...) and is something really
> > > > >> difficult to implement currently.
> >
> > > > >> Probably I should have said IMHO, much more often, so please take
> this
> > > > >> as the opinion this is.
> >
> > > > >> --Jan
> >
> > > > >> On Jan 24, 8:15 pm, Mauricio Scheffer <[email protected]
> >
> > > > >> wrote:
> >
> > > > >> > But you would still have to place these concerns somewhere in
> the
> > > > >> > layout or in the view, so it's the same as RenderAction. The
> only
> > > > >> > advantage is the possibility of processing all these sub-actions
> in
> > > > >> > parallel, but you'd lose the ability to define different
> parameters
> > > > >> > for each sub-action (i.e. they
> >
> > ...
> >
> > read more »
>
> --
> You received this message because you are subscribed to the Google Groups
> "Castle Project Development List" group.
> To post to this group, send email to [email protected]
> .
> To unsubscribe from this group, send email to
> [email protected]<castle-project-devel%[email protected]>
> .
> For more options, visit this group at
> http://groups.google.com/group/castle-project-devel?hl=en.
>
>


-- 
Ken Egozi.
http://www.kenegozi.com/blog
http://www.delver.com
http://www.musicglue.com
http://www.castleproject.org
http://www.idcc.co.il - הכנס הקהילתי הראשון למפתחי דוטנט - בואו בהמוניכם

-- 
You received this message because you are subscribed to the Google Groups 
"Castle Project Development List" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/castle-project-devel?hl=en.

Reply via email to