See the announcement and grab the latest beta bits.
http://groups.google.com/group/castle-project-users/browse_thread/thread/632ef8b47395736b
What’s new?
http://docs.castleproject.org/Default.aspx?Page=Whats-New-In-Windsor-3&NS=Windsor
Major kudos to Krzysztof Koźmic for running the Windsor show so smoothly.
btw – a new design to the castle project website is about to be launched. It looks awesome! I’ll update once its out
I had tremendous fun coordinating work on the project, and I enjoy working with Monorail on my day job. I just do not have neither the time nor the attention to give the project anymore, and John is a much better fit, as he proved over the last few months with his efforts for the project.
So I treated myself to a one demanding hobby less.
I hope it will help me post more regularly now.
Interesting enough, I plan to do a few posts about recent performance issues I tackled in AspView. So I guess my MR days really aren’t over yet :)
We’re going for a Castle ad on stackoverflow.
How can you help? hop on meta.stackoverflow.com at http://bit.ly/9eNHig, and upvote Castle.
thx
huge kudos to Stackoverflow for doing this, and to Mauricio Scheffer for setting us up
http://github.com/castleproject/
thanx a bunch to the work done by Mauricio Scheffer, Henry Conceição and the rest of the people helping out in the process.
fork away :)
If you use monorail, then go ahead and vote:
During the long, long time it took to get from 1.0RC3 to 2.0, many things have changed, and many things were added. I probably won’t cover it all in this post, and I’ll probably forget a few things that I got so accustomed to use (I have always used trunk versions, even way before I became a committer).
Programmatic config If (like me) you do not like putting stuff in config files that the operations team do not care about, you can now run a Monorail application without the Monorail section in the web.config file.
How? you’d need your Global class to implement IMonoRailConfigurationEvents.
e.g. from many of my websites: (I’m configuring AspView as view-engine)
public void Configure(IMonoRailConfiguration configuration)
{
configuration.ControllersConfig.AddAssembly(Assembly.GetExecutingAssembly());
configuration.ViewEngineConfig.ViewPathRoot = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Views");
configuration.ViewEngineConfig.ViewEngines.Add(new ViewEngineInfo(typeof(AspViewEngine), false));
}
you can setup many optional things that way. e.g.:
// configue jquery as the validation engine
configuration.JSGeneratorConfiguration.AddLibrary("jquery-1.2.1", typeof (JQueryGenerator))
.AddExtension(typeof (CommonJSExtension))
.ElementGenerator
.AddExtension(typeof (JQueryElementGenerator))
.Done
.BrowserValidatorIs(typeof (JQueryValidator))
.SetAsDefault();
// configure url extensions
configuration.UrlConfig.UseExtensions = false;
delve into the intellisense on the IMonoRailConfiguration interface to find more
Return binders The example speaks for itself:
public class State
{
public string Code { get; set; }
}
[return: JSONReturnBinder]
public State[] GetStates()
{
// fake code for the sake of the demonstration
return new[] { new State { Code=“CA” }, new State { Code=“WA” } };
}
will render the JSON representation of the given State array
New routing engine see http://www.castleproject.org/monorail/documentation/trunk/advanced/routing.html
and http://kenegozi.com/blog/2009/02/10/monorail-routing-and-the-homepage-routing-rule.aspx for setting a homepage route
RescueController A rescue controller will take care of exceptions that have happened during an Action.
You’d create your rescue controller, implement IRescueController, inherit from SmartDispatcherController, and setup the rescue controller in the RescueAttribute on the regular controller.
see more here: http://www.castleproject.org/monorail/documentation/trunk/usersguide/rescues.html
AspView The C# based view engine became a first class citizen in Monorail. There has been many improvements there during the time, which deserve a separate post perhaps. meanwhile you can look at the aspview tag on this blog: http://kenegozi.com/blog/Tag/aspview.aspx
I can’t think of more stuff right now, so ping me if I forgot anything.
Being an Open Source project, with very good test coverage and a very active development, most users that actually run Castle bits in production were running off of trunk anyway.
The trunk is very stable, and the act of “release” should have simply been tagging any single commit to trunk as the 2.0 RTM.
However, we felt that we wanted some more stuff to justify a release – like updating the documentation, re-doing samples and Visual Studio integration packages, etc.
That lead us to a halt, as active committers did not use neither integrations nor samples, and same for the documentation. My personal stand was (and still is) that if someone wanted an official release so badly, then that one should contribute toward this, either with time and work, or with sponsorship money to buy this time and work.
No one did.
A few attempts at these parts was taken, but none concluded.
Meanwhile the project grew more and more, and parts of it became mandatory dependencies to various mainstream projects (such as NHibernate), while Windsor became more and more adopted as an IoC container of choice for many people.
Getting to a single point of approval across the board for the whole castle stack, without breaking third-party projects that depends on parts of Castle, became very difficult.
Breaking apart In order to allow a manageable release process, the project was broken down to its parts. Now we have the four main projects, released on their on, with depending projects using compiled releases of the others.
The main projects are:
More details can be found on the projects page of castle’s website
An all-trunk builds can be retrieved with the aid of the horn-get project.
So why is Monorail last? The reason is rather simple. Monorail depends on almost any other part of the stack. It even has subprojects such as ActiveRecord’s DataBinder (ARDataBind) which depends on ActiveRecord, and a WindsorIntegration project which depends on the IoC stack.
As a result we had to wait to get releases for all other projects.
What’s next? I still have no idea. There are a few discussions going on about that (such as this one on the new roadmap), and you are all welcome to join the debates.
After a long huge wait, finally Monorail 2.0 is out, get yours from https://sourceforge.net/projects/castleproject/files/
HUGE thanks to John Simons and the rest of the Castle project committers, plus the rest of the good people that have supplied us with patches, bug fixes, and whatnot.
This move somewhat concludes the move from the old 1.0RC3 release from 2007, to the new releases of the Castle stack about two years afterwards.
I’m going to follow up with a couple of “what’s new”, “how-to upgrade” and “why the hell did it take so long” posts soon, so keep watching.
Looking into When using an OR/M of any kind, it is quite worthwhile to be able to look at the SQL generated by the tool, for various reasons (such as tuning the DB, finding SELECT N+1 issues, and sheer curiosity).
Solution #1 One way of doing that is to start a profiler on the DB engine, but it has its downsides. For one, you would need a profiler tool, which is not always freely available. You might also not be able to access the DB engine with that kind of tool on various hosted environments.
In NHibernate’s configuration (and it is also exposed to Castle’s ActiveRecord users) you can set a property names “show_sql” to true. This will cause NHibernate to spit every SQL query, along with its parameters, onto the Console. Very useful when running Tests, but when running within a Web Application, you do not have access to the Console window, and can’t really see what is going on.
That also leads to another problem with using a profiler on the DB engine – you won’t be able to figure out which queries belong to which web request.
Solution #2 One comprehensive solution is to use the excellent tool from Oren Eini – NhProf. I will not cover this tool here; it does lots of great stuff, and can help your development cycle. However not everyone will be willing to pay the price for using it.
not to worry, I hereby offer you two more options, which gives you less options, but are good enough for the problem at hand, and are free.
Free solution #1 NHibernate is using log4net. it stores a lot of what it’s doing there. So, one can always setup a logger named “NHibernate.SQL” and get a hold of the queries. I do not cover log4net usage here. Google it up, and then set up the NHibernate.SQL logger.
You’d also want to setup a log4net variable for you to group the queries it gets by the web-request that needed them. You can do so by setting a property on log4net’s GlobalContext. e.g., in Application_BeginRequest:
log4net.GlobalContext.Properties["page_url"] = Context.Request.RawUrl + "|" + Guid.NewGuid();
then you’d set the log appender to write the page_url value, and you’ll be able to Group By it.
But this suck. You need to depend on log4net even if you do not want to, and setup that hack-ish global property, then read it from the log4net storage, and lots of complexities. wouldn’t it be great if you could simply got a hold of the Console’s output (or at least the NH parts of it?)
Free solution #2 – even simpler The Console object allow you to set a custom Writer to its Out stream. Meaning, you can grab the Console’s output into an in memory string during a request, and then at the end of the request, grab all lines that starts with “NHibernate:” and you’re done:
on Application_BeginRequest:
var writer = new StringWriter();
Console.SetOut(writer);
Context.Items[SqlLogFilter.SQL_LOG_WRITER_KEY] = writer;
on Application_EndRequest:
var writer = HttpContext.Current.Items[SQL_LOG_WRITER_KEY] as StringWriter;
if (writer != null)
{
var lines = writer.ToString().Split(new[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries);
var relevantLines =
lines.Where(l => l.StartsWith("NHibernate") || l.Length > 0 && char.IsWhiteSpace(l[0])).ToArray()
;
var queries = string.Join(Environment.NewLine, relevantLines)
.Split(new[] {"NHibernate:"}, StringSplitOptions.RemoveEmptyEntries)
.Select(q => q.Trim());
DoSomethingWith(queries);
}
within DoSomethingWith you can do whatever you like with the queries string collection
The more complete solution that I use, is taking advantage of a feature in Monorail’s AspView called ViewFilter (you can do this with ASP.NET’s output filter; look up HttpFilter. it’s not as clean, but workable). I create a filter that wrap the stuff that’s on the Application_EndRequest, turn the queries collection into a bunch of <pre> elements, and stick it within the view-engine’s output by simple string.Replace call, injecting these <pre> elements into a marker location in the markup.
I’d then use jQuery to make these <pre> elements visible when clicking somewhere secret on the screen.
The ViewFilter’s code (for reference):
public class SqlLogFilter : IViewFilter
{
public static readonly string SQL_LOG_PLACEHOLDER = "SQL_LOG_PLACEHOLDER";
public static readonly string SQL_LOG_WRITER_KEY = "SQL_LOG_WRITER_KEY";
public string ApplyOn(string input)
{
var log = "";
var writer = HttpContext.Current.Items[SQL_LOG_WRITER_KEY] as StringWriter;
if (writer != null)
{
var lines = writer.ToString().Split(new[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries);
var relevantLines =
lines.Where(l => l.StartsWith("NHibernate") || l.Length > 0 && char.IsWhiteSpace(l[0])).ToArray()
;
var queries = string.Join(Environment.NewLine, relevantLines)
.Split(new[] {"NHibernate:"}, StringSplitOptions.RemoveEmptyEntries)
.Select(q => q.Trim());
log = queries
.Select(q => "<pre>" + q + "</pre>")
.Aggregate("", (q1, q2) => q1 + q2);
var count = queries.Count();
log = "<p>Queries: " + count + "</p>" + log;
}
return input.Replace(SQL_LOG_PLACEHOLDER, log);
}
}
When using Windsor’s logging facility, you’d usually take a dependency of an ILogger in your component, and have Windsor create the logger instance. The logger’s name will be of your component’s full type name.
e.g. for the following component:
namespace My.Application
{
public class UsingLogIntegration
{
readonly ILogger logger;
public UsingLogIntegration(ILogger logger)
{
this.logger = logger;
}
}
}
The logger’s name will be My.Application.UsingLogIntegration
At times, you would need to get a logger in a different way, either because you’d want a special name, or you will be in a location where you cannot have Windsor resolve that for you as a dependency (say within an ASP.NET’s Global.asax class, which gets instantiated by ASP.NET, not by Windsor).
The naive approach would be to ask the container for an ILogger, however if you’d try this, you’ll discover that Container.Resolve<ILogger>() will not fit your needs. So what will you do?
Well, the facility also sets an ILoggerFactory, which is in charge of creating loggers. So, do that instead:
var loggerTypeOrName = GetTheTypeForTheLoggerOrAStringIfYouPrefer();
var logger = Container.Resolve().Create(loggerTypeOrName);
ILoggerFactory.Create() can live with a type (will use the full type name as name) or with a string.
So you want to be able to do some logging from your code.
log4net for example, is a very common logging framework for .NET, and using it is pretty straight forward, and the net is full of log4net intros.
Usage example:
namespace My.Application
{
public class UsingLog4netDirectly
{
private static log4net.ILog logger = log4net.LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType.FullName);
...
...
...
}
}
However, there are some caveats with using it directly.
Windsor, once again, can help a lot with making it much easier. e.g:
namespace My.Application
{
public class UsingLogIntegration
{
readonly ILogger logger;
public UsingLogIntegration(ILogger logger)
{
this.logger = logger;
}
...
...
...
}
}
Windsor will take care of injecting the correct logger instance, with the name set correctly (using the class name, not needing the wacky MethodBase… stuff)
So, what do you set this up?
Required assemblies: Assuming you already use Windsor, you need
You actually do not need to reference these assemblies, only make sure they are on the application’s bin folder. If you use the programmatic configuration (like I do), you’d also need the first (the facility) referenced from your code.
Registration:
container.AddFacility("LoggingFacility", new LoggingFacility(LoggerImplementation.Log4net));
and … that’s it !
You still need to setup log4net’s configuration, and tell the application where it is:
log4net.Config.XmlConfigurator.Configure();
Get a different logger for tests Easy. Instead of configuring the facility, you simply configure another implementation.
container.Register(Component.For().Instance(new ConsoleLogger()));
If you’d explore the Castle.Core.Logging namespace you’d find few, very useful built-in implementations, such as a NullLogger (which you get by calling NullLogger.Instance), ConsoleLogger, StreamLogger (write to a file or memory stream), TraceLogger (writes to the diagnostic trace output) and WebLogger (writes to the HttpContext’s Trace, visible at trace.axd).
I want to release MonoRail as soon as I can. In order to do so I will need some help from the community. Let me list the things currently missing:
Any help with the above will be greatly appreciated.
thx,
Ken.
Scenario: You are building a Monorail web site, and want to setup a route from the application’s path to a given action (usually home/index)
The problem: The pattern “/” does not work, so
RoutingModuleEx.Engine.Add(
new PatternRoute("Home", "/")
.DefaultForArea().IsEmpty
.DefaultForController().Is("Home")
.DefaultForAction().Is("Index")
);
will fail to serve http://yoursite/
Same will happen if you’re using the Code Generator for setting up rules.
[PatternRoute("Homepage", "/")]
public void Index() { ... }
will fail just the same
The fix: Use the pattern “/[controller]”, like that:
RoutingModuleEx.Engine.Add(
new PatternRoute("Home", "/[controller]")
.DefaultForArea().IsEmpty
.DefaultForController().Is("Home")
.DefaultForAction().Is("Index")
);
or if you’re using the Code Generator:
[PatternRoute("Homepage", "/[controller]")]
public void Index() { ... }
Future fix: I’m considering adding a useful HomepageRoute that will derive from PatternRoute and will have all the needed conventions for easily setting up the homepage rule. Hopefully will be in trunk by this weekend. This will allow a simpler default syntax:
RoutingModuleEx.Engine.Add(
new HomepageRoute()
);
or (using the code generator):
[HomepageRoute]
public void Index() { ... }
Convention over Configuration.
Here is the promised presentation from the talk I gave yesterday, for the Web Developers Community at Microsoft offices in Ra’anana.
The sources for the demo I showed are hosted on github. If you’re not using git (and you should give it a try if that is the case), you can grab a zip of the latest snapshot from that site (there’s a ‘download’ button). Git is worth using if only for the great service given by github.
http://github.com/kenegozi/monorail-aspview-demo/tree/master
As for the slides - I tried using scribd and SlideShare, both attempts ended up not too well. I’ll try to get a better format later on.
I’d like to thank Noam King, the organiser of the WDC group, for having me as a speaker. I’d also like to thank Damien Guard who have created the Envy Code R font which I used during the presentation.
I’ll be giving a talk on Monorail tomorrow evening, at Microsoft offices in Ra’anana.
Registration details are here:
https://msevents.microsoft.com/CUI/EventDetail.aspx?EventID=1032402276&Culture=he-IL
I’ll try to upload the presentation beforehand to here (no promises though).
See you there :)
Following my last post, I’ve put up a quick poll for trying to grasp some knowledge about the way people are using (or not using) MonoRail.
It’s not complete, and there will be further polls as I can already think of questions I have for the community, that did not make their way to this poll, and are very important imo.
So, if you care for the future of MonoRail, please do spare some moments to fill in the poll. Be nice and write down your feelings, pain-points and general rants in the text areas. I won’t be offended by anything.
No personal details will be published (at least not deliberately - and I don’t believe anyone will hack into the lousy SQL server it’s stored on).
so, without further ado, I give you the poll:
From the mailing list:
… the PMC decided to make a few changes to the Castle Project:- Projects will be split- Each project will have a leader (positions open to any committer)By that we intent to fix our release debt. as having each project running individually allow us to release and document each one of them without dragging/waiting for others.
We still haven’t decided how to solve dependencies and such, but with time I’m certain we’ll be able to come up with solution that will benefit the community.
ah, and I have been the one appointed as Project Leader for Monorail.
Quoting again from the mailing list:
We would expect from the leaders to oversee the development (near and long term), set up goals, roadmaps, coordinate the documentation effort and release it.
So my main effort now will be to push a Monorail 1.0 RTM release out of the door. There are many things that need be done before this comes true as in terms of the non-code aspects (like docs, wizards, etc.), Monorail is not as ready as ActiveRecord for example.
I will be posting some specific requests for help on the various tasks that will need to be done. I hope that with the aid of the community, we will have a release soon-ish.
explanation (before the wife kills me): I have some free time in the coming months, so I’m looking for interesting consulting gigs.
So, if you’re in a company / dev team, and looking for some help with Castle (Windsor, MonoRail), NHibernate, or general information system design and architecture advices or training, setting up build and test environments, or any other of the things I rant about in this blog, then I’m your guy.
I also do web-client ninja work, dancing the crazy css/html/javascript tango (jQuery: yes, Ms-Ajax: no)
I currently live in Israel, but I’m fine with going abroad for short terms if you’re an off-shore client.
you can contact me at “ken@kenegozi.com”
I’ve just came across a comparison on IoC containers in the .NET world:
Haven’t read it yet cuz Im actually off-computer right now (the lappy is attached to the living room TV, and the break in the movie is almost over), but MAN is has COLOUR charts, so you can bet your arse I’m gonna read it later.
Not that I’m excited. I’m pretty sure that (INSERT WINNER HERE LATER) will prove to be the best IoC ever.
Background When using SmartDispatcherController as a base class for a MonoRail’s Controller, there are built-in smarts for binding values from the client (Form, QueryString, Request.Params) into .NET data types.So, assuming the request holds “age=30”, and there’s an action
public void SomeAction(int age) ...
then the integer variable ‘age’ will get populated with the value 30.
This will work for every .NET primitive (int, string, bool) and even DateTime and Guid. If the value is missing from the request, a default value will be set, for example - 0 for integers, or null of nullable types.
There’s also DataBindAttribute that allow you to bind values to a non-primitive DTO object.Say you have
public class User
{
string Name {get;set;}
int Age {get;set;}
}
and that your request is holding “User.Name=Ken&User.Age=30”, then the following action
public void SomeAction([DataBind("User")] User user) ...
will bind the age and name into a new instance of User.
Problem Yesterday, on Castle devs mailing list Andre Loker was asking about a way to bind a value to an action argument, but with the value having a name that cannot match a c# variable name.For example, let’s say that the request is holding “User.Age=30”, but you do not want to bind to a User instance (through DataBind) but you want only the Age part, into an integer variable.You certainly cannot have your action signature look like
public void SomeAction(int User.Age) ...
Solution: Luckily for us, MonoRail was built with extensibility in mind (and whenever a user feels something more is required in the field of extensibility, a patch is always welcome :) ).The extension point here is the IParameterBinder interface, which is being used in DataBindAttribute to let the framework know that the attribute is to be used for data binding.
IParameterBinder:
/// <summary>
/// Implemented by attributes that wants to perform
/// some conversion to populate a smart dispatcher
/// action argument.
/// </summary>
public interface IParameterBinder
{
/// <summary>
/// Calculates the param points. Implementers should return value equals or greater than
/// zero indicating whether the parameter can be bound successfully. The greater the value (points)
/// the more successful the implementation indicates to the framework
/// </summary>
/// <param name="context">The context.</param>
/// <param name="controller">The controller.</param>
/// <param name="controllerContext">The controller context.</param>
/// <param name="parameterInfo">The parameter info.</param>
/// <returns></returns>
int CalculateParamPoints(IEngineContext context, IController controller, IControllerContext controllerContext, ParameterInfo parameterInfo);
/// <summary>
/// Binds the specified parameters for the action.
/// </summary>
/// <param name="context">The context.</param>
/// <param name="controller">The controller.</param>
/// <param name="controllerContext">The controller context.</param>
/// <param name="parameterInfo">The parameter info.</param>
/// <returns></returns>
object Bind(IEngineContext context, IController controller, IControllerContext controllerContext, ParameterInfo parameterInfo);
}
The CalculateParamPoints function is used by the framework to help SmartDispatcherController decide with overload of a given action should be used.
the Bind function, well, binds the request data into the given parameter.
Here is a naive BindFrom attribute, which is to be used like that:
public void SomeAction([BindFrom("User.Age")] int age) ...
The code:
[AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)]
public class BindFromAttribute : Attribute, IParameterBinder
{
private readonly string parameterName;
private readonly IDataBinder binder = new DataBinder();
public BindFromAttribute(string parameterName)
{
if (string.IsNullOrEmpty(parameterName))
{
throw new ArgumentException("parameterName must not be null or empty", "parameterName");
}
this.parameterName = parameterName;
}
public string ParameterName
{
get { return parameterName; }
}
public int CalculateParamPoints(IEngineContext context, IController controller, IControllerContext controllerContext, ParameterInfo parameterInfo)
{
var token = context.Request[parameterName];
if (CanConvert(parameterInfo.ParameterType, token))
return 10;
return 0;
}
static bool CanConvert(Type targetType, string token)
{
if (token == null)
return false;
try
{
Convert.ChangeType(token, targetType);
return true;
}
catch(FormatException)
{
return false;
}
}
public object Bind(IEngineContext context, IController controller, IControllerContext controllerContext, ParameterInfo parameterInfo)
{
var token = context.Request[parameterName];
if (CanConvert(parameterInfo.ParameterType, token) == false)
return null;
return Convert.ChangeType(token, parameterInfo.ParameterType);
}
}
Conclusion The IParameterBinder interface is very important as it allow a user to extend MonoRail to his exact needs. If you want to learn more about that interface and it’s uses, the best places to look are DataBindAttribute.cs in Castle.MonoRail.Framework/Attributes, and ARDataBindAttribute.cs in Castle.MonoRail.ActiveRecordSupport
As a side note, I’m thinking about adding the discussed behaviour into the default DataBindAttribute, so one would be able to bind into primitives, say from “User.Age=30&User.Name=Ken” using
public void SomeAction([DataBind("User")] int age, [DataBind("User")] string name) ...
The FactorySupportFacility in Windsor is very useful but there’s a little something to be aware of when using it.
What is it? This facility allows you to tell the container that when a given service is to be resolved, instead of new-ing it, it should call a factory method to obtain an instance.
This is very useful for context objects (like DbContext, HttpContext etc.) , which are usually being supplied by a framework thus you can’t have the container instantiate them directly. So, assuming you want to inject a ISomeContext object into a service, you need to create a factory that can obtain it for you:
public class SomeContextFactory
{
ISomeContext ObtainFromFramework()
{
return SomeFrameworkContext.Current; //or whatever
}
}
then you can setup the container to use that factory when injecting the context
The usage: Online examples:
And, the gotcha: When taking the programmatic road, you must follow this order of doing things:
var facility = new FactorySupportFacility();
container.Kernel.AddFacility("factory.support", facility);
facility.AddFactory<ISomeContext, SomeContextFactory>("some.context", "ObtainFromFramework");
If you mix 2 and 3, it would break.
There reason of course is that registering the factory into the facility, mean that the facility needs no know about the current container and kernel. This is being done in step 2 so you simply can’t do step 3 before that.
The Sharks Here in Israel, there’s a reality/documentary TV show called “The Sharks”.
It’s about people who have some kind of a business idea, and are looking for investors.
Each entrepreneur gets a few minutes to present their idea and business plan in front of 4-5 well-known Israeli businessmen, trying to get their support in return for percentages of their project.
One can differentiate the totally bad projects with possibly OK projects, simply on the basis of a proper preparations. Some projects are simply vague ideas that popped up on someone’s head, without any business plan of any kind.
Then you have the projects that comes with a detailed business plan, market research, pricing policies and what-not. These are of course the ones that the Sharks (potential investors) show interest in. The interesting bit is that most of the times, instead of asking strictly business related questions, they tend give more importance to the actual usability of the proposed product/service/whatever. They try to get in the head of the potential consumers and look for Achilles’ heels from the user’s point of view.
Solving consumer problems The point is, that you cannot create a product or service to solve problems that you think that people have. You have to solve actual problems that potential consumers are facing.
Paraphrasing DHH from a presentation lately, “It’s not Rocket Surgery”. You should simply solve people’s problems, otherwise they won’t be interested.
self consumer Who is the better consumer than yourself?
Example: There’s this person I know, who will sell you baby carriers. They look very simple in first glance, but then you see that it’s actually pretty useful - it’s adjustable, you can re-use the same carrier in several carrying positions (low, high, front, back), and it’s comfortable for parent and baby. The thing is - she didn’t wake up one day with a crazy idea, hoping it’d match someone’s needs. She made one for herself and her baby, making it better with time, and then thought - ‘hey someone else might like it’
Going back to DHH and his presentation, he states there clearly that the whole RubyOnRails thing was simply something he needed for his day job, so it became very useful, as the consumer (himself) was giving him direct feedback during the development process.
Same can be said on many OSS projects, like NHibernate, the whole Castle stack and many more.
I can testify on AspView, which I created to make my day job easier and more fun, as I disliked WebForms and my employer insisted on ASP.NET and C# all around - that was my best shot. I got immediate feedbacks from the consumer (myself and my team members) so it stayed focused on solving consumer needs.
Demonstrate trust in your tools You should be trustworthy. I evangelise the use of good tools, and I name the Castle stack, NHibernate, Rhino Commons, and more as good tools. I can do this whole heartedly since I use these very tools for my day jobs, on paid projects, not only for pet projects.
And if you are not a consumer Take ASP.NET MVC. This project is being internally run by a team of developers, who their day job is to build this tool, not to use it. On the surface it presents a major problem, no consumer feedback.
The way they chose to solve this problem was pretty simple. Expose as much as you can to the public. Push potential users to play with the API, experiment with use cases, build extensions, whatnot. Continuously grab community input, incorporate it in the product, and get new feedback. All that has started from the earliest stages by ScottGu, then Phil Haack. The while team seam to be everywhere, from mailing lists to ALT.NET conferences, getting consumer input and building around it.
The outcome is that they can focus on solving consumer problems, and the progress of improvements is amazing. It got to the point that I have no problem at all with using ASP.NET MVC, even though I’m an active member in MonoRail. Personally I prefer MonoRail, but I really see ASP.NET MVC as a viable option, and recommend it as a possible solution.
Opposite examples Take the Entity Framework. I’ve been hearing about this beast from 2005. However being able to get the feel of it took way too long. Meanwhile it appear that a lot of stuff has been introduced into it, that might not even be interesting to consumers, while rendering fixing the consumers’ problems more difficult.
And as for trusting your own tools - I’ve heard once that Visual Source Safe was never used internally for development within Microsoft. I also don’t really believe that there is a single public major website under Microsoft’s umbrella that uses SqlDataSource, heavily customised GridView components and other widely demo-ed Webforms stuff.
Confidence Technologies like Silverlight, ASP.NET MVC, not to mention the more experimental stuff like IronXYZ and F#, find their way into community review, and even to internal production use. Microsoft are voting confidence in these products, so do I.
ALT.Microsoft So as far for the notorious Vote of No Confidence in EF, I never have joined it as it simply make no sense imo. It simply does not interest me enough to even vote. They way I see it, EF belongs next to WebForms, while MVC/IronXYZ/F#/etc are legitimate ALT.NET
Cuz ALT.NET is not about opposing anyone. Definitely not MS - hey these guys brought us the CLR and BCL.
It’s also not about being the freedom guerilla fighters fighting the evil Corporate. Not at all.
I think that ALT.NET is a great idea, just like XP (Extreeme Programming), and like XP it has a bad name, as it implies ‘niche’, ‘alternative’, ‘scary’, ‘elitist’, ‘vane’.
It’s not.
It’s about good tools, built to help make us developers work better, and have more fun during. Parts of the DevDiv are as ALT.NET as it gets.
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.
After making it build locally and reaching the conclusion that AspView builds correctly as part of the main Castle build , I’ve commited the changes to the repository, and the build server appear to agree with me:
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.
So after moving to Vista last week, I’ve tried a full castle build with tests.
Things I had to take care for it to run properly (from easy to not-as):
Now that I have a way to run the build and make sure all tests pass, I can start working on my next Castle assignment - bringing AspView into the core project, but that’s a whole other post so keep your RSS reader open …
Following Scott Hanselman’s post on FileUpload in ASP.NET MVC, I’ll add here a few bits on doing that in MonoRail.
First, as MonoRail is an extension on top of plain ol’ ASP.NET, just as ASP.NET MVC is, you can do the exact same thing - i.e iterate over Request.Files, and use a mocked Files collection for test or something.
But as the action parameters binder is very smart, and easily extensible, it’s even nicer to just bind the posted data to a HttpPostedFile, using a FileBinder:
So a custom binder is an attribute, that implements IParameterBinder, a two methods interface:
CalculateParamPoints() - is for helping the framework correctly guess the best candidate of the action overloads. If the file exists in the request then it makes an action with a HttpPostedFile parameter with the name of the file upload name, a better candidate than an overload with a String parameter with the same name.
Bind() - well, kinda’ self explanatory.
so now you’re action can look like this:
Cool? well actually what really is cool is that binding to HttpPostedFile is baked into MonoRail to begin with - so you don’t even need this FileBinderAttribute at all ! you can simply
So why did I show you that?
Testablility.
Since HttpPostedFile is not easily mockable* (cuz it’s bloody sealed and not new-able), you should do what you always do when in need to bypass one of these un-testable hard-to-test* sealed classes: Adapter pattern. Introduce IHttpPostedFile, and supply your own HttpPostedFile encapsulating the built in one.
so:
and
The tools (various small helper libraries) are now under http://svn.castleproject.org:8080/svn/castlecontrib/Tools/
what’s in there:
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 :)
One of the methods of querying the DB when using NHibernate, is to issue HQL queries. HQL stands for “Hibernate Query Language”. It has a SQL-like syntax and is very intuitive for people with SQL background.
The way this works is that NHibernate ‘compiles’ the HQL query into SQL, and then issues the SQL query (using ADO.NET’s facilities) to the DB.
Sounds pricey?
enter Named Queries.
now these are HQL (or SQL) queries, each has a name (obviously), that are been supplied to NH through the mapping. The queries are being translated and cached as IDbCommand objects as part of the framework initialisation, which mean that you get rid of the HQL->SQL overhead throughout the life of the process.
One other major benefit, is that the mechanism to actually execute these named queries, does not differentiate between HQL and SQL queries (for the simple fact that these queries have already been transferred to SQL at runtime). That gives you the possibility to replace HQL queries into tighter SQL queries (with the same parameters and which returns the same resultset) should your DBA figure out a better one.
But if you’re using ActiveRecord, you usually do not have direct access into the mapping (.hbm) files. So how would you use named queries with AR?
enter HqlNamedQueryAttribute (not such a great name, as I did state that it would also work for SQL queries).
So, for an example, on this blog’s source code, within PostRepository.cs you’d see this code:
...
#region queries[assembly: HqlNamedQuery(Queries.FindPostsInArchive, Queries.FindPostsInArchive)][assembly: HqlNamedQuery(Queries.FindByUrlFriendlyTagName, Queries.FindByUrlFriendlyTagName)]namespace KenEgozi.Com.Domain{ internal partial class Queries { internal const string FindPostsInArchive = @" from Post p where year(p.Lifecycle.CreationDate) = :year and month(p.Lifecycle.CreationDate) = :month order by p.Lifecycle.CreationDate desc"; internal const string FindByUrlFriendlyTagName = @" select p from Post p join p.Tags t where t.UrlFriendlyName like :urlFriendlyTagName order by p.Lifecycle.CreationDate desc;"; }}#endregion
...
public ICollection<Post> FindInArchive(int year, int month) {
return session .GetNamedQuery(Queries.FindPostsInArchive) .SetParameter("year", year) .SetParameter("month", month) .List<Post>(); }
...
Queries class is marked as partial, as other queries might be presented on other repositories or services that would need to add more named queries. I considered grouping of queries into groups by the using repository, or by aggregate roots, but the thing is - having all of the queries under the same namespace helps discoverability, and helps with preventing duplications
Another funny quote from Castle dev list:
Ayende (after a discussion on the lack of DynamicProxy documentation):Yes, the underlying assumption that by the time you are done understanding DP you don’t have the strength to write docs.
If you wanna grok that, then you can look at a small snippet from DP2 code on the blog’s title, or browse the repo
We, at Castle, are occasionally getting bashed at the lack of documentation. I think that the area most users are complaining about is Windsor and MonoRail, (as these two are evolving in the most rapid way).
My personal view on the matter is that since the whole Castle stack, and especially MonoRail and Windsor, are all about “zero friction” and “Convention over Configuration”, the easiest way is to lay hands on sample or oss code and apply that you your solution.
Anyway, in the Alt.NET uk thing that was at Conchango/London last month I’ve met one Symon Rottem. It appear that this guy know his way around tech-docs, and he had picked up that errand, and started putting effort in improving the overall documentation level for Castle, especially the User-Manual part (as the API actually is being generated and is quite good).
I’d also recommend his (young yet promising) blog. It’s on my Google-reader blogroll for quite some time, and I really need to add “Import OPML” to my blog so I’d be able to update the blogs list on the side panel here.
It’s so awesome.
I have about 1 minute for that, and the code is very self explanatory, so Im just doing a Copy&Paste from the Castle dev list:
Craig Neuwirt:
The recent changes to the kernel registration interface allows for custom registration strategies. I just added an AllTypesOf strategy to allow for the most common scenarios. Here are some examples:
kernel.Register( AllTypesOf<IController> .FromAssembly( Assembly.GetExecutingAssembly() ) );
kernel.Register( AllTypesOf<ICommon> .FromAssembly(Assembly.GetExecutingAssembly() ) .WithService.FirstInterface() );
kernel.Register( AllTypesOf<ICommon> .FromAssembly( Assembly.GetExecutingAssembly() ) .Configure( component => component.LifeStyle.Transient .Named( component.Implementation.FullName + "XYZ" ) ) );
kernel.Register( AllTypesOf<CustomerChain1> .Pick( from type in Assembly.GetExecutingAssembly().GetExportedTypes() where type.IsDefined(typeof(SerializableAttribute), true) select type ));
Ayende:
You are taking all the fun out of Binsor :-)
I’m getting asked for this a lot (lately on the Castle’s usergroup, and on many other occasions)
You friend is ActiveRecordMediator.Execute
So here is a sample:
ActiveRecordMediator.Execute(typeof(ActiveRecordBase), delegate (NHIbernate.ISession session, object data){ IDbConnection con = session.Connection; IDbCommand cmd = con.CreateCommand();
// That's the key part - joining the current AR transaction scope session.Transaction.Enlist(cmd);
// now you have a IDbCommand instance - use it at will
}, null);
If you want to create a proper method for handling the delegate instead of the anonymous one, then you can pass data in there (using the third argument) and it would get into the delegate as the “object data” thing.
Lately there has been some noise around the lack of documentation on the Castle project.
I have expressed my view on the matter on the mailing list, and in short I’d say that having an undocumented feature is way better than not having that feature at all.
During the ALT.NET UK conference, one of the guys approached me and said that he has solid background in technical documentation, and that he is willing to put some effort to that end.
I’m terrible with names, so I forgot his (sorry …), but if it’s you dear reader (or if it’s not you, but you are willing to help with that) then please do contact me should you need any help in kicking it off.
Thanks a bunch,
Ken.
The Static SiteMap Generator’s home is in Castle Contrib, and it’s named Castle.Tools.StaticMapGenerator
I’ve just commited it to the repository, so it’s at http://svn.castleproject.org:8080/svn/castlecontrib/Castle.Tools.StaticMapGenerator/trunk/
UPDATE (22/06/2008):The source has slightly moved (to a sub folder):http://svn.castleproject.org:8080/svn/castlecontrib/Tools/Castle.Tools.StaticMapGenerator/
I hope to have time soon to blog about the creation of this little tool, and of the usage. Also, expect a binary soon.
Last night I’ve built a nice new tool called StaticMapGenerator which is used to generate a typed static resources site-map for ASP.NET sites (works for MonoRail, ASP.NET MVC and even WebForms).
I’ll blog about it on a separate post in details.
Since I didn’t want any dependency (but .NET 2.0 runtime) for the generator and the generated code, I couldn’t use Windsor to IoC. That calls for a hand rolled simple IoC implementation
Ayende has already done it in 15 lines, but I wanted also to automagically set dependencies and have a simpler registration model.
so I’ve quickly hacked together a configurable DI resolver (a.k.a. IoC container) in 15 Minutes and 22 Lines Of Code. Call me a sloppy-coder, call me whadever-ya-like. It just works.
Ok, I’ve cheated. You’d need using statements too, but you can see that I was generous enough with newlines …
Usage:
Given those:
You can do that:
You need not worry about supplying the BuildDirectoryStructureService with an implementation for the service it depends on, but only to register an implementation for that service.
Lately there has been a major refactoring work being done on MonoRail, as part of the effort toward a release hopefully later this year. As of today, AspView’s trunk is once again compatible with Castle’s trunk.
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
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 …
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:
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>&lt;span&gt;&lt;span&gt;
Have fun.
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:
Create a Helper class and put it there
Create a base class and put it there
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 !
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
&lt;tag&gt;
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.
I’ve spent some times lately with Linq To SQL and have played a bit with the Mapping namespace.
Why I do not like it very much is a matter for a different post. The matter at hand is that I want the power of Linq, and I want the power of NHibernate, and I want the easy road of ActiveRecord.
What do I mean by that? I’d like:
the needed prequisites:
So, Ayende has kick-started it, and with some help from Bobby Diaz, we have a prototype level NHibernate provider for Linq.
To make it work with ActiveRecord, all you need is to add:
using System;using Castle.ActiveRecord;using Castle.ActiveRecord.Framework;using NHibernate;namespace NHibernate.Linq{ public class ActiveRecordContext : NHibernateContext { public ActiveRecordContext() : base(null) { session = GetSession(); } private ISession GetSession() { ISessionScope scope = SessionScope.Current; if (scope == null) throw new InvalidOperationException("You should be in a SessionScope()"); ISessionFactoryHolder holder = ActiveRecordMediator.GetSessionFactoryHolder(); return holder.CreateSession(typeof(ActiveRecordBase)); } }}
and now you can do stuff like:
using (new SessionScope()){ ActiveRecordContext context = new ActiveRecordContext(); var q = from c in context.Session.Linq<Category>() select c; foreach (Category c in q) Console.WriteLine(c.Name); }
Assuming Category has [ActiveRecord] mapping.
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://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:
HtmlDecodeViewFilter
HtmlEncodeViewFilter
LowerCaseViewFilter
LowerCaseViewFilter
Can you think of more reusable view filters? why not post them here, or better yet, supply a patch to AspView with you filters?
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.
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 …
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
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
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 thatyou could only have passed variables (byname), 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
In one word: Wow.
In a few more: It seam that the Castle Project PMC got tired of me nagging them about some patches, so they’ve decided to make me a commiter.
I find it very flattering, as this group is made of very talented people, who are maintaining a rather large, sophisticated, extremely useful and widespread set of frameworks and libraries.
I hope I will stand up to the faith they’ve given in me, by contributing Good Stuff into the repository, and help making existing Good Stuff into Great stuff, and Great Stuff into Amazing.
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:
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.
Have a base class for your controller that would define TypedFlash and TypedPropertyBag. Not mandatory, but very convenient.
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:
view (Index.aspx):
<aspview ... >... <reference assembly="AspViewTestSite.dll"/>...</aspview>
...<% 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.
The castle project has a little gem hidden within.
Well, it has many of those, but I’ll refer to one of them here.
Castle.Components.DictionaryAdapter
This is a tool that can generate typed wrapper around any IDictionary, using a POCI (Plain Old CLR Interface) as a contract. The generation occur on runtime, using Reflection.Emit magic.
Ok, assume you have an information system written in ASP.NET ( warning - WebForms code ahead).
You might keep the current username and a user preferences object in the session.
Somewhere along your application, you’d probably have a pieces of code like that:
and in your code you’d be able to do:
Now, I won’t get into those arguments, but generally speaking it would be great if you had an interface to encapsulate your session data (for example - it’s good for testing as you can easily mock session data).
So:
And use it like that:
You probably want to put the creation of the TypedSession in a base class.
And you’ve probably noticed that the adapter itself is being acquired through an interfacedFactory, so you can easily use your IoC container of choice to plug in specialized implementations on rare edge cases, and also use your Mock framework of choice for easy testing.
On the next post I’ll show you how well that fit into the world of MonoRail and AspView, as the use of dictionaries is wide (PropertyBag and Flash), and using that library + the newest addition to AspView can grant you with a simple, type safe and intellisense friendly view development experience.
Although about three weeks too late, I present thee:
AspView, builtfor 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 …
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):
DataBind of fields - nice migration from string into classes and vice versa.
Need vcompile.exe in order to compile views.
Cannot use asp.netcontrols. 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)
Routing is a must (think about url structure in our project). (RoutingHttpModule will do the job)
Learn about the mapping process between controllers, views & parameters.
Can use Castle.Validation in order to validate our business objects. (Sweet)
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)
The controller can be injected with outside components (database, services etc) via Windsor, it’s integrated easily. (Another sweet spot)
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)
FormHelper & DictHelper should make our life easier. (and you can build your own Helpers easily)
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).
Use Flash property (dictionary) and RedirectToReferrer method to “refresh” page.
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)
ViewComponent – like a custom control (without the dark magic of asp.net) but contains only UI rendering logic.
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 ;) )
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;) )
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)
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)
We can use Filter for authentication – read about it a little. Each action on the controller will trigger this before running (or after).
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:
The slides (used the newly released StarOffice from Google Apps. Should show ok in Powerpoint)
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’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 Castledev 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:
publicclassGourmetController : SmartDispatcherController
{
[AccessibleThrough(Verb.Get)]
publicvoid WineMatch()
{
PropertyBag["matches"] = FoodAndWineMatchRepository.FindAll();
}
[AccessibleThrough(Verb.Post)]
publicvoid Update([DataBind("matches")]FoodAndWineMatch[] matches)
{
FoodAndWineMatchRepository.UpdateAll(matches);
RedirectToAction("WineMatch");
}
}
The View:
<%@PageLanguage="C#"%>
<%@ImportNamespace="Gourmet"%>
<%
FoodAndWineMatch[] matches;
%>
<%
IDictionary @checked = DictHelper.CreateDict("checked='checked'");
%>
<formaction="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>
<span><%=match.FoodName%></span>
<inputtype="hidden"name="matches[<%=i%>].FoodName"value="<%=matches[i].FoodName%>"/>
</td>
<td>
<%=FormHelper.CheckboxField("matches[" + i + "].MatchesCabarnet", matches[i].MatchesCabarnet?@checked:null)%>
</td>
<td>
<%=FormHelper.CheckboxField("matches[" + i + "].MatchesZinfandel", matches[i].MatchesZinfandel?@checked:null)%>
</td>
<td>
<%=FormHelper.CheckboxField("matches[" + i + "].MatchesPinot", matches[i].MatchesPinot?@checked:null)%>
</td>
</tr><%++i; } %>
<tr>
<tdcolspan="4">
<inputtype="submit"value="Save"/>
</td>
</tr>
</table>
</form>
And the mocked “domain objects”:
publicclassFoodAndWineMatch
{
privatestring foodName;
privatebool matchesCabarnet;
privatebool matchesPinot;
privatebool matchesZinfandel;
public FoodAndWineMatch() { }
public FoodAndWineMatch(string foodName)
:
this(foodName, false, false, false) { }
public FoodAndWineMatch(string foodName,
bool matchesCabarnet,
bool matchesPinot,
bool matchesZinfandel)
{
this.foodName = foodName;
this.matchesCabarnet = matchesCabarnet;
this.matchesZinfandel = matchesZinfandel;
}
publicstring FoodName
{
get { return foodName; }
set { foodName = value; }
}
publicbool MatchesCabarnet
{
get { return matchesCabarnet; }
set { matchesCabarnet = value; }
}
publicbool MatchesPinot
{
get { return matchesPinot; }
set { matchesPinot = value; }
}
publicbool MatchesZinfandel
{
get { return matchesZinfandel; }
set { matchesZinfandel = value; }
}
}
publicstaticclassFoodAndWineMatchRepository
{
privatestaticFoodAndWineMatch[] _matches = null;
publicstaticFoodAndWineMatch[] FindAll()
{
if (_matches == null)
_matches = newFoodAndWineMatch[] {
newFoodAndWineMatch("Salmon"),
newFoodAndWineMatch("Steak"),
newFoodAndWineMatch("Chicken"),
newFoodAndWineMatch("Chocolate")
};
return _matches;
}
publicstaticvoid UpdateAll(FoodAndWineMatch[] matches)
{
_matches = matches;
}
}
No hacking needed. Controller code is short and intuitive.
Oh. No postback for every client click …
I especiallyliked one of the comments on Jon’s post:
I love ASP.NET because of tricks like this that the developer can use.
Well, Ido not likeWebForms because it makes me “do tricks” (or hack) instead of bringing business value.
So I do not mean that Jon’s “hack” is bad. That’s what you have to do when you’re WebForm-ing. I just say that there are other web development frameworks (actually, all but WebForms) that are more suited for reasonable html generation and for dealing with the http protocol.
It was absolutely brilliant.
I started to work for SQLink on late December 2005 as a Team Leader in the Web Projects Department.
Colleaged by Oren Ellenbogen, it has been a pleasure. Our department head, Moti, was doing the best he can to create a very likeable working environment, and all our developers were enjoing a workplace that enabled them to learn a lot. Oren and I were directing all kinds of sessions with the developers, showing them stuff about .NET and the CLR, from “what are nullables”, through “What does the ‘using’ reserved word mean”, to “how the GC is actually working”.
We have built this great website called GotFriends, that gave the company a great new source for recruiting new employees, and actually is ground breaking in the Israeli HR world. Building that site, we’ve used many technologies to make it work smoothly with the company’s inner legacy HR system, and with the aid of the SQL master Moran Benisty, it even worked in an efficient way, and coded in a maintainable manner.
Mixing WebForms and Monorail, CodeSmith based BLL with ActiveRecord/NH, ASP.NET WebServices (asmx) and POX/JSON services, it was a very fun thing to work on, in addition to the business benefit to the company.
However, a few months ago the Web Project Department was closed, and the company started a new R&D team, leadedby Elad, the company’s VP of Business Development. We were two developers (Moran and I), and we worked on several initiatives that the CEO Tamir, and Elad, were cooking all the time. Those projects wereall Community-Driven-So-Called-Web-2.0-Kinda-Websites. It was a real delight, and I got the chance to learn a lot about the business side of running an Internet related initiative, as both Tamir and Elad are experienced and intelligent, and the process of refining ideas, with those two, was a real treat.
They also gave me the freedom to make all the technology decisions, and they’ve had enough faith in me to allow me run the projects using MonoRail and AspView, and running Castle ActiveRecord for DB access. Actually, most of the drive behind creating AspView was actually driven by Elad and Tamir, as I’ve promised to do the best I can to make sure that future additions to the team won’t need to learn Boo / Velocity in addition to learn the Monorail MVC and hql.
Which actually worked great. Moran has left the team about two months ago, and we’ve brought three new guys along (Ili, Ofir and last but not least, Itay), and they have seam to easily get control of all the “funky” technologies I’ve put in use in our projects.
Sadly enough, one of the initiatives has stalled just before airing, due to some business decisions. Then we started a new one, and in about 3 weeks we’ve had a working proof-of-concept, and I really hope that the site will air during August. I give the credit to the team, and to the use of MonoRail/ActiveRecord, as it’s such agile and suits highly-changing-environment, as most web initiatives are.
A point of interest: This very blog’s engine was actually a beta testing for some of the stuff we were using on our last project.
That’s it folks. I wish the SQLink family all the best, and I’m going to keep an eye on the cool stuff the R&D team is doing, and hopefully I’ll report on their success (which would be an AspView success too …) right here on my blog.
Check out this nice tool from Omer Rauchwerger.
It could help a team to manage a coding convention. Should be very useful in Open Source environments. For example, when committing changes to castle project (or sending a patch) there is a coding standard than needs to be followed. Regionerate could help a lot with that effort.
I need to see if it can select methods and properties by attributes. It could then help making MonoRail controllers and ActiveRecord decorated classes more readable (region of all actions with a “SkipFilterAttribute”, region of “Property” and region of “HasMany”, etc.)
UPDATE:
Silly me, I forgot to mention that I found about this great tool at Roy Osherov’s blog. A very good one, that is. Many Agile related stuff, and funny little things, too. So go on and subscribe to it’s feed.
taken from Karl Seguin post about his .net wishlist:
Thinking beyond the common request to implement an MVC pattern, I’d be great if the ASP.NET team could rethink the current model and life cycle. It leaks badly in any complicated scenario. 6 years after its release, I still don’t fully understand it, and I’m ready to bet that I’m in the overwhelming majority. The only time it doesn’t leak is when you don’t need any of the fancy stuff it tries to do. I’m almost at the point where I just don’t use .NET if I’m building a heavy web-based application. Forget learning an O/R mapper, test driven development or understanding domain driven development, the single best thing any ASP.NET developer can learn right now is MonoRail.
Could not agree more …
If you are an AspView user you might have noticed a problem.
If you setup a nullable-value-type parameter with a default value other than null, then you’d get a casting error.
example:
<%
int? someInt = default(int);%>
some markup
<% if (someInt == default(int)) DoSomething();%>
it happened because of the way GetParameter worked
GetParameter is a method that gets a view parameter value from the view’s properties collection (PropertyBag, Flash, Request.Params, etc.). It’s located inthe AspViewBase class (the base class for each and every view in the AspView world).
So, now it’s fixed, and a test was added to make sure it’ll stay that way.
As soon as google.com will be accesible again, you’d be able to check out and build.
UPDATE:
I’m too tired (3am here). The sources are on castle contrib and not on google, so you’d find them here
From Castle Project users group:
I’ve just built the trunk yesterday (rev 3812).
Main reason: I needed the BaseControllerTest from Castle.MonoRail.TestSupport.
The build was targeting .NET 2.0, in release, and no tests were run.
You can download it from: http://kenegozi.com/Castle_r3812_net-2.0_release_not_tested.zipNote that it is not tested, so use it at your own risk. If you’re not going production this week, it should not be a problem …
I needed to manually Castle today, for the first time.
The need is for Castle.MonoRail.TestSupport.BaseControllerTest only, so I do not really care about all the rest.
Opened “How to build.txt”
I know that the builds in the CI server are failing due to some filing tests on DP2, so I add “-D:common.run-tests=false”.
no brainer.
I am also targeting .net2 only, so I add “-t:net-2.0”
baboom. This fails.
The nant exe is telling me that I can only build to .net 1.1, or .net compact framework 1.0.
So I went to nant’s config file, and found out to my surprise, that the frameworks that are present there are:
.net 1.1,
.net compact framework 1.0
.net 2.0 BETA 1
hmmm.
So I’ve edited the config, changed the existing .net 2.0 config name to .net2.0Beta1,
copy&pasted the .net node to another one, now switching version number from
sdkdirectory=”${path::combine(sdkInstallRoot, ‘bin’)}” frameworkdirectory=”${path::combine(installRoot, ‘v2.0.40607’)}” frameworkassemblydirectory=”${path::combine(installRoot, ‘v2.0.40607’)}”clrversion=”2.0.40607”
to
sdkdirectory=”${path::combine(sdkInstallRoot, ‘bin’)}” frameworkdirectory=”${path::combine(installRoot, ‘v2.0.50727’)}” frameworkassemblydirectory=”${path::combine(installRoot, ‘v2.0.50727’)}”clrversion=”2.0.50727”
voila. Now the build is starting.
However, the Castle.Components.Validator.Tests dll refuse to build. I’ll disable it, too.
UPDATE:
I’m an idiot. Did not notice that NAnt has gone far beyond rc3 a long time ago …
They just keep on coming …
just added a blogroll.
To the DB, to the Domain, to the controller and to the view.
Took me (all in all) 30 minutes, including all the coding, CSS-ing, uploading to the webserver, setting up the DB table on the hosted server, adding a few entries, clearing the browser’s cache, and viewing it.
ah, and committing changes to Google code.
All of that was made in the Budapest Airport cafeteria, while waiting for my flight home (was a great trip. Photos, though not many of them, will be posted later on).
Rest assure that the DB access code is tested, and that the calls to the DB and to the cached data from the Controller and View are all typed.
I’d like to thank NHibernate, Castle and AspView (hey - that’s me !), who made this possible.
I bet Ayende would have done it in 20 …
I’ve just noticed two sites that uses AspView vienegine (of course they’re on MonoRail)
The first, https://www.musicglue.com/, has the static “home-page” stuff being served from a standard webforms aspx files. The Signup Procees however, and other applicative parts are using MonoRail, with AspView based views. The team behind this site said to me that they’re moving to a complete MonoRail/AspView solution in time.
The other, http://www.escapegreat.com/, is using AspView, top to bottom.
Both sites seam to be working great.
Gives me strength to continue the development on AspView, and find ways to improve it even better.
I’ve just commited to the repository a new version of AspView.
The main addition is “Auto Recompilation” feature.
This means that when you change one of the view sources, the application will automatically recompile the views upon the following request.
You enable the feature by adding the next attribure to the aspview config section in web.config:
<aspview .... autoRecompilation="true" ... > ...</aspview>
Breaking change:
If you happen to reference an assembly from the GAC (using the aspview configuration in the web.config) you need to add a hint for the engine, like this:
<reference assembly="MyAssemblyFromGAC.dll" isFromGac="true" />
Known issues:
You need to let ASPNET user (or the Application Pool user) a modify access on the bin folder.Note that if you use the inner WebServer of Visual Studio this should not be a problem, since in that case the web application runs with your user, that has the needed peremissions on the bin folder.
For a strange reason, after you change a view and do the F5 in the browser, you still see the old version, and only on second F5 will the views be actually recompiled and refreshed. I hope to fix it soon …
Download from here.
Sources are here.
I’ve just got the announcement from the Ruby.NET team at QUT, about the new beta release, numbered 0.7.
The two major things in there:
the compiler now creates pdb files, which means that it can be debugged with the interactive debuggers,
Visual Studio 2005 integration, including Ruby projects.
Can’t wait to check this out.
I’d like to see if I can do some integration into the AspView project, to enable a RubyOnMonoRail thing. I guess it’d have to wait for the BCL integration, promised to be released around the end of this year, but it is quite interesting as it is right now.
ActiveWriter is a VS2005 plugin, that adds a new item type for your projects. This item is actually a visual designer for ActiveRecord classes. Quite neat, and hopefully will increase the penetration of Castle’s ActiveRecord to the “If there’s no VS wizard, I do not use it” kinda guys.
You can read about it and download it from http://altinoren.com/activewriter/
I’d like to point you to a new podcast from HanselMinutes, about MonoRail. Scott Hanselman is interviewing a couple of guys from Eluetian as MonoRail Power Users. Theyare doing a lot of workwith MonoRail using Brail.
Listen to that if you want to hear about how simple MVC for ASP.NET can be.
Actually, It seams that it is getting so much attention, that even MSFT are thinking about implementing something Rails-i in the future ASP.NET. Read this if you do not believe me.
What’s new?
Support for ViewComponents, including those with Sections. It is tested against CaptureFor, and GridComponent.
You can now specify saveFiles=”true” in the config, and the compiler will leave the .cs files generated from the views to the disk, so you can match compilation errors from Visual Studio directly to the view’s concrete class source.
The syntax for the ViewComponents is xml-like: just add
<component:VIEWCOMPONENTNAMEARGUMENTS><section:SECTIONNAME></section:SECTIONNAME>Some content </component:VIEWCOMPONENTNAME>
where VIEWCOMPONENTNAME is the component’s class name, SECTIONNAME is the section name, for components that uses sections, and the ARGUMENTS are xml-attributes, for example: id=”capturedContent” myData=”<%=items %>”
examples (from the test site):
for constant arguments:
<component:CaptureForid="capturedContent"> This content should be rendered in the captured-for place holder </component:CaptureFor>
for variable arguments:
<component:GridComponentsource="<%=items%>"> <section:header><table><thead><th>Id</th><th>Word</th></thead></section:header><section:item><tr><td>1</td><td><%=item %> </td></tr></section:item><section:footer></table></section:footer></component:GridComponent>
As usual, source code is at http://svn.castleproject.org:8080/svn/castlecontrib/viewengines/aspview/trunk/,
Note that for a successful build you’d need to fix the siteRoot parameter in vcompils’s app.config, to point to the actual physical path to the test site’s root
I haven’t written much lately, since I was:
a. Learning for my final exam so I’d get my Bachelor’s Degree at this decade.b. Under a lot of preassure at work, since we have a cool web2.0 thingie approaching a public beta real soon (will be followed).c.Sneasing my heart out, darn flew.d.Got into a new project at my personal business. This one is driven by Castle’s ActiveRecord+MonoRail+AspView, and due to the client’s request it’ll use Access as the backend DB, and that would be a first-time-ActiveRecord/access for me. I still hope to convince him to at-least go for embedded FireBird.
So, stay tuned to some experiences with AspView, and hopefully in about a month you’ll havetwo MonoRail/AspView driven websites out in the open. I am excited. Are you?
Here is the latest addition to AspView.
example:
<%@PageLanguage="C#"Inherits="Castle.MonoRail.Views.AspView.ViewAtDesignTime"%> <% %> Outside the filter <filter:LowerCase>Inside the LowerCaseViewFilter - this text should be viewed in lower case</filter:LowerCase> Outside the filter AGain <filter:UpperCase> Inside the UpperCaseViewFilter - this text should be viewed in upper case </filter:UpperCase> Finally - outside the filter
As you can see, the syntax is simple. Given a viewFilter, named “MyViewFilter”, you use the xml tag <filter:my> or <filter:myViewFilter>. The viewfilter itself has to be suffixed with “ViewFilter” (Just like Controllers are suffixed with “Controller”, etc.), and it has to implement IViewFilter which is defined with:
using System;using System.Collections.Generic; using System.Text; namespace Castle.MonoRail.Views.AspView {publicinterfaceIViewFilter {string ApplyOn(string input); }}
The power of the ViewFilters is than they can apply to a whole SubView, while the subview is rendered as a black box, the filter does the work AFTER the subview was rendered.
Grab the sources, play, and have fun.
After hammet’s approval, I hav finallyadded AspView source to the Castle Project’s Contrib section of the subversion repository.
Thank hammet and the rest of the Castle crew for voting for that.
So from now on, you’d be able to grab the sources from http://svn.castleproject.org:8080/svn/castlecontrib/viewengines/aspview/
Two last comments:1.The latest edition works with Castle’s trunk from build 229.2. The latest additions are supporting “~” as a macro for siteRoot, and “~~” as a fullSiteRoot (~ would expand to the virtual directory, and ~~ would expand to full url- http://…).
There are two facts here:1. I love NHibernate.2. I hate NHibernate’s exception messages.
And here’s my story.
On a project I’m working on, I need to show a projection of “top 10” from the database. let’s show this on the good old Blog scenario:
So I want to show the posts with the longest comments measured by the comment’s length. Stupid, huh? but it’s a demo only (I cannot expose the actual ERD). Let’s say I want the top 5.
I am using Castle ActiveRecord. There is a Post and a Comment classes. However, I do not wish to load Posts objects, since It will load the Comments, too, and maybe other stuff that the Post class is related to. So I have defined a PostProjection class:
1: publicclass PostProjection
2: {
3: publicstring Title;
4: publicint Length;
5: public PostProjection(string title, int length)
6: {
7: Title = title;
8: Length = length;
9: }
10: }
I have also added an [Import] attribute on the Post. The actual querying is done using the next hql:
1: publicstatic PostProjection[] GetTopPosts(int postsToGet)
2: {
3: SimpleQuery<PostProjection> q =
4: new SimpleQuery<PostProjection>(typeof(Post), @"
5: select new PostProjection(p.Title, sum(c.LineCount))
6: from
7: Post p inner join
8: p.Comments c
9: order by sum(o.LineCount) desc
10: group by p.Title");
11: q.SetQueryRange(postsToGet);
12: return q.Execute();
13: }
It worked great.
Yesterday I’ve upgraded my Castle dll’s to the ones from build 229. It includes NHibernate 1.2.0.2002
Now the “select new” started to fail, and NHibernate started to claim than “Could not find constructor for: PostProjection”.
I’ve been scratching my head, trying various approaches, and even was keen to skip the “new” and use an object[ ] and populate the Projection Array by hand, but then I tried changing the “length” parameter of the constructor from “int” to “long”. Magically it solved the problem.
Now, if only NHibernate would have said :
Could not find constructor for: PostProjection.Looking for: PostProjection(string, long)
I would’ve known what the problem was, and what should I change.
So what have we learned today?
I’ve svn-ed the NHibernate trunk, added some code so this message would be more developer friendly, and I’m going to send the patch to NHibernate’s JIRA.
What’s new?
siteRoot has been added to AspViewBase, so you can ditch the “string siteRoot” from the declerations area.
Some permormance improvements. Instead of using “Activator.CreateInstance” everytime a view is to be rendered, a hashtable with ConstructorInfo objects is generated upon reading CompiledViews.dll. This was taken from the c# version of Brail
A new syntax for subviews:
you can use
1: <subView:MyMenu item="menuItem"></subView:MyMenu>
instead of
1: <% OutputSubView("MyMenu", Helper.Dict("item", "menuItem")); %>
take note the <subView:Blah /> is not currently allowed. I’ll fix it shortly.
the link is here
I’ve been off the radar lately, due to some extensive work I do on a website for my employer.
It is still in early stages and I cannot talk about the site itself, but I can talk a little about the technology that drives it.
In one word: Castle.
In a few more words:
Data Access and OR/m: Castle’s ActiveRecord over NHibernate
Web UI Engine: Castle’s MonoRail
ViewEngine: AspView (by yours truely, inspired by Ayende’s Brail). All my spare time from work goes there.
Client Side Javascript stuff: Prototype and Scriptaculous.
I really believe in the efforts made by Castle group, and I hope the the site I’m working on will be successful, as to serve for yet another prove of concept.
One more thing I’m doing last month, is that I’ve decided to finally end the thing with my Bachelor’s degree. I needed to retake Linear Algebra I (yep, that one the all the non-bullet-time Matrixes … I H-A-T-E adjoined matrixes. yuck) so that’s actually why AspView doesn’t progress as I’d want it too (and as some of my readers want, too).
What we have:
Default Helpers are now declared in the AspViewBase. It means that you can use <%=FormHelper.LabelFor(…) %> without the need to declare the helper at the begining of the view.
the compiler was refactored to allow for better testing, and for implementation of further view languages. vurrently I’ve started with VB.NET but it is not working yet, since I have no time to make sure the VB syntax is correct. The tests of the compiler are missing due to some stupidity on my side, of not commiting the TestCase …
I’ve wanted to let svn access but I have some trouble with that. I’ve started a sourceforge project but I cannot upload the repo to the site. I did all they’ve asked on the site but the import process reporting failure no matter what I do. I guess that the best way will be if the Castle team would allow AspView into it’s codebase, maybe on the Contrib repo to begin with …
So meanwhile you can download the current bits from here.
Keep me posted,
Ken.
Just read it.
I started commenting to that post, but I figured that the people who’ve downloaded AspView up to now (I have about 30 or so downloads last week) will want to read it, so I’m posting it here.
So, as Hammet said, the extension is determined on the web.config. The .aspx is used for the view source files so VSNET will color and intellisense them. however, the actions are mapped to an extension that is mapped in the web.config.Still, AspView have some .aspx hard-coded in it, simply cuz I needed to get something working, and working fast. This is why I’ve left non-crucial features out for the moment, such as:1. Dynamic compilation (It is non crucial. IMHO real applications should be pre-compiled, while the dynamic thingie is for design time only)2. Nicer code (more maintainable, less typos such as “extention”, refactoring for testability).3. View Components (subviews are doing the trick for me for now, but in order to mature there must be implementation for it) 4. using the .config. 5. A lot more
btw, helpers ARE supported, You just need to add the declaration in the place, like
<% Post[] posts;AjaxHelper AjaxHelper;AjaxHelper AjaxHelper;%>
In the trunk there is some improvements, such as refactored AspViewCompiler, so it uses a PreProcessor that has subtypes. Currently it has a working CSharpPreProcessor, and a non-working VbPreProcessor. I intend to try adding a BrailPreProcessor … I hope to be able to mix view languages in the same site. each language group will be compiled to a module, and linked to the CompiledViews.dll assembly.
Since I haven’t set any public repository yet, and since I do not have much time for uploading bits manually, you cannot see the work in progress, and it’s my bad. I’ll upload the latest stuff soon, and I’m working on setting up a repo somewhere. btw - do you have recommendation? (CodePlex? Sf? )
So I’m releasing AspView.
You can download the source from here.
It was written against the Castle 1.1 from the trunk, build no. 152.
Please note that in order to run the TestCases you’d have to make sure that the latest Castle.MonoRail.TestSupport is in the GAC.
The documentation is poor since I have a little time now. I am working on a website for my employer (that utilizes AspView and AR) and until the first beta release I won’t have time to do anything but major bugfixes. This project isn’t open sourced so I won’t be able to share it’s sources, however since this will be a public site, it would serve as a Proof Of Concept to the MonoRail and AspView.
The views MUST have the following structure: a. Page header - Must be present for intellisense to work:
1: <%@ Page Language="C#" Inherits="Castle.MonoRail.Views.AspView.ViewAtDesignTime"%>
b. Directives - Not mandatory:
1: <%@ Import Namespace="System.Text"%> 2: <%@ Import Namespace="System.Drawing"%>
c. Properties decleration - Currently it’s mandatory. If you have no properties you mast have an empty block:
1: <% 2: string[] strings; 3: DateTime today; 4: int index; 5: %>
or just
1: <% 2: %>
d. View body
In a layout view you place the inner view using the ViewContents property, like this:
1: blah 2: blah 3: <%=ViewContents%> 4: blah 5: blah
.hlt { background-color:yellow;}
So what is AspView?
It is a Visual Studio 2005 friendly ViewEngine implementation.
The scripting is done using VisualStudio languages (c# and VB.NET). The views are precompiled, (or can be compiled on-demand, but anyway not interpreted).
The project was inspired by the Brail ViewEngine, but since it doesn’t use Boo it is more Management-Friendly, since they need not worry about getting out of the “safe” microsoft world.
I tend to like Boo as a language very much, and I like Brail a lot, too (since it allows for less code in the view thanks to the Boo magic) but I lack the tight Visual Studio integration (opening .boo files in #Develop messes up my desktop), and the intellisense is quite important, at least for the developers I worl with.
So I will post in the next few days about it, and I’ll make it available to be downloaded (source and binary) as soon as I’ll test it a little more. I hope to have a public svn repository soon.
A little demo view:
1: <%@ Page Language="C#" Inherits="Castle.MonoRail.Views.AspView.ViewAtDesignTime"%> 2: <% 3: string[] strings; 4: %> 5: 6: 7: hello from index<br /> 8: This are the strings:<br /> 9: <%foreach (string s in strings) { %> 10: <%=s %><br /> 11: <% } %> 12: 13: <br /> 14: End of normal view 15: <br /> 16: <% OutputSubView("Home/SubViewSample"); %>
Ayende has recently posted a walkthrough for building Web Apps using the Castle Project’s libraries.
He covers ActiveRecord and MonoRail basics, showing off some of the shiny and new abilities (AR scaffolding, ARSmartDispatchers, Generics integration and so on).
The only thing missing is IoC-ing using Winsdor or even Binsdor. Maybe to hook some BL layer or something.
So it concludes (as of now) a Part I, Part II , and source-code.
If you wanna see a decent web development framework at action - tune up to those posts.
Ayende has posted about the matter, only he’ve used the title “MonoRail vs. ASP.NET” instead. I think that his title isn’t accurate since MonoRail is actually a WebForms replacement that is built ontop of ASP.NET, exploiting all of the cool features found in ASP.NET and in the .NET framework alltogether. It’s the Web development framework that Microsoft forgot. So it has the benefits of the Rails interpretaion for MVC, with the power of .NET.
Here is the comment I’ve posted to Ayende’s post:
“My point of argue in favor of MR for people who are afraid of “non-microsoft” is, that actually MR is ASP.NET. It is just not WebForms. You get all the good stuff from ASP.NET: the .NET framework for start, compiled views (on Brail - kudos to you), the HttpModule stuff, seeamless integration with AR. This is what I say to the PMs, etc. To the developers themselves who are afraid, There’s a more detailed approach. Developers (especially ones who didn’t do web programming aside ASP.NET, and probably has a lot of VB experience but no PHP/JSP/ASP) like WebForms cuz they can get to the txtUsername.Text, txtPassword.Text, and txtAge.Text easily, not needing Request.Form[“Password”] (hey - it’s not typed !!!) . But then I reffer them to the fact that actually txtAge.Text isn’t typed too. it’s a string, and should be parsed, tried, validated etc. They should also manually create a User instance, and fill it’s properties. Doing the same on MR with Dispatching and AR is there without any line of code. I show them an example aqnd then hold them as they almost fall off their chairs. Not’n like a good example. 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) can make the move from WebForms to easier for developers, but frankly, as you’ve said, people who can’t get it OJT with a few examples aren’t the one’s I’m likely to work with anyway.”
As said in the title, ASP.NET Ajax (aka ATLAS) is maturing and reached Beta 1 stage.
I haven’t being too mush into it lately, since I’ve beenunder the impression that though Microsoft’s ASP.NET Ajax library was very rich and had many features, it also suffered from many childhood problems, including too many js errors, and a huge .js script to download.
Now, it has an official name, and a beta release, and it’s maturing. The .js was split by functionality, release and debug version of the .js are present, prototyped classes have replaced the closure based ones, and it’s better for me cuz I find it easier to overload behaviuors when needed.
So try it outand read what Scott Guthrie has to say about it.
Since nowadays I’m more into MonoRail over Brail than into Webforms, I guess that the Core package is what really intresting for me, and I’ll try to combine it with AjaxHelper from MonoRail. I hope to report on the matter shotrly.
On a small debate with a friend, about weather he should design and implement a Data Access Layer himself, or use an existing framework, I came across a piece by Ayende about 25 Reasons Not To Write Your Own Object Relational Mapper.
I’d like to add a quote from Code Complete 2 about programmers who are reluctant to read (and use) existing solutions to known problems (on p. 823):
… even if you want to reinvent the wheel, you can’t count on success. You might reinvent the square instead.
It’s definitely not a Dave Barry kinda funny punch line, however it’s very much to-the-point.
I am working with AR for a few month now, ignorantly ignoring the Castle Project’s wiki.
Stupid I am. I could have learned a lot and save a bunch of wandering around the net and the intellisense to learn obvious stuff.
Thanks to hammett who pointed me there.
Anyway - now I read it from <html> to </html>, and I saw the part about running HQL using the Execute Callback
There are examples, each one with two flavors: “not using generics”, and “using generics”. Well, the one about the Execute Callback is misleading. It should have been “not using anonymous method” and “using anonymous methods”, since the second one does not use generics.
So I thought - let’s make the API simpler.
We would have like to allow the user execute her hql like that:
1: publicstatic Post[] GetPostsByAuthorName(string authorName)
2: {
3: return (Post[])Execute(typeof(Post), "from Post p where p.Author = ?", authorName);
4: }
Or even better, by using generics (this time for real):
1: publicstatic Post[] GetPostsByAuthorName(string authorName)
2: {
3: return Execute<Post>("from Post p where p.Author = ?", authorName);
4: }
Here is the magic:
1: publicstatic T[] Execute<T>(string hql, paramsobject[] parameters)
2: {
3: IList untypedResults = (IList)Execute(delegate(ISession session, object data)
4: {
5: object[] queryParams = (object[])data;
6: IQuery query = session.CreateQuery(hql);
7: for (int position = 0; position < queryParams.Length; ++position)
8: query.SetParameter(position, queryParams[position]);
9: return query.List();
10: }, parameters);
11: T[] results = new T[untypedResults.Count];
12: untypedResults.CopyTo(results, 0);
13: return results;
14: }
I’ll add an overload that will accept named parameters. I am not sure about the right way to do that, though.
My options are:
1: Execute<T>(string hql,
2: string[] paramNames,
3: Type[] paramTypes,
4: object[] parameters)
Or:
1: Execute<T>(string hql, IParameter[] parameters)
where IParameter definition is something like:
1: publicinterface IParameter<T>
2: where T: Type
3: {
4: publicstring Name { get; set;}
5: public T Value { get; set;}
6: }
Maybe both?
And maybe I haven’t read the wiki thoroughly enough and there are already implementations for all that?
WARNING:I’m going to use some lousy examples in this post. Please bear with me, and stick to the Point rather than to the actual Classes being presented.
What is a projection?
Consider this genius ERD:
A sample projection could be a kind of a view:
The SQL is (surprise!)
1: SELECT
2: p.Title as PostTitle, c.Content
3: FROM
4: Comments c INNER JOIN
5: Posts p ON c.PostId = p.Id
But we live in the Classes/Code/Compiler/Types/etc. domain, not the SQL domain, so I’d need a Post and a Comment classes that would derive from ActiveRecordBase<>. But what about the CommentsView? I can select into an array of objects using a simple HQL’s select:
1: IActiveRecordQuery query = new HqlBasedQuery(typeof(Job),
2: “select c.Post.Title, c.Content from Comment as c”); 3: 4: ArrayList report = ActiveRecordMediator.ExecuteQuery(query) as ArrayList; But I do not want to, since every item in the ArrayList is of type object[]. yuck.
No, I want to use a CommentView class, and this syntax:
1: IActiveRecordQuery query = new HqlBasedQuery(typeof(Job),
2: “select new CommentView(c.Post.Title, c.Content) from Comment as c”);
3:
4: ArrayList report = ActiveRecordMediator.ExecuteQuery(query) as ArrayList;
and now the ArrayList contains CommentView objects.
In order to achieve that, we need to use the peculiar named attribute, [Import] like that:
1: [Import(typeof(CommentView), "CommentView")]
2: [ActiveRecord("Comments")]
3: publicclass Comment : ActiveRecordBase<Comment> { /* blah blah */ }
Now ActiveRecord (assuming Comment class was initialized using ActiveRecordStarter) knows that CommentView refers to a projection of the Comment ActiveRecord, using the class CommentView.
The use of [Import] is not documented too well, so I’ve included ImportAttribute in the post’s title so It could be easily found. After a few refinements I hope to post it to the CastleProject wiki.
Note Ayende’s post, with some better example for projection, but it lacks the demonstration of using Import attribute, so that’s actually the reason for this post.
That’s for the “how you do that”.
now for the “How I think you should be able to do that”:
well, INHO, the Import attribute is poorly named.
The name of the Attribute makes no sense to me.The lack of default name makes no sense to me. I should be able to
1: [Import(typeof(CommentView))]
And what if I need some different projections to the same AR type? Multiple Import attributes make no sense, too.
Does the Import attribute serves a different purpose? If not – why not call it “Projects”? (since it projectsto some other classes)
like:
1: [Projects(typeof(CommentProjectionOrWhatever))]
2: publicclass Comment : ActiveRecordBase<Comment> { /* blah blah*/ }
or even better yet:
1: [Projects(
2: typeof(CommentProjectionOrWhatever),
3: typeof(YetAnotherCommentProjectionNeededForDemonstrationPurposesOnly )]
PROBLEM:When editing Monorail views, you are losing the XHTML intellisense that normal webforms have in Visual Studio.
SOLUTION:Add a proper xmlns to the html tag.My layouts start with this:
1: <?brail
2: output '<'
3: output '?xml version="1.0" encoding="utf-8"?'
4: output '>'
5: ?>
6: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
7: <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="he-il" lang="he" >
This applies to brail, but can of course be used on any other view engine, with the needed adjustments.
Lines 1-5 is needed due to a bug(?) in some versions of brail. brail used to recognize a script by ‘<? ?>’, ‘<?brail ?>’ and ‘<% %>’ signs. therefore, using a <?xml ?> declaration caused the boo compiler to say that he knows nothing about ‘xml’. I think that Ayende has solved the problem now, by allowing only ‘<?brail ?>’, but I think it’s not yet on the main trunk, so I still use the listed method.
Line 6 is the DOCTYPE, I use XHTML 1.0 transitional.
Line 7 is the magic part. Visual Studio parses this line, reads the xmlns, and can hint you with intellisense forhtml tags and attributes. The xml:lang and lang attributes are of course changeable.
It works in layouts, or in views that are a full html document (with <html> tag) but not with VieComponents or views that uses layouts.
If someone has a way to do that, please share it.
I’ve evaluated some methods to rail and to MVC in the .NET world, without using webforms.
The first method I tried was to treat aspx’s kind’a like old ASP, no server controls, allowing multiple forms, no __VIEWSTATE __EVANTVALIDATION __UGLYHIDDENFIELD in the generated markup, and calling actions on the server, implemented as Controllers over ashx’s, or directly linking to a new .aspx view (if no operation is required).It allowed me to create super clean html, but it has it’s limits, since I’ve had to implement a mechanism for MasterPages and UserControls, and that suck.There is BooWebness. Seams like a great effort, and I like the natural .ashx approach, but I am not very into its whole framework there.
Then I’ve went after MonoRail.Cool.Has a lot out-of-the-box, including MasterPages(Layouts), UserControls(ViewComponents), Markup Helpers, AjaxHelpers, and a large community. Being part of Castle is a Big Bonus. I believe in Castle. I’ve been using Castle’s ActiveRecord for a while and I find it almost too good to be true. So MonoRail fits well in Castle’s world, so I’m into it.
Now I needed to choose a view engine.NVelovity was disqualified for its discontinuesness, and the need to learn something new and narrow. Not to mention the fact that it’s interpreted.The WebForms hybrid just doesn’t look too good.Brail from Ayende is very nice. Learning Boo isn’t like learning a new thing, since I’ve had a little taste of it in the past, and since it’s .NET, and since it has a very readable syntax that any C#/VB.NET/Python/Perl/java/you-name-it developer can learn in minutes. Brail is a lovely name, and I can count on Ayende to keep developing it as much as it’s needed.
So Brail over MonoRail it is.
Posts about the matter will come shortly.
Should I use HtmlHelper?
take a look at this: ${HtmlHelper.Form(‘/Home/Search.rails’)} ${HtmlHelper.LabelFor(‘q’,’search:’)} ${HtmlHelper.InputText(‘q’, ‘’, 50, 50)} ${HtmlHelper.SubmitButton(‘Search’)} ${HtmlHelper.EndForm()} and that: <form method=”post” action=”Home/Search.rails”><label for=”q”>Search:</label><input type=”text” name=”q” /><input type=”submit” value=”Search” /></form> Okay. So AjaxHelper is cool, and maybe FormHelper will have someAdded Value in it, but I cannot figure out yet the benefits of using HtmlHelper, especially for non-data elements, such as <label>
If you have a good reason to use HtmlHelper, please enlight my.
I like XHTML more than I like HTML.
But IE doesn’t think so.
He needs the markup to be very explicit about the web page being xhtml.
.xhtml isn’t enough, and even not Doctype-ing.
No. he must have the optional <?xml version=”1.0” ?>.
So I’ve added it to my Layout.boo file.
Boo? Boom. Boo marks macros (such as <?brail ?>) with <? ?> blocks, and Boo doesn’t recognize a macro with the name xml.
My current solution is to write: <?brail output ‘<’ output ‘?xml version=”1.0” ?’output ‘>’ ?> I guess that adding a dummy xml macro would make the boo templates look nicer, but it is an ugly solution, and since (ugly & nice != nice), we need a better solution.
Maybe a change in Brail (on BrailPreProcessor.boo), to transform <?xml … ?> stuff to it’s “output” equiv, can be done.
The reference I’ve used whilelearning to use Castl’e ActiveRecord implementation is the Blog/Post demos that can be found on Castle’s site.
Let’s look at the Type Hierarchy example, that can be found here.
It shows an implementation of a class diagram that look a little bit like this:
Let’s look at the code : [ActiveRecord(“entity”), JoinedBase]publicclassEntity : ActiveRecordBase{privateint _id;[PrimaryKey]publicint Id{get { return id; }set { id = value; }}}[ActiveRecord(“entitycompany”)]publicclassCompanyEntity : Entity{privateint comp_id;[JoinedKey(“comp_id”)]publicint CompId{get { return comp_id; }set { comp_id = value; }}}[ActiveRecord(“entityperson”)]publicclassPersonEntity : Entity{privateint person_id;[JoinedKey(“person_id”)]publicint PersonId{get { return person_id; }set { person_id = value; }}} But look what happens. since the Id property on entity is public and inherited to the subclasses, you get something like this:
So there is a duplicate field here !!!. and it’s not only a getter-setter thingie. It also have different private members.
My solution for this is to virtualize the base Id, and protectedize (hehe) the _id member, like this:
[ActiveRecord(“entity”), JoinedBase]publicclassEntity : ActiveRecordBase{protectedint _id;[PrimaryKey]publicvirtualint Id{get { return id; }set { id = value; }}}[ActiveRecord(“entitycompany”)]publicclassCompanyEntity : Entity{[JoinedKey(“comp_id”)]publicoverrideint Id{get { return _id; }set { _id = value; }}}[ActiveRecord(“entityperson”)]publicclassPersonEntity : Entity{[JoinedKey(“person_id”)]publicoverrideint Id{get { return _id; }set { _id = value; }}} Now it makes more sence:
And before you hit me with a big stick - I do know of ActiveRecordBase<T> . :) the above code is for demonstration purposes only, not to be Copy&Pasted to your Brand-New-Best-Erp-Ever-Made-And-Will-Make-You-Rich
So after a lot of talking about the matter, I’m starting a little (but real) project with Castle’s ActiveRecord as an ORM service.
What I’m still not sure about, is weather I should inherit everything from ActiveRecordBase, or have my own base class and use ActiveRecordMediator?
Sure, I can derive my base class from ActiveRecordBase and have common behaviour for my model, but I am still not sure that I’m fully into the ActiveRecord pattern as a whole. It’s tempting to exploit Castle’s implementation but to keep the methods in a seperate class rather than in the model itself.
I also have some problem with the need to do FindAll, Find, etc. on each class so to expose the static methods in a typed way.
Well, I take back the last paragraph, since Icould use ActiveRecordBase<> and it solves this problem.
To conclude: I tend to go with subclassing ActiveRecordBase<> as a base class for my model, and I’m starting to code (and test) that way,but I could still use the knowledge gained by people with real experience withthis implementation…
I’ve looked for insights on the matter on the web, and have found nothing.If anyone reading this has an insight about the matter, please comment here, so people who do their first steps in Castle’s ActiveRecord implementation would have a better kick start regarding this issue.
I’ll post here links for stuff that I find usefull, for people who are doing their first steps in the Castle’s ActiveRecord’s world.
This post is to be updated while finding more resources.
Note that this is not a replacement for the official ducomentation that can be found on Castle’s website, but merely a place to do the beginner’s life somewhat easier.
Posts by Hamilton hammett Verissimo, who is the engine behind the whole story:http://geekswithblogs.net/hammett/articles/76697.aspxhttp://geekswithblogs.net/hammett/articles/76809.aspxmake sure that you are following his blog.
An article by Ayende about using Generics with ActiveRecord:[http://www.castleproject.org/index.php/ActiveRecord,.Net_2.0_and_Generics](http://www.castleproject.org/index.php/ActiveRecord,.Net_2.0_and_Generics)as before - stay tuned to Ayende’s blog for he very experienced in ActiveRecord and in NHibernate too, for the matter. He is also avery readablewriter.