Did you checked Bistro[1]? He is doing something similar to what you are proposing.
One thing that we should avoid, imho, is the "class/interface explosion" thing. Take fubumvc for example: to create a simple hello world you need to write 4 classes. 1 - http://bistroframework.org/index.php?title=Quickstart Cheers, Henry Conceição On Mon, Mar 22, 2010 at 3:41 AM, John Simons <[email protected]> wrote: >>where does filters come in? > The same way as I resolve Handlers, eg: > windsorContainer.ResolveAll<IRunBeforeAllHandlersFor<TWebCall>>(new { > EngineContext = engineContext, ControllerContext = context}); > windsorContainer.ResolveAll<IRunAfterAllHandlersFor<TWebCall>>(new { > EngineContext = engineContext, ControllerContext = context}); > We can even have validation done this way, eg: > windsorContainer.ResolveAll<IHandleValidationFor<TWebCall>>); > >>how do you bind incoming parameters? > The derived classes from WebCall are populated with the incoming params. > Eg. > public class ProductViewWebCall : WebCall{ > public string ProductId { get; get; } > } > or > public class UserCreateWebCall : WebCall{ > public string Name { get; get; } > public string Password { get; get; } > } > >>how do you enforce ordering > You don't need because if you do then you are mixing "concerns" > That said, yes I do agree that sometimes you may want to run a handler > first, specially if we have an authorisation handler. > I'm thinking about implementing the ordering the same way NServiceBus does > it (see http://www.nservicebus.com/Documentation.aspx): > public void SpecifyOrder(Order order) > { > order.Specify(First<H1>.Then<H2>().AndThen<H3>().AndThen<H4>() > //etc); > } > > > Please remember this is just a hobby at the moment and I know that there is > still a lot to think about, also if I go down this path and get it working, > I would create a new project and not call it MR because this is a huge > change for Monorail users, that said this would definitely give us the edge > over the difference between the MS implementation of MVC and our own :) > > > Cheers > John > > ________________________________ > From: Ken Egozi <[email protected]> > To: [email protected] > Sent: Mon, 22 March, 2010 5:10:51 PM > Subject: Re: MonoRail roadmap/todos > > 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]. >> 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. > > > > -- > 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. > -- 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.
