Some more AspView love:
This dude, Morten Lyhr (great blog - go on and subscribe), has taken the sample MonoRail Getting Started project and AspView-ed it.
can you guess why this makes me happy?
This is the output of building Castle's trunk, both for .NET 3.5 and .NET 2.0, after inserting AspView into the core project. Took me a while as I had to:
So, soon enough (hopefully by the end of this day) you'd be able to see AspView on the build server.
Thx again for all of the users and patch-contributors for your faith in this library.
I've just stumbled upon an old post on this very blog.
In the post I actually quote a comment I have left on Ayende's blog. The nice excerpt from there:
Maybe having a ViewEngine that's use c# or VB.NET instead of boo (not the WebForm ViewEngine which suck, but somthing similar to Brail)
This was on 26/10/2006 ...
Three weeks later (on 14/11/2006) I've announced AspView, after starting working with the first bits for my employer at the time, SQLink
Two days later I have made a first release public.
on 01/12/2006 I was granted a Write access to castle/contrib - AspView started gaining some recognition from the community
The rest is history. You can follow on the AspView tag here
What's there to come? stay tuned and find out
Usually I won't just link to a post, however go and read this post from Andre Loker is is a good one, and the title says it all.
A quote from there, just as appetiser:
if you use ReSharper (and you should) you can skip the ViewAtDesignTime class altogether and just use the AspViewBase class (or a derived class) in the view. ReSharper will still provide Intellisense. The list of members is much more reliable as those members will definitively be available during compilation.
All in all, Andre's blog is good reading. Added to my rss-reader of choice.
Have just came back from my talk, given for The Developers Group in Microsoft's Victoria offices, London UK.
Took me a bit to find the place, as the building does not say "Microsoft" on the outside (as opposed to the offices in Israel).
The presentation went pretty much ok, considering it was my first time actually presenting in English, in front of an English crowd, and considering I had a PC malfunction that has forced me to recreate the Demo project, on the train today ... Just finished it up 5 seconds before connection the laptop to the projector.
I didn't manage to squeeze in some of the parts that I wanted to, like JSONReturnBinder and Windsor integration, and like Unit-Testing controllers and views, but I do hope that I managed to do justice with this wonderful stack, within the limited time and my horrible English ...
Unfortunately, I missed the post-meeting-pub-thing as I just happened to leave the place last and didn't see where everyone did go, so if you were there and has some questions, please do not hesitate to leave them here as comments.
Anyway, as promised, here are the slides and the demo project.
If you are using git, and have a git-hub account, then you would be able to follow the demo project's source at http://github.com/kenegozi/monorail-aspview-demo/tree/master
Have fun.
P.S
I'd like to thank Jason from The Developers Group, and Nina from Microsoft, who have helped with the administration part of things. Everything went smooth despite my late arrival. I'd also like to thank the attendees for their patience and listening. I hope you've enjoyed it, I definitely have :)
MonoRail runs on .NET 2.0. AspView is no different, and is compiled for .NET 2.0, so people who cannot run 3.5 (shared hosting, other limitations) can still enjoy every shining new feature.
However, if you DO want to use c#3 stuff in view templates (like extension methods), then you can. Thanks to Felix Gartsman, the AspView compiler would try to load the c# compiler based on the codedom section of the application .config file.
So, if you're using autorecompilation=true, the add this to your web.config:
<system.codedom>
<compilers>
<compiler language="c#;cs;csharp"
extension=".cs"
type="Microsoft.CSharp.CSharpCodeProvider,System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
warningLevel="4">
<provideroption value="v3.5" name="CompilerVersion" />
<provideroption value="false" name="WarnAsError" />
</compiler>
</compilers> </system.codedom>
If you want to precompile your views, then add the same to vcompile's app.config.
There appear to be yet another XML API.
So, when you want to generate:
<?xml version="1.0" encoding="utf-8"?>
<root>
<result type="boolean">true</result>
</root>
instead of (using System.XML):
XmlDocument xd = new XmlDocument();
xd.AppendChild(xd.CreateXmlDeclaration("1.0", "utf-8", ""));
XmlNode root = xd.CreateElement("root");
xd.AppendChild(root);
XmlNode result = xd.CreateElement("result");
result.InnerText = "true";
XmlAttribute type = xd.CreateAttribute("type");
type.Value = "boolean";
result.Attributes.Append(type);
root.AppendChild(result);
one can (using the new API):
XmlOutput xo = new XmlOutput()
.XmlDeclaration()
.Node("root").Within()
.Node("result").Attribute("type", "boolean").InnerText("true");
Exciting.
Or is it?
Why not just (using your template-engine of choice):
<?xml version="1.0" encoding="utf-8"?>
<root>
<result type="<%=view.Type%>"><%=view.Value%></result>
</root>
works great for the "complex" scenarios on Mark S. Rasmussen's blog:
<?xml version="1.0" encoding="utf-8"?> <root> <numbers>
<% foreach (Number number in view.Numbers) { %> <number value="<%=number%>">This is the number: <%=number%></number>
<% } %> </numbers> </root>
and:
<?xml version="1.0" encoding="utf-8"?> <root> <user> <username><%=view.User.Username%></username> <realname><%=view.User.RealName%></realname> <description><%#view.User.Username%></description>
<articles>
<% foreach (Article article in view.User.Articles) { %> <article id="<%=article.Id%>"><%#article.Title%></article>
<% } %> </articles> <hobbies> <% foreach (Hobby hobby in view.User.Hobbies) { %>
<hobby><%#hobby.Name%></hobby>
<% } %>
</hobbies> </user> </root>
is Hobby and Article more complex? no probs. break it down to sub-views:
<?xml version="1.0" encoding="utf-8"?> <root> <user> <username><%=view.User.Username%></username> <realname><%=view.User.RealName%></realname> <description><%#view.User.Username%></description>
<articles>
<% foreach (Article article in view.User.Articles) { %>
<subview:Article article="<%=article%>"></subview:Article>
<% } %> </articles> <hobbies> <% foreach (Hobby hobby in view.User.Hobbies) { %>
<subview:Hobby hobby="<%=hobby%>"></subview:Hobby>
<% } %>
</hobbies> </user> </root>
Can you get more expressive that that?
Look how easy it is to visualize what we're rendering, and how easy it is to change.
I consider all those XML API (including ATOM/RSS writers) as a leaky and unneeded abstractions, just like WebForms. Do you?
Last Thursday I was informed by the organizers of alt.net UK conference that they have managed to squeeze me in, so I immediatly booked a flight to London, and have attendet.
I was superb, and I've written a few posts, but since I was not online during the last few days I had no chance of publishing 'em. Hopefully they'll get during the next few days.
A lot have also been piling up on my MonoRail and AspView "desktops" so I appreciate the patience of the users, and I promise to do my best to keep up with the requests and patches being sent to me ...
From time to time you'd want some of your markup rendered only on 'real' scenarios. For example, you wouldn't want google analytics to track visits you do on your dev machine. Sometime you'd even develop while your machine is not even connected to the internet, and every page would try get the analytics script and will behave strangely.
In Monorail, the Request has a property named IsLocal, just for that. I've wrapped it in a nice ViewComponent.
public class GoogleAnalyticsComponent : ViewComponent
{public override void Render()
{
if (Request.IsLocal)
return;
RenderView("AnalyticsCode");
}
}
Accompanied by the AnalyticsCode view template:
<%@ Page Language="C#" Inherits="Castle.MonoRail.Views.AspView.ViewAtDesignTime" %>
<script src="https://ssl.google-analytics.com/urchin.js" type="text/javascript"></script>
<script type="text/javascript">
_uacct = "MY_URCHIN_CODE";
urchinTracker();
</script>
, that can easily be extensible to set the urchin code with a parameter.
In a good timing for the new year, I'm happy to announce new features to AspView.
I have dedicated a post for each so I'd have a way to reference those features, and for my dear readers to comment on each feature.
So, what's all the fuss about?
Downloads, as always, are from www.aspview.com
A cool feature, repeatedly asked for by users (of AspView, and of MonoRail in general).
When stating the layout name in the controller, you use a comma separated list of layouts to be applied, from the most general (outer) inward.
Example:
in the controller:
[Layout("Site, Admin")]
public class UsersController : SmartDispatcherController
{
public void Index() { }
}
and given those schematic templates:
We'd get:
Say you want to have the possibility to create a method to work in views.
for the sake of argument, let it be:
public string DoubleId(string s)
{
return s + s;
}
your options:
But what if it's simple enough (so you won't need a unit-test) and it's not supposed to be reused (so creating a Helper/Base class is an overkill)?
Now you can put it directly in your view template, and this is how:
<script runat="server">
public string DoubleId(string s)
{
return s + s;
}
</script>
Regular view code
<%=DoubleIt(view.Name) %>
Now the devil advocates would say that "Logic In View Is Evil". And I would concur. But it's not actually logic. It's supposed to be used for view-related string manipulations and such. And anyway you can do Evil Deeds without it, too. And you don't HAVE to use it if you don't want to.
The idea (and 99% of implementation) is by Gauthier Segay. Thanks dude !
It's been asked on the Castle mailing list, and was implemented for NVelocity (and for Brail too, I think), so now it works on AspView, too.
So, doing:
[Layout("\custom\layout")]
public class MyController ...
Would use the template from Views\Custom\Layout.aspx
The existing <%= %> syntax would keep output the raw strings, so it can be used to output properties that has markup inside, like CMS data, the ViewContents in layouts, CaptureFor data, etc.
If you want http encoded output, use <%# %> or ${} instead.
Example:
Given the following view template:
<%
string markup = "<span>";
%>
<%=markup%>
<%#markup%>
${markup}
The rendered output would be:
<span>
<span>
<span>
Have fun.
I found out that on many occasions I use stuff like:
<aspview:properties>
string message = "";
</aspview:properties>
To avoid the need of:
<% = message ?? "" %>
That's it.
From now on, null values would just be ignored.
Notice that it won't help you on
<%=post.Blog.Title %> if post.Blog is null ...
If you know not what XSS is or how easily you can expose your application to XSS, take a short read at the next posts:
AspView was written by me, for my (and my employer at the time) use. Therefore, I did not make it 'secure by default' in terms of HttpEncode.
However, seeing now that the convention lean toward outputing HtmlEncode-ed by default, I'm adapting AspView to that.
The usage would be similar to the one suggested for Asp.NET MVC at http://blog.codeville.net/2007/12/19/aspnet-mvc-prevent-xss-with-automatic-html-encoding/
So,
<%="<tag>" %>
would output
<tag>
While
<%=RawHtml("<tag>") %>
would output
<tag>
The only exception here is ViewContents on layouts. since the view contents is 99% of the times made of markup, so in the layout would still write:
<%=ViewContents %>
All of that stuff is being implemented with AspView trunk (versions 1.0.4.x) that works with Castle trunk.
If anyone wishes me to bubble it down to the 1.0.3.x branch (for Castle RC3), please leave your comments here. Unless I'll see that people actually want that I would probably not make the effort.
I'm pleased to announce that the first step of AspView refactoring is over. The pre-compilation process is now way more coherent and easy to follow and to test. Soon enough, as I'll complete adding a service locator to the mix, it would also be easily extensible.
What can you do now that you couldn't have done before? Use a custom base class for views.
For example: let's say that you have created a supercool helper. You'd probably name it SuperCoolHelper. Now you register that helper on the controller:
[Helper(typeof(SuperCoolHelper))]
public class MyController ...
You can, ofcourse declare it on every view:
<aspview:parameters>
<%
SuperCoolHelper SuperCoolHelper;
%>
</aspview:parameters>
<%=MyCoolHelper.CoolStuff() %>
You can also use the DictionaryAdapter and add the helper to the base view interface:
public interface IView
{
SuperCoolHelper SuperCoolHelper { get; set; }
}...
<% Page Language="C#" Inherits="Castle.MonoRail.Views.AspView.ViewAtDesignTime<IView>" %>...
<%=view.MyCoolHelper.CoolStuff() %>
But now you can create a base class for the view:
The base class:
public class MyView : AspViewBase
{
SuperCoolHelper SuperCoolHelper { get { return (SuperCoolHelper)Properties["SuperCoolHelper"]; } }
}
A mocked class that inherit from Web.UI.Page to make intellisense play nicely:
public class MyViewAtDesignTime : ViewAtDesignTime
{
SuperCoolHelper SuperCoolHelper { get { throw new NotImplementedException("useless"); } }
}
and in the view:
<% Page Language="C#" Inherits="MyViewAtDesignTime" %>
...
<%=MyCoolHelper.CoolStuff() %>
You can mix that with the DictionaryAdapter integration:
<% Page Language="C#" Inherits="MyViewAtDesignTime<IPostView>" %>
... <%=MyCoolHelper.CoolStuff(view.Post.Title) %>
As usual: http://www.aspview.com
77 tests, all green.
That's all new tests from the last week.
I think it's almost stable enough for releasing it on aspview.com
I'll just put the old tests back in (with Ignore) as regression tests, until I'm comfortable enough to remove.
So - custom base classes for views are just around the corner.
Right after that - better extensibility (through custom Pre Compilation Steps provider and MarkupTransformation Provider)
you can of course watch the progress on svn (it's all on the trunk, so if you're using trunk for production, please restrain yourself a few more days ...)
stay tuned ...
Following users requests, I have just posted two documents to using.castleproject.org.
The first is an explanation about the CodeGenerator (from Contrib), and another one, on using the DictionaryAdapter.
Here are the links:
Related stuff:
Following many requests from users, I've created a screen cast in which I show how to setup a new MonoRail/AspView website, from scratch (no wizards).
CreatingMonoRailAspViewWebProjectFromScratchinVisualStudioExpress.wmv
On that demo, I've used Visual Web Developer 2008 Express and Visual C# 2008 Express, both in Beta2, just to show how you can simulate some of the "Web Application Project" experience in the Express editions. Of course it's much easier to work with a full Visual Studio with Web Application Project as you then have everything in a single application, and it's easier to handle.
Nothing on the demo is 2008 specific, and it runs on .NET 2.0, so VS2005 would do just fine here.
The demo is very simple, and I have generally just showed a "Hello World" level of setup. I hope to spare some time to follow up with setting up things like Windsor Integration, the Castle.Tools.CodeGenerator, and other cool stuff.
The links I use on the demo are:
I've used Windows Media Encoder to capture the screen, and my SHURE SM58 mic to record the narrating. It's a great mic, however plugged into my sorry excuse for a sound-card.
It's my first screen cast, and I'd love to hear comments from you people, both on the content and on the presentation.
Scott Guthrie is going to present a demo application using the ASP.NET MVC Framework.
First episode is here: http://weblogs.asp.net/scottgu/archive/2007/11/13/asp-net-mvc-framework-part-1.aspx
Very interesting. I can already see four things that my current VS2005/MonoRail/AspView/IIS5-6 stack lack.
Sounds bad?
Well:
So - all the downsides are taken care of.
Plus, the stack I use is being used in production environment by gazillion people (ok, AspView is not that common, but the ViewEngine is just 5% of the whole stack, and it's the rock solid part anyway). It is working with .NET 2.0 so I need not convince clients to go for installing .NET 3/3.5 on their shared hosting solution, and since it's open-source, I can tweak stuff for my needs without the need to wait for a hotfix/ServicePack that might never appear, if not too late.
And if I'm not enough of a jerk for ranting like that, I'm going to try (if I'd have enough time) to put up a sample application using MonoRail/AspView similar to Scott's, but this time, you would actually be able get the bits and run it on your machines.
Stay tuned.
I've been asked lately about the use of the ViewFilter mechanism in AspView.
I've once written about it briefly here on my blog, and you can see it at http://www.kenegozi.com/Blog/2007/01/08/introducing-viewfilters.aspx
However, I'll post another (a bit more realistic) example here.
Scenario: some kind of a CMS thing. You want to present the user with some markup, in both "preview" mode and "Source" modes.
If the server had direct access to the markup in a string literal, things were easy. That usually happens when the markup is to be supplied by an end user, either directly or through a WYSIWYG Html editor. You'd end up with something like:
public interface IContentItem
{
public string Markup { get; }
}
your view would look like:
... <h3>Preview:</h3>
<div><%=view.ContentItem.Markup %> </div>
<h3>Source:</h3>
<div><%=Helpers.Html.HtmlEncode(view.ContentItem.Markup) %> </div>
...
easy enough.
However, what if the piece of markup that you want to show, has some view-logic, so you have a template generating the markup from an entity? For example, this blog has a view "Posts/One" that gets a Post entity, and fits it into a single post markup, putting the title in a <h4>, tags in <span> with theit title and href, etc.
How can you show the markup source for that?
ViewFilter to the rescue.
In short - A ViewFilter is a way to transform a chunk of a view, using simple manipulations. Do not look for that on other View Engines, as it's currently an AspView-only feature.
Let's code our needed filter:
public class HtmlEncodeViewFilter : IViewFilter
{
public string ApplyOn(string input)
{
return HttpUtility.HtmlEncode(input);
}
}
and in the view:
...
<% foreach (Post post in view.Posts) { %>
<h3>Preview:</h3>
<subview:.Posts.One post="<%=post %>" > </subview:.Posts.One>
<h3>Source:</h3>
<filter:HtmlEncode>
<subview:.Posts.One post="<%=post %>" > </subview:.Posts.One>
</filter:HtmlEncode>
<% } %>
Hey - you won't even need to create that filter. AspView is supplied with four basic (however useful) filters:
Can you think of more reusable view filters? why not post them here, or better yet, supply a patch to AspView with you filters?
Following a request from Gauthier Segay, AspView now supports nested view components.
scenarion: you are using CaptureFor to inject markup from a view to a layout, and you want the injected markup to include a view component output.
in the layout:
...
<%=CapturedContent %>
...
in the view:
...
<component:CaptureFor id="CapturedContent">
Some markup
<component:SomeFancyStuff>Fancy component content</component:SomeFancyStuff>
</component:CaptureFor>
While working on that, I found out yet another problem. nested components of same type would brake
so:
<component:Bold><component:Bold>stuff</component:Bold></component:Bold>
would brake.
As you probably might know, the whole preprocessing of view, from AspView syntax to standard C# is done with Regular Expressions. For quickly doing the above, I helped myself to http://puzzleware.net/blogs/archive/2005/08/13/22.aspx in order to build the balanced tags aware regular expression, and now it works like a charm. Roy Osherove's Regulator was helpful, too.
So, as of revision 360 in Castle Contrib repository, nesting view components works (for both the trunk and the RC3 compatible branch)
As usual - go to http://www.aspview.com to get the binaries, or to http://svn.castleproject.org:8080/svn/castlecontrib/viewengines/aspview/ for the sources.
Cheers.
If you set autoRecompilation="true" in your aspview section on web.config, then you need not use the vcompile.exe on every build. The views would get compiled in memory from sources.
Benefits: Change a view source, refresh the browser - viola, you can see he change impact. No need to rebuild the web project, the application is not restarted so no session is lost, and no need for "double refresh".
Still, when you deploy it's strongly advised that you'd run VCompile manually, copy the compiledViews.dll to the server, and set autoRecompilation="false" on the server's web.config.
The starter tutorial on using.castleproject.org is now updated, and you can download AspView binaries from http://www.aspview.com
Please use that (and other) new features and leave me some comments please ...
The old syntax for passing parameters to subviews was:
View sources files used to look like this:
<%Page Language= ... %>
... blah blah ...
<subview:whatever name="value"></subview:whatever>
The problem was that you could only have passed variables (by name), so if you needed to pass a string literal you had to declare a string object with the literal:
<%Page Language= ... %>
... blah blah ...
<%string value="literal"; %>
<subview:whatever name="value"></subview:whatever>
The new syntax follows the syntax for view components, and also the expected scripting syntax.
so now:
<%Page Language= ... %>
<%
%>
<subview:whatever name="mike" age="<%=30%>" currentItem="<%=item%>"></subview:whatever>
would pass the string literal "mike" to name, the int constant 30 to age, and the object item to currentItem.
You can download the new binaries, and a utility to migrate your existing views to the new syntax, from http://www.aspview.com
So, what is Properties Section?
View sources files used to look like this:
<%Page Language= ... %>
<%
int someProperty;
%>
... rest of view ...
The problem was that if you had no properties (or have used the DictionaryAdpater option described here) then you had to have an empty section, like:
<%Page Language= ... %>
<%
%>
... rest of view ...
Which is quite ugly.
So, following Lee Henson's suggestion, the properties section should now be wrapped in a special tag, and you can just omit that tag if you do not need to declare any properties.
The new syntax (new stuff in Bold Italic Font):
<%Page Language= ... %>
<aspView:properties>
<%
int someProperty;
%>
</aspView:properties>
... rest of view ...
You can download the new binaries, and a utility to migrate your existing views to the new syntax, from http://www.aspview.com
I've just setup a brand new site for AspView.
It's main purpose is to aggregate AspView related data to one central location. It would contain links to AspView related posts from this blog and others, links to online documentation and samples.
There'd be also a "download" page containing the latest builds to be used with Castle RC3 and Castle trunk.
The site's link is (surprise surprise): http://www.aspview.com
Following my last post on the DictionaryAdapter, I'll demonstrate here how you can get typed access to your views' properties.
What it requires from you:
1. Declare an interface for each of your views. That is a Good Thing anyway, as designing to a contract is a good best practice, and it allows for easy testing.
2. Have a base class for your controller that would define TypedFlash and TypedPropertyBag. Not mandatory, but very convenient.
3. Use the newest build of AspView. Again - not mandatory, but helpful.
Now for the showtime.
First we would create a base class for our controllers, with a TypedPropertyBag and TypedFlash properties:
public abstract class Controller<IView> : SmartDispatcherControllerController
where IView : class
{
IDictionaryAdapterFactory dictionaryAdapterFactory;
IView typedPropertyBag;
IView typedFlash;
protected IView TypedPropertyBag
{
get
{
if (typedPropertyBag == null)
typedPropertyBag = dictionaryAdapterFactory.GetAdapter<IView>(PropertyBag);
return typedPropertyBag;
}
}
protected IView TypedFlash
{
get
{
if (typedFlash == null)
typedFlash = dictionaryAdapterFactory.GetAdapter<IView>(Flash);
return typedFlash;
}
}
protected override void Initialize()
{
base.Initialize();
IDictionaryAdapterFactory dictionaryAdapterFactory = new DictionaryAdapterFactory();
}
}
tip:
You can look at a more complete version of that base-class, written by Lee Henson (who have made some improvements to the original DictionaryAdapter, and also have introduced me to Peroni Beer).
The base controller also declares a type parameter for a Session DictionaryAdapter, hooks into the Castle.Tools.CodeGenerator, and uses IoC for DI.
Talking about those issues is a separate subject, for other posts.
Now let's create the view contract. A rather stupid example would be:
public interface IStupidView
{
Guid Id { get; set; }
string Name { get; set; }
}
controller:
public class StupidController : Controller<IStupidView>
{
public void Index()
{
}
public void DoStuff(string name, string password)
{
if (password != "AspView Rocks")
{
TypedFlash.Name = name;
TypedFlash.Message = "Wrong Password";
RedirectToAction("Index");
return;
}
TypedPropertyBag.Id = Guid.NewGuid();
TypedPropertyBag.Name = name;
}
}
view (Index.aspx):
<%@ Page Language="C#" Inherits="Castle.MonoRail.Views.AspView.ViewAtDesignTime<IStupidView>" %>
<%
%>
<p><%=view.Message %></p>
<form action="DoStuff.rails">
Name: <input type="text" name="name" value="<%= view.Name %>" /> <br />
password: <input type="password" name="password" /> <br />
<input type="submit" />
</form>
view (DoStuff.aspx):
<%@ Page Language="C#" Inherits="Castle.MonoRail.Views.AspView.ViewAtDesignTime<IStupidView>" %>
<%
%>
The data was: <br />
Id: <%= view.Id %>, Name: <%= view.Name %>
Look at the intellisense (and at my ultra-cool black color scheme):
Things to notice:
1. Do not forget to reference the Assembly that has the view interface declaration. On the test site within aspview's source repository the interface is declared in the Web project (AspViewTestSite), so the web.config has this:
view (Index.aspx):
<aspview ... >
...
<reference assembly="AspViewTestSite.dll"/>
...
</aspview>
2. you can use the DictionaryAdapter directly, on older versions of AspView (and on WebForms aspx/ascx files) by simply grabbing an adapter manually. sample:
...
<% IMyViewContract view = new Castle.Components.DictionaryAdapter.DictionaryAdapterFactory()
.GetAdapter<IMyViewContract>(Properties); %>
...
blah blah <%=view.UsefulProperty %>
...
Ok, cut the crap. where can I get it?
UPDATE:
The DictionaryAdapter was initially written by the guys from Eleutian as part of Castle.Tools.CodeGenerator.
Although about three weeks too late, I present thee:
AspView, built for Castle RC3 (release, debug, source)
I've also introduced a well due improvement to the engine. Now it supports the use of a 404 rescue view, that would get rendered in case of the url mapping to a non-existent controller.
the commit comment (for revision 314) says it all:
Handling view creation for EmptyController, specifically when a controller is not found and a 404 rescue exists
Next improvement will include an option for doing AutoRecompilation in memory, as sometimes the IIS process gets hold on the CompiledViews assembly files (dll and pdb) and failing the automatic recompilation process.
I certainly need that as it happens on my machine too much, and building the Web project takes a solid 10-15 seconds, while running vcompile is a milliseconds thing only.
Soon ...
Now that the Big Boys do actually listening to the community, and gives a shot at a solid MVC web framework is a Good Think.
I would really like to see that in action, and would really like to see how they are coming up with stuff that are more than just url->action wiring, such as parameter bindings, view-components, etc.
It's going to be interesting, and MonoRail (and) might need some boost to keep being the (imho) no. 1 choice for Web MVC in .NET
It would be interesting also to see where would AspView fit in the new playground.
btw, would that be part of .NET 4.2?
Anyway, since it might take some time to get this new stuff on a production level, I do not believe that no one that works on production system (or those that are supposed to be at production during the coming year) should ditch MR. Even when it'd be out, I might consider MR as a better solution as it's Open Source, therefore more self twickable, and a lot more responsive in terms of bugfixes.
Regarding my MonoRail/AspView talk from last week, Oren Ellenbogen has compiled a list of "things to remember".
His list (with my notes):
These are my notes about the lecture (as someone who wants to use it in our project at Semingo):
1. DataBind of fields - nice migration from string into classes and vice versa.
2. Need vcompile.exe in order to compile views.
3. Cannot use asp.net controls. Actually we don't need it in our project. (Actually you can use 'em in MonoRail, if you are using the WebFormsViewEngine, but it hurts the simplicity of MonoRail too much)
4. Routing is a must (think about url structure in our project). (RoutingHttpModule will do the job)
5. Learn about the mapping process between controllers, views & parameters.
6. Can use Castle.Validation in order to validate our business objects. (Sweet)
7. Ask Egozi about client side validation .vs. server side validation in MonoRail. (Castle.Component.Validation integrates well into prototype's Real-Easy-Field-Validation, as well as some more js validation libraries)
8. The controller can be injected with outside components (database, services etc) via Windsor, it's integrated easily. (Another sweet spot)
9. TDD is easy (controller and view(should we?)), we can mock everything! Don't forget to call PrepareController method (inside the base class). (Actually PrepareController is Per Controller, so usually it will be called in [SetUp] of each Fixture)
10. FormHelper & DictHelper should make our life easier. (and you can build your own Helpers easily)
11. Controller fills PropertyBag(view use it) & Flash (customer messages) – need to define a property in the view (make it string.Empty as default, if Flash["property_name"] wasn't filled).
12. Use Flash property (dictionary) and RedirectToReferrer method to "refresh" page.
13. Layout["X"] – like master page! (I wouldn't say "like MasterPage" as it's just a simple ol' view, but it gives you a common markup frame for your views, in a similar way of a WebForms' MasterPage)
14. ViewComponent – like a custom control (without the dark magic of asp.net) but contains only UI rendering logic.
15. component:CaptureFor -> we can use it to add javascripts, css files into the html header in the "master page". (dude - It's a Layout, not a MasterPage ;) )
16. We can override the "default" render of the controls via sections in the markup (define sections will override it). (dude - It's a component, not a control;) )
17. Egozi uses prototype (pasha as well?) as ajax framework. For Ajax – call CancelLayout method and RenderView("name_of_view"). This is called SubView and we use it in the markup with <subView:name_of_view />. (Actually I tend to use prototype as a Javascript enhancement, where needed. If only 'ajax' calls are needed, jQuery or YAHOO.connection would be a better lightweight solution)
18. We can use the Cache attribute (MonoRail) over the controller method (aka "Action") in order to avoid cacheability of urls (like Response.Exired = DateTime.Now.AddDays(-1) or something like this). (You can also use Response.Cache as before, the attribute makes our code nicer)
19. We can use Filter for authentication – read about it a little. Each action on the controller will trigger this before running (or after).
20. PropertyBag uses string, eleutian solved it with a smart code generator (pre-build). Create typed Flash and PropertyBag if implementing interfaces. Read about it (ask Egozi for link). (it's in Castle.Tools.CodeGenerator on CastleContrib, and also look at their blog. The tool actually is being used for typing of your site's Controllers, Actions, and Views. As a side effect, they have created DictionaryAdapter than can do the IDictionary<->TypedObject thing. And yuu can also hand-type PropertyBag and Flash.)
Thanks Oren.
Ok. After some delay (couldn't get Internet Connection at my mother in-law's house), here are the links from my MonoRail / AspView talk:
1. The slides (used the newly released StarOffice from Google Apps. Should show ok in Powerpoint)
2. A zip file, containing AspView built against MonoRail from revision 4016 (build no. 472), including a skeleton web project (as shown on my talk), the minimal castle dll's needed to run the skeleton project and links to Castle's build server (to get the full castle libraries) and to my blog.
I did that MonoRail / AspView talk yesterday at August's IVCUG (that's Israeli Visual C#/++ User Group) at Microsoft offices in Raanana, Israel.
I was a great experience for me, and I thank all of you who came in, asked questions, left some change in my hat (damn, I forgot the hat), and (hopefully) had a great time.
The presentation will be uploaded here soon, so will the demo code, and the promised zip with AspView executables for castle build 472 (revision 4016) + stub web.config. It's just that I need to actually WORK today since the last days was more "prepare to presentation" that "work for a living" kinda days.
So, tune in. It would be by here this weekend.
Meanwhile you can go over aspview source code (there's AspViewTestSite that demonstrate many of MonoRail and AspView features. It's quite old and when I wrote it I was quite a MonoRail newbie, so stuff there are not necessarily best-practice quality, but you can grasp how to use subviews, viewcomponents, viewfilters, etc very easily).
http://svn.castleproject.org:8080/svn/castlecontrib/viewengines/aspview/trunk/
You can also look over my blog engine's sources that I have presented yesterday. It's at:
http://kenegozi-weblog.googlecode.com/svn/
The code shown was from going-ddd branch.
bad name btw, as the model is too simple for DDD, and I also violate it from time to time ... (Repository<Comment> ...)
That one is just a link to ScottGu's post on IronRuby.
Now I really need to make sure AspView can handle more languages, as I see IronRuby a natural candidate to be hosted within the AspViewEngine.
If I only had some more free time ...
(Note that it's a call for people who can make it happen. AspView is OSS, so you can give it a shot)
I'm going to give a talk about MonoRail (and AspView, of course), on the next C# UserGroup meeting, at Microsoft Israel offices in Raanana.
If you're interested in a solid MVC implementation for web development, that leverages all the goodies of ASP.NET, without the complications of WebForms - this talk is for you.
I'll brief over "what is MVC" , and then will demonstrate some of MonoRail's features that can help you build web applications in a way that is easy, expressive, testable and fun. I'll also demonstrate how to create a full MonoRail/AspView application from scratch, using trunk versions, as this is something that many people ask for on the Castle dev and user lists, and on my email's Inbox, too.
If you have any ideas/question about MonoRail or AspView, that you'd like me to address during that talk, please drop a comment here or to my email, and I'll try to make room for that in my talk.
Admission is free, and you may attend without reserving a place.
However, the group admins kindly request that you notify them if you plan to attend so that they can be sure to have enough chairs and FOOD!
Contact them through the usergroup's webpage.
See ya.
Referring Jon Galloway's post, here is my 5-minute-scracth-up-somthing that includes no hacking at all:
The Controller:
public class GourmetController : SmartDispatcherController { [AccessibleThrough(Verb.Get)] public void WineMatch() { PropertyBag["matches"] = FoodAndWineMatchRepository.FindAll(); } [AccessibleThrough(Verb.Post)] public void Update([DataBind("matches")]FoodAndWineMatch[] matches) { FoodAndWineMatchRepository.UpdateAll(matches); RedirectToAction("WineMatch"); } }
The View:
<%@ Page Language="C#" %> <%@ Import Namespace="Gourmet" %> <% FoodAndWineMatch[] matches; %> <% IDictionary @checked = DictHelper.CreateDict("checked='checked'"); %> <form action="Update.aspx" method="post"> <table> <tr> <th>Food Name</th> <th>Cabarnet</th> <th>Zinfandel</th> <th>Pinot</th> </tr> <%int i = 0; %> <%foreach (FoodAndWineMatch match in matches) { %> <tr> <td>