Development Blog

 Wednesday, April 11, 2007
« CR_Searcher | Main | Adaptive Fetching Strategies in ORMs »

We were on the phone today with Scott Bellware and he asked us if we could toss together a simple MonoRail project that showed the Castle.Tools.CodeGenerator stuff in action. A few other people have been asking us to do something similar for the other things we've been discussing on our blog. So, Aaron and I sat down and pair-programmed out some source that does just that. It shows several things:

  • An Action/View map is generated using Castle.Tools.CodeGenerator, and used to do view renderings, and (if desired) action redirections and the like.
  • PropertyBag wrappers are created using the IDictionaryAdapterFactory code that Lee contributed.
  • We show how we test our controllers using the test fixture code Aaron has been posting about.
  • It has a small service layer that roughly shows how we architecture our code around here.
  • It uses Windsor integration, so you can see how that's used if you've been curious.

Please keep in mind this took us about an hour to whip up and we did not actually practice full TDD with it. Enjoy!

Source

Wednesday, April 11, 2007 6:31:07 PM (Pacific Standard Time, UTC-08:00)
Thank you for doing this. Can't wait to check out the goodies.
Thursday, April 12, 2007 10:14:25 AM (Pacific Standard Time, UTC-08:00)
This is great example. But how do I use this and incorporate this into my project. How do I generate the SiteMap?
JohnLamberson
Thursday, April 12, 2007 12:08:14 PM (Pacific Standard Time, UTC-08:00)
I would check back on this post:

http://blog.eleutian.com/PermaLink,guid,b454e935-2813-4bb9-b8f3-a724a2a81458.aspx

There have been a few changes since then, but the example has been updated for them. You can find the XML you'll need in your csproj inside the MonoRail.Example.csproj, for example.

From there it's mostly making sure paths are right, references are right. And you've made the necessary changes to your controller base class (addding CodeGeneratorServices property, PerformGeneratedInitialize method) see ExampleController for help on that. Mark your controllers partial and away you go.

Drop us a line if you have any problems.
jacob
Thursday, April 19, 2007 4:26:15 PM (Pacific Standard Time, UTC-08:00)
What are the minimum components that need to be registered in the container. I see your example container registers everything in the namespace?
Monday, April 23, 2007 9:14:31 AM (Pacific Standard Time, UTC-08:00)
DefaultControllerServices is needed, the controller's, obviously.... There seems to be two calls that will both register the code generator services (one of them looks redudant) Most of the services in Castle.Tools.CodeGenerator need to be registered. It's probably easier just to start off with ICodeGeneratorServices and work your way up. IControllerReferenceFactory, IArgumentConversionService, IRuntimeInformationService, IRedirectService.... those are a few that I know you'll need. There are some you won't, as they're used during generation.
jacob
Wednesday, April 25, 2007 6:18:00 PM (Pacific Standard Time, UTC-08:00)
Hey guys I am getting a really wierd exception with the code generator last time I played around with it I didn't receive exceptions like this.

The "GenerateMonoRailSiteTreeTask" task failed unexpectedly. System.TypeLoadException: Unable to resolve: UserBuilder

Its failing on this method/action.

[AccessibleThrough(Verb.Post)]
public void Create([DataBind("user")] UserBuilder builder)

if I remove that method it builds fine.

any ideas?

Thanks, Mike

The "GenerateMonoRailSiteTreeTask" task failed unexpectedly.
System.TypeLoadException: Unable to resolve: UserBuilder

Server stack trace:
at Castle.Tools.CodeGenerator.Services.TypeResolver.Resolve(String
typeName, Boolean throwOnFail)
at Castle.Tools.CodeGenerator.Services.TypeResolver.HighLevelResolve(String
name)
at Castle.Tools.CodeGenerator.Services.TypeResolver.ResolveTypeReference(TypeR­eference
reference)
Thursday, April 26, 2007 9:36:18 AM (Pacific Standard Time, UTC-08:00)
My bet is your UserBuilder class is in a different project than your web site.

I just ran into this as well and was told that the answer is out there on the mailing lists but am still looking for it. Guessing you need to cue the generator task as to what assemblies are required by the task

I bet it would be possible to have the build task look at the project's references and load assemblies from that list as necessary.
Thursday, April 26, 2007 9:41:08 AM (Pacific Standard Time, UTC-08:00)
Found the thread: http://groups.google.com/group/castle-project-devel/browse_thread/thread/1f447e80d5e3bc74/2b9fa29ea65922bb

Enjoy.
Thursday, April 26, 2007 12:38:13 PM (Pacific Standard Time, UTC-08:00)
do you have any example to show how to used typed flash and typed session object also?

Also create a view interface for each view takes too much work...do you suggest any way around it?
JohnLamberson
Thursday, April 26, 2007 3:36:35 PM (Pacific Standard Time, UTC-08:00)
Kevin, yea I was just working through this today w/ the dovetail guys... they key is that DependsOnTargets="ResolveReferences"... if you don't have that, well, you'll waste a few hours :)
Aaron Jensen
Thursday, April 26, 2007 3:40:10 PM (Pacific Standard Time, UTC-08:00)
John, I'm pretty sure those are just IDictionary's, so you'd just do it the same way. Have you tried that and run into a problem? We don't use flash or session for much of anything...

Yea, creating the view interfaces is work... and I've been thinking about ways around that, but it's off in the horizon.
Aaron Jensen
Thursday, May 10, 2007 5:05:25 PM (Pacific Standard Time, UTC-08:00)
I am able to get the code generator up and running for a while now. However, I just noticed recently that the data on the form is lost when the form failed validation check. I am doing something wrong?
JohnLamberson
Thursday, May 24, 2007 4:45:48 AM (Pacific Standard Time, UTC-08:00)
Hi all,
Great example! But I have a couple comments...

I was looking at the sample code and wondered if I had stumbled onto a potential problem.

In the code you are injecting the ICodeGeneratorServices into the controller. But this instance is a singleton, whereas the controller is transient(I think). But in PerformGeneratedInitialize() of the controller you set properties of the ICodeGeneratorServices instance. Won't this cause a problem since every controller is using the same instance of ICodeGeneratorServices?

Also, I believe that you need an additional step in PerformGeneratedInitialize():
_services.CodeGeneratorServices.RailsContext = Context;


Thanks all!
Brian Chan
Comments are closed.