Of course, this is really just a custom binding question in general.. I just like to mention ActiveRecord because I still maintain some AR+Monorail codebases, and it's batteries included experience for basic app's is still quite compelling to beginning users.
On Mon, Mar 22, 2010 at 9:51 PM, John Simons <[email protected]>wrote: > Sorry Alex but I haven't really thought about AR, I'm a NHF + NH guy. > But once I have something working and ready to share, I'm open for > suggestions ;) > > Cheers John > > On 22/03/2010, at 18:18, Alex Henderson <[email protected]> wrote: > > So for things like Active Record data binding, fetching etc. would that be > something like? > > config.For("/Product/Update/") > .MapToCommand<ProductListCall>() > .BindWith(new ActiveRecordDataBinder { Prefix="product" }); > > On Mon, Mar 22, 2010 at 7:41 PM, John Simons <<[email protected]> > [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> >> 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]>[email protected]> >> *To:* <[email protected]> >> [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]> >> [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> >>> 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]> >>> [email protected]. >>> To unsubscribe from this group, send email to >>> <castle-project-devel%[email protected]> >>> [email protected]. >>> For more options, visit this group at >>> <http://groups.google.com/group/castle-project-devel?hl=en> >>> http://groups.google.com/group/castle-project-devel?hl=en. >>> >>> >> >> >> -- >> Ken Egozi. >> <http://www.kenegozi.com/blog>http://www.kenegozi.com/blog >> <http://www.delver.com>http://www.delver.com >> <http://www.musicglue.com>http://www.musicglue.com >> <http://www.castleproject.org>http://www.castleproject.org >> <http://www.idcc.co.il>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]> >> [email protected]. >> To unsubscribe from this group, send email to >> <castle-project-devel%[email protected]> >> [email protected]. >> For more options, visit this group at >> <http://groups.google.com/group/castle-project-devel?hl=en> >> 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]> >> [email protected]. >> To unsubscribe from this group, send email to >> <castle-project-devel%[email protected]> >> [email protected]. >> For more options, visit this group at >> <http://groups.google.com/group/castle-project-devel?hl=en> >> 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]<castle-project-devel%[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.
