The new thing in MS web development is Razor, which at its base a templating engine.
It would be really cool if:
These things would allow using it as a true templating engine, which then can be embedded as a view engine for other web frameworks (like Monorail and Fubu, and more), use it for off-line email templates processing, maybe even for emitting customised setting files for automated deployment scenarios.
I need to try and explore into there and sniff around.
Microsoft free Web Camps around the globe
The bug: Weird behaviours regarding session management
The blame: (within session access wrapper static class):
private static IDictionary session;
...
if (session == null)   session = new SessionAdapter(HttpContext.Current.Session);
...
so the first time the last line is called, the then-current-session is stored in a static variable, thus the first session is always referenced even for newer sessions.
The reason for the above code being present in the first place is that:
public static void SetSessionTo(IDictionary newSession)
{
session = newSession;
}
So that tests that a stubbed ‘session’ could have been injected into the session-wrapper-static-class thingie.
Clearly, the implementation was wrong.
The fix: now the code looks like this:
private static IDictionary stubbedSession;
static IDictionary Session
{
get { return stubbedSession ?? MonoRailHttpHandler.CurrentContext.Session; }
}
And these were 60 seconds on careless coding.
Ken, the careless coder
Following my post on key-level locked cache, I got the following piece of code from my friend Moran Benisty, implementing the same idea over XmlDocuments which is being loaded over the Internet, and ASP.NET’s Cache.
This is a real life code. He’s using it on a very large-scale website in production.
As usual - use at your own risk, and be kind enough to share thoughts and improvement ideas here for his use.
public static class XmlService
{
private static Dictionary _locks = new Dictionary();
public static XmlDocument GetXml(string url)
{
return GetXml(url, new TimeSpan(1, 0, 0), false);
}
public static XmlDocument GetXml(string url, TimeSpan timeToHold, bool autoRefresh)
{
if (HttpRuntime.Cache[url] as string == "Failed")
return null;
XmlDocument xml = HttpRuntime.Cache[url] as XmlDocument;
if (xml != null)
return xml;
if (!_locks.ContainsKey(url))
lock (_locks)
if (!_locks.ContainsKey(url))
_locks.Add(url, new object());
if (HttpRuntime.Cache[url] == null)
lock (_locks[url])
if (HttpRuntime.Cache[url] == null)
{
xml = LoadXml(url);
if (xml != null)
HttpRuntime.Cache.Insert(url, xml, null,
DateTime.Now.Add(timeToHold),
System.Web.Caching.Cache.NoSlidingExpiration,
System.Web.Caching.CacheItemPriority.NotRemovable,
delegate(string dataKey, object value, CacheItemRemovedReason reason)
{
if (autoRefresh)
GetXml(url, timeToHold, autoRefresh);
}
);
else
HttpRuntime.Cache.Insert(url, "Failed", null, DateTime.Now.AddMinutes(5), System.Web.Caching.Cache.NoSlidingExpiration);
}
xml = HttpRuntime.Cache[url] as XmlDocument;
return xml;
}
private static readonly ILog _errorlog = LogManager.GetLogger("ErrorLogger");
private static XmlDocument LoadXml(string url)
{
try
{
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(url);
request.Timeout = 3000;
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
XmlDocument xml = new XmlDocument();
xml.Load(response.GetResponseStream());
return xml;
}
catch (Exception ex)
{
_errorlog.Error(ex.Message, ex);
return null;
}
}
}
I’d have switched XmlService with KeyLevelCacheService, XmlDocument with T, and LoadXml with Func<T>, then have a separate XmlService use KeyLevelCacheService internally.
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
It seam like every one (now including me) is posting excitingly about the new preview of ASP.NET MVC.
Probably to get traffic or whadever.
Most of those goes like “I usually do not do this, but hey- here’s the link”.
Justice Gray’s post is different.
btw, as you are all excited about it, I’d use that to point you to something quite similar, more mature, that lets you “easily build MVC based applications in ASP.NET with routing, intellisense, and total joy, not to mention that it runs on .NET 2.0 “ - that would be the MonoRail thing, preferably (by me and a few others) accompanied by AspView.
And since I didn’t put the MVC p2 link here, I won’t link to MonoRail and AspView. After all, if you’re reading this, you probably have those links in your favorites …
Reading this post from Phil Haack made me jump a little. Oh no, I said, Please don’t let the clean IMvcFramework become clumsy.
Ayende has ranted about it better than I would.
Now I see that Phil has issues with ABC as well.
The answers for the ABC problems he shows there are cumbersome. In order to gain “flexibility”, you end up polluting your API with “CanSupportCrap” methods, etc.
So, to recap:
Please Please Please keep IHttpContext in place …
This weekend I’ve had to pleasure to attend the altnetuk conf in London. This has been quite an amazing experience. I have really liked the way it has ben organized into open-spaces, and I just wish I could’ve split myself to four, so I’d be able to be at all of the sessions (the F# one was greatly missed …)
I have met great people, have discussed exciting things, and had a lot of fun.
Most of the people referred to me as “the MonoRail guy” which was quite amusing, as I am only the creator of AspView (which in turn is a shameless idea-and-code ripoff from Brail), and I have very little to do with the actuall coolness and usefulness of MonoRail … I do hope though that I did manage to address pepole concerns regarding MonoRail, and the Castle Project as a whole.
Interesting (however not surprising) moment:
On the panel dealing with MVC frameworks for ASP.NET, about 25 people were around the table. When people who are actually using MonoRail/ASP.NET MVC for commercial production environment, only 4 have raised their hands. however, all the others said that they wish the could have done that, and the only reason they do not, is the reluctance from their bosses/clients.
After being told that MonoRail would not make his dreams come true, Dylan Beattie have answered:
“MonoRail would not make my dreams come true. It would however, make my nightmares disappear”
Brilliant.
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 got frustrated with the fact that I have no intellisense (nor compile time check) for locating static files like .js, .css and image files.
So I sat up and created a simple console application that can generate exactly that, out of the site’s filesystem.
usage:
D:\MyTools\StaticMapGenerator /site:D:\Dev\MySite
it generates a file called Static.Site.Generated.cs within the site’s root folder, and then I go and include that file in my web project.
No I can do stuff like:
<script type="text/javascript" src="<%= Static.Site.Include.Scripts.myscript_js %>"> </script><link rel="stylesheet" href="<%= Static.Site.Include.CSS.master_css %>" /><img alt="Ken Egozi" title="My Logo" src="<%= Static.Site.Include.Images.Logos.my_logo_png" />
How cool is that?
It works in every ASP.NET compatible web framework (MonoRail, ASP.NET MVC, even WebForms …)
The only prequisite is .NET 2.0 runtime.
Sorry for keeping it out of reach for the moment. I need a little bit of time to setup a svn repository to make the source public (it would of course be BSD/Apache2/MIT thing) and to upload a binary. No promises given, I’ll try to make it in the coming weekend, or even tonight, so stay tuned.
The code is somewhat naive, and certainly does not cover any edge cases, however it’s enough to work cleanly on the largest project I’m currently involved in (Music Glue). Patches to make it more configurable and able to handle more edge cases would be gladly accepted once it’s out.
One cool spot - as part of this, I have also implemented my tiny IoC container in 33 LoC.
Well, According to Scott Gu we’d be able to download the binaries Next Week,
I can’t wait to put my hands on that, and start finding the possibilities of this framework in conjunction with MonoRail.
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.
Now that the Big Boys do actually listening to the community, and gives a shot at a solid MVC web framework is a Good Think.
I would really like to see that in action, and would really like to see how they are coming up with stuff that are more than just url->action wiring, such as parameter bindings, view-components, etc.
It’s going to be interesting, and MonoRail (and) might need some boost to keep being the (imho) no. 1 choice for Web MVC in .NET
It would be interesting also to see where would AspView fit in the new playground.
btw, would that be part of .NET 4.2?
Anyway, since it might take some time to get this new stuff on a production level, I do not believe that no one that works on production system (or those that are supposed to be at production during the coming year) should ditch MR. Even when it’d be out, I might consider MR as a better solution as it’s Open Source, therefore more self twickable, and a lot more responsive in terms of bugfixes.
Another nice news from Scott Guthrie:
a small excerpt:
Today I’m excited to announce that we’ll be providing this with the .NET 3.5 and VS 2008 release later this year.
Following that thread from Castle Project’s user group, I’m writing that down as to remember that.
Notice that an ASP.NET application mat spawn more than one HttpApplication object. That is, to keep HttpApplication thread safe, thus providing each thread it’s own instance. Now the Start event may fire only during the (logical) application start, rather than on each instance start. Therefore, if you want to hook events, you’d want to do that on the application’s Init event, that would get called for each HttpApplication instance.
So you say “Hey Ken, that’s not fair. Ranting about the bad performance tipsisn’t good enough. We want GOOD tips”.
I won’t say that those are necessarily GOOD tips, however they are probably BETTER.
without further ado, I’ll quickly pull out of my hat my somewhat better tips:
Learn to use caching, both for dynamic and static content.
TURN OFF ViewState (and ControlState). Find better solutions. Really. You do not need the viewstate to get txtName.Text. Just use the damn Form[“txtName”], or writeTypeSafe wrapper around the Form (or Request.Items) collection.
Learn SQL.
Use caching.
ADD Client-side validation to the Server side validation. DO NOT remove server side validation, as every javascript beginner can bypass client-side stuff.
Avoid SELECT+N.
Cache responses where appropriate.
Have as least external files as you can. Join all .js to one file. join all .css to one file. It takes a LOT more time for the browser to open a connection to the server, that to actually get those lousy extra 5k. And out-of-the-box, browsers can have a maximum of 2 connections to the server at once.
Cache DB queries when appropriate
Enable GZip on IIS
Use the “COUNT” keyword in SQL, rather than the”Count” or “Length” .NET properties
Did I mention caching?
Avoid Page where it can be replaced with an IHttpHandler. That code is BAD:
public class SomePage : System.Web.UI.Page{ protected void Page_Load(object sender, EventArgs e) { Response.Clear(); Response.Write(something); }}
Wow.
Take a look at that tip sheet.
Are these guys serious?
Best quotes:
3. Avoid Server-Side ValidationTry to avoid server-side validation, use client-side instead. Server-Side will just consume valuable resources on your servers, and cause more chat back and forth.
huh?
12. Caching is Possibly the number one tip!Use Quick Page Caching and the ASP.net Cache API! Lots to learn, its not as simple as you might think. There is a lot of strategy involved here. When do you cache? what do you cache?
if it’s no. one tip (and it is), why is it numbered 12?
20. Option Strict and Option ExplicitThis is an oldy, and not so much a strictly ASP.net tip, but a .net tip in general. Make sure you turn BOTH on. you should never trust .net or any compiler to perform conversions for you. That’s just shady programming, and low quality code anyway. If you have never turned both on, go turn them on right now and try and compile. Fix all your errors.
what’s that has to do with performance?
I just can’t believe that CodeProject has linked to that article.
Actually, it’s not much of a challenge, but it is a catchy title.
Or is it?
Anyway, that’s the details:
I’d kindly ask all of you ASP.NET Ajax wiz guys (and gals), to supply me with a simple UpdatePanel thing.
What should it do?
I want to have a webpage, based onthis template, that on dropdown change, will go to the server with the selected value in the dropdown, and update the data (table) with some crap, based on the sent value.
You can leave the actual data retrieval to a simple method returning an array of string array, or you can go and implement a CodeSmith/DAAB/Whatever based supercool data access code. I would ignore it anyway. I want the Ajax stuff.
Now, to the why.
I am doing that MonoRail presentation at Microsoft’s Israel IVCUG (Israel Visual C(#/++) User Group) next week. I might be showing some demos, and I want to be fare when I show a comparison to WebForms stuff, and not come up with a crappy code and say “ha ha”, but show something that one of you, my-dear-readers-who-actually-uses-asp-net-ajax-for-living, wrote, and is considered a good example.
Also, I’m lazy. Seriously. Creating a presentation takes a LOT of time and effort, and I do not have much of the first, and rather avoid much of the later.
So, please do send me that code, to my-first-name at that-blog’s-hostname.
thanks.
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.
TodayI was informed by Dror that although I managed to redirect all requests to html/aspx url’s on my blog (the ones that dagBlog was using) to the new pemalink format, I forgot to do the same for the old syndication link.
So that link was http://kenegozi.com/blog/SyndicationService.asmx/GetRssand now it’s http://kenegozi.com/Blog/Syndication/Atom.aspx
I could’ve used the monorai redirection module that is already in use on my blog, but I chose to do it differently, with a dedicated handler, just to show how easy it is do to such stuff, even without a full blown redirection engine.
So, I’ve added this:
publicclassSyndicationRedirectionHandler : IHttpHandler
{
#region IHttpHandler Members
publicbool IsReusable
{
get { returntrue;}
}
publicvoid ProcessRequest(HttpContext context)
{
context.Response.StatusCode = 301;
context.Response.Redirect("http://kenegozi.com/Blog/Syndication/Atom.aspx");
}
#endregion
}
and that line into web.config:
<addverb=”*“path=”SyndicationService.asmx”type=”KenEgozi.Com.Weblog.SyndicationRedirectionHandler, KenEgozi.Com.Weblog”/>
Voila.
Today we tried to have this in a view’s parameters section:
<%
int id = default(int);
%>
It won’t work.
Internally, AspView looks for a parameter (in the PropertyBag, Flash, Form, QueryString etc.) with the name “id”.
Now if it is not found, it should set to “default(int)”. The problem is duw to a bug in AspViewBase (which is the base class for all views) that sets a null value if the property is not found, thus failing the cast to value type (you cannot (int)null).
I’ll add a test, fix the bug, and commit it, hopefully by this weekend.
Meanwhile, we “solved” the problem by using:
<%
object id = default(int);
%>
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’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?
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.
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.
There is a nice post about naming the Atlas package, at http://aspadvice.com/blogs/ssmith/archive/2006/08/16/Atlas_Naming_Game.aspx
There are some funny comments there, so do not miss.
And that is my comment:
“I think that too descriptive names suck.
I’d go with any non-descriptive name, such as the ones MS uses as codenames (I loved Avalon and so on).I believe that from the marketing point of view, non-descriptive catchy names ar far better than the others.It’s like dice.com and monster.com doesn’t include “job” in their name.
But since MS are determined to use descriptive names, at least they should concentrate on the “what” and not on the “how”.so “Async XmlHttp Enabled Web Apps” (AXEWA ?) is bad, while “Dynamic Web Browsing” is better.”
Scott Guthrie has recently posted this. He is pointing out to a few dozens of posts about ASP.NET 2.0.
The stuff there ranges from UI tweaks, security, performance, VS2005 tips and more.
A “must be in the favorites or even as a desktop shortcut preferably with keyboard shortcut too” for everyone who deals with ASP.NET developing.
If you’re into automated generation of data manipulation UI, then you must check out BLinq, written by Polita Paulus of Microsoft, at http://www.asp.net/sandbox/app_blinq.aspx?tabid=62
In short, it uses DLinq to generate a DAL, and then builds simple ASP.NET pages using GridView and DetailsView Controls (developed by Polita herself), to manipulate all of the tables from the database.
In my opinion, it serves as a great prove of concept for the whole ASP.NET and Linq technologies, as the fastest RAD tool for web application development.
Just build a database, and in an eye Blinq, you have a way to manipulate it through web app.
I find it great. Aren’t you?
The web application that we’re working on now, uses ASP.NET 2.0’s ObjectDataSource model, to bind to GridView and FormView in the front-end.Starting off, I’ve made a hierarchy of base classes to manage the data-binding and visual behaviors for Entity Pages (used to view, edit or insert a single entity) and Master-Details Pages (used to manage Master-Details scenarios).The base classes looked like:
class BasePage : Page { /* ... */ }class BaseEntityPage<T> : BasePagewhere T: Entity{public BaseEntityPage(){/// hook ObjectDataSource and FromView databind events}//... }class BaseMasterDetailsPage<T> : BaseEntityPage<T>where T: Entity{public BaseMasterDetailsPage() : base(){/// hook GridView databind events}//... }
Somewhere along the road, we’ve decided to change the first module being developed, to use ascx controls in a single page, instead of multiple pages in a master page (due to the fact that it became a nested master page, and vs2005 doesn’t like it).So, a developer working on the change from Pages to UserControls, changed the base class to something like that:
class BaseUserControl : UserControl { /*...*/ }class BaseEntityUserControl<T> : BaseUserControlwhere T: Entity{public BaseEntityUserControl(){/// hook ObjectDataSource and FromView databind events}//... }class BaseMasterDetailsUserControl<T> : BaseEntityUserControl<T>where T: Entity{public BaseMasterDetailsUserControl() : base(){/// hook GridView databind events}//... }
Later on, we needed some standalone pages (not “mastered”) to have data capabilities.We already had the databinding for UserControls, but now we would need to create empty “dummy” pages and host UserControls in them, which means that instead of aspx + aspx.cs files per page, we’ll have aspx + aspx.cs + ascx + ascx.cs files !!!We could always keep the BasePage hierarchy next to the BaseControl hierarchy, but it will create an ugly duplication.If Multi-Inheritance was possible, we would have used something like:
class EntityController { /* ... */ }class BaseEntityPage<T> : BasePage, EntityController { /* ... */ }class BaseEntityUserControl<T> : BaseUserControl, EntityController { /* ... */ }
The solution is to use an external controller, we’ll call the Manager, to do all the recurrent login that applies to both the Pages an the UserControls.We’ll use an EntityManager that will manage both BaseEntityPages and BaseEntitycontrols, and a MasterDetailsManager that will manage BaseMasterDetailsPages and BaseMasterDetailsControls. Each and every page and UserControl will register itself with a manager.Now the base class look like that:
class EntityManager<T> {}class MasterDetailsManager<T> : EntityManager<T> { }class BaseEntityPage<T> : BasePagewhere T: Entity{private EntityManager<T> manager;public BaseEntityPage(){manager =new EntityManager<T>(this);}//... }class BaseMasterDetailsPage<T> : BaseEntityPage<T>where T: Entity{public BaseMasterDetailsPage() // not calling base() cuz we need a different manager{manager =new MasterDetailsManager<T>(this);}//... }class BaseEntityUserControl<T> : BaseUserControlwhere T: Entity{private EntityManager manager;public BaseEntityUserControl (){manager =new EntityManager<T>(this);}//... }class BaseMasterDetailsUserControl<T> : BaseEntityUserControl<T>where T: Entity{public BaseMasterDetailsUserControl () // not calling base() cuz we need a different manager{manager =new MasterDetailsManager<T>(this);}//... }
All the databinding logic and visual behavior control, is now placed in the managers classes, and the page or control itself, is only dealing with the things that are specifically needed by it.The developers on the team, when creating a new page or UserControl, only need to register their page or control to the appropriate manager, and not to mind all the databinding and behavior stuff.
Some annoying problem I’ve encountered lately.While developing on my XP machine, I have had some ASP.NET 1.1 applications and ASP.NET 2.0 applications running side-by-side, as virtual directories on the single website allowed by IIS5.1
When I’ve published an ASP.NET 2.0 application to a production server, running IIS6.0 (on Windows 2003 Server) with already installed ASP.NET 1.1 applications, I’ve found out that if the old applications are running, the new one returns “Server Application Unavailable”, and vice versa.A quick search in the Event Viewer revealed that IIS isn’t fond of running applications of different ,NET runtime version, in the same process. Quite reasonable that is, yet annoying.
That’s when I remembered that I’ve always said to myself that I should look into the reason that IIS5.0 and IIS5.1 runs each ASP.NET application in a aspnet_wp.exe worker process, while IIS6.0 uses a single w3wp.exe worker process.
A little web search and I’ve found this: http://technet2.microsoft.com/WindowsServer/en/Library/d0a61f24-942e-4379-adad-8232be03441c1033.mspx, and adjacent pages.
So this is a new feature of ASP.NET, that makes it possible to run a few applications in the same process. Every few applications (virtual directories) are assigned to an application pool, and each application pool runs in its own process.There are a few settings that can be done for each application pool. Those settings are overriding the defaults in the machine.config file.
Adding an application pool is done through inetmgr.msc, by just adding a new pool to the Application Pools section. Use the option to copy settings from the default application pool, so you’d have a decent place to start from:
Assigning a pool to an application is done through the main property page of the application’s virtual directory:
The solution to our problem is now obvious:When configuring a new IIS6.0 server, we will start with an application pool for each ASP.NET version we’re using (1.0, 1.1, 2.0), and any virtual directory we setup in the server will be configured to be part of the corresponding application pool. Now the applications can coexist and run together.
Enough with server configuration stuff. Now go back to coding.
Ken.
Well, Here’s my first hopfully useful post in my blog.
The problem:
pdb files of projects and assemblies being referenced by a web application, somtimes become “source controlled” when using VS 2005 and VSS. This is leading to the pdbs and even dlls to become readonly, and therefore the break of a succesful post-build events, such as copying newly compiled dlls to the web application’s Bin directory, hence unexpected behavior of the application.
The “Why the heck this is happening”:
Using VS 2005 to develop ASP.NET 2.0 applications is somewhat different than in the good old VS 2003.
The main difference is caused by the missing project file.
As opposed to VS 2003, which compiled the cs (and vb) files of a web project using csc.exe (and vbc.exe), as with regular (not web) projects, things are different with VS 2005 web projects.
In order to allow on the fly compile of source files (codebehinds and App_Code files), and on the other hand, to allow a precompilation ofthe whole project (including aspx, ascxand other “non code” files), the framework has provided us with a special compiler, named aspnet_compiler.exe
allowing a full “automated” compiled outside of any IDE, requires disrelying on an IDE specific file, such as the csproj/vbproj files, therefore, everything in (and under) the application’s directory considered to be a part of the project.
In VS 2003 the compiler knew about referenced dlls and projects from the csproj/vbproj file. Now referenced dlls are known throuh a .refresh file in the Bin directory, that points to the location of the dll, and referenced project files are written to a special section in the web.config.
Controlling the source manually using VSS interface is possible, yet you have to manually remember not to check in items from the Bin directory, except the .refresh files.
The VSS integretion in VS 2005 is trying to outsmart the problem. it assumes that if a .refrsh file exists in the Bin directory, then the file it references is not to be source controlled. For example: if the Bin directory contains a file names MyAssembly.dll.refresh, then if it also contains a file names MyAssembly.dll (and it will, after a succesfull build), it won’t treat it as source controlled.
It also understands that if a file is there, due to a build action, it is also marked so it won’t besource controlled.
But, if you build you solution in Debug configuration,now you have pdb files in the Bin directory. let’s say that you do a Release Build, that does not create and copy pdb files. now the existing pdb files in the Bin directory are not marked, and the VSS integration will sense that there are new files in the Bin, that have no .refresh file, andwas not created during the last Build event, so it will mark them as Check InPending files !!!
The “Gosh it’s Ugly solution”:
You need to:1.Rebuild the solution in Debug configuration2. Close and Reopen the project.
If you’ve already accidently Checked In the pdb files, you need to:1. Manually delete them from the VSS.2. Manually set their readonly attribute to false.3.Rebuild the solution in Debug configuration4. Close and Reopen the project.
The place where i’ve found this solution: http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=106422&SiteID=1
So until next time, keep on with the good coding thing you’ve beendoing while you’ve start reading this post.
Ken