personal comments edit

Every good developer knows to always have a backup. For example, over two years ago, I announced my world domination plans. But there was a single point of failure in me putting all my world domination plans on the tiny shoulders of just one progeny. My boy needs a partner in crime.

mia So my wife and I conspired together and we’re happy to announce that baby #2 is on the way. Together, the two of them will be unstoppable!

My wife is past her first trimester and we expect the baby to RTF (Release To Family) around October.

This second time around has been a bit more challenging. My poor wife, bless her heart, has had to deal with much more sever nausea this time around.

Notice the crinkle in the ultrasound photo. My son did that. ;) He’s trying to destroy the evidence.

Many of you who have more than one children might be able to relate to this, but I really considered not writing a blog announcement for my second child. There was the feeling that it was such a novel thing the first time, but now it’s becoming old hat (not really!).

But then I mentally fast forwarded 16 years later and pictured my future daughter finding the firstborn announcement and not finding her own blog announcement. Try explaining that to a kid. I can deal without the drama.

Well I won’t have to! Hi honey, here’s your announcement. Now you be good while daddy goes shopping for a shotgun and a shovel. :)

asp.net, asp.net mvc comments edit

There are a couple of peculiarities worth understanding when dealing with title tags and master pages within Web Forms and ASP.NET MVC. These assume you are using the HtmlHead control, aka <head runat="server" />.

The first peculiarity involves a common approach where one puts a ContentPlaceHolder inside of a title tag like we do with the default template in ASP.NET MVC:

<%@ Master ... %>
<html>
<head runat="server">
  <title>
    <asp:ContentPlaceHolder ID="titleContent" runat="server" />
  </title>
</head>
...

What’s nice about this approach is you can set the title tag from within any content page.

<asp:Content ContentPlaceHolderID="titleContent" runat="server">
  Home
</asp:Content>

But what happens if you want to set part of the title from within the master page. For example, you might want the title of every page to end with a suffix, “ – MySite”.

If you try this (notice the – MySite tacked on):

<%@ Master ... %>
<html>
<head runat="server">
  <title>
    <asp:ContentPlaceHolder ID="titleContent" runat="server" /> - MySite
  </title>
</head>
...

And run the page, you’ll find that the – MySite is not rendered. This appears to be a quirk of the HtmlHead control. This is because the title tag within the HtmlHead control is now itself a control. This will be familiar to those who understand how the AddParsedSubObject method works. Effectively, the only content allowed within the body of the HtmlHead control are other controls.

The fix is pretty simple. Add your text to a LiteralControl like so.

<%@ Master ... %>
<html>
<head runat="server">
  <title>
    <asp:ContentPlaceHolder ID="titleContent" runat="server" /> 
    <asp:LiteralControl runat="server" Text=" - MySite" />
  </title>
</head>
...

The second peculiarityhas to do with how the HeaderControl really wants to produce valid HTML markup.

If you leave the <head runat="server"></head> tag empty, and then view source at the rendered output, you’ll notice that it renders an empty <title> tag for you. It looked at its child controls collection and saw that it didn’t contain an HtmlTitle control so it rendered one for you.

This can cause problems when attempting to use a ContentPlaceHolder to render the title tag for you. For example, a common layout I’ve seen is the following.

<%@ Master ... %>
<html>
<head runat="server">
  <asp:ContentPlaceHolder ID="headContent" runat="server"> 
    <title>Testing</title>  
  </asp:ContentPlaceHolder>
</head>
...

This approach is neat because it allows you to not only set the title tag from within any content page, but any other content you want within the <head> tag.

However, if you view source on the rendered output, you’ll see two <title> tags, one that you specified and one that’s empty.

Going back to what wrote earlier, the reason becomes apparent. The HtmlHead control checks to see if it contains a child title control. When it doesn’t find one, it renders an empty one. However, it doesn’t look within the content placeholders defined within it to see if they’ve rendered a title tag.

This makes sense when you consider how the HtmlHead tag works. It only allows placing controls inside of it. However, a ContentPlaceHolder allows adding literal text in there. So while it looks the same, the title tag within the ContentPlaceHolder is not an HtmlTitle control. It’s just some text, and the HtmlHead control doesn’t want to parse all the rendered text from its children.

This is why I tend to take the following approach with my own master pages.

<%@ Master ... %>
<html>
<head runat="server">
  <title><asp:ContentPlaceHolder ID="titleContent" runat="server" /></title>
  <asp:ContentPlaceHolder ID="headContent" runat="server"> 
  </asp:ContentPlaceHolder>
</head>
...

Happy Titling!

asp.net comments edit

In my last blog post, I walked step by step through a Cross-site request forgery (CSRF) attack against an ASP.NET MVC web application. This attack is the result of how browsers handle cookies and cross domain form posts and is not specific to any one web platform. Many web platforms thus include their own mitigations to the problem.

It might seem that if you’re using Web Forms, you’re automatically safe from this attack. While Web Forms has many mitigations turned on by default, it turns out that it does not automatically protect your site against this specific form of attack.

In the same sample bank transfer application I provided in the last post, I also included an example written using Web Forms which demonstrates the CSRF attack. After you log in to the site, you can navigate to /BankWebForm/default.aspx to try out the Web Form version of the transfer money page. it works just like the MVC version.

To simulate the attack, make sure you are running the sample application locally and make sure you are logged in and then click on https://haacked.com/demos/csrf-webform.html.

Here’s the code for that page:

<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
    <title></title>
</head>
<body>
  <form name="badform" method="post"
    action="http://localhost:54607/BankWebForm/Default.aspx">
    <input type="hidden" name="ctl00$MainContent$amountTextBox"
      value="1000" />
    <input type="hidden" name="ctl00$MainContent$destinationAccountDropDown"
      value="2" />
    <input type="hidden" name="ctl00$MainContent$submitButton"
      value="Transfer" />
    <input type="hidden" name="__EVENTTARGET" id="__EVENTTARGET"
      value="" />
    <input type="hidden" name="__EVENTARGUMENT" id="__EVENTARGUMENT"
      value="" />
    <input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE"
      value="/wEP...0ws8kIw=" />
    <input type="hidden" name="__EVENTVALIDATION" id="__EVENTVALIDATION"
      value="/wEWBwK...+FaB85Nc" />
    </form>
    <script type="text/javascript">
        document.badform.submit();
    </script>
</body>
</html>

It’s a bit more involved, but it does the trick. It mocks up all the proper hidden fields required to execute a bank transfer on my silly demo site.

The mitigation for this attack is pretty simple and described thoroughly in this this article by Dino Esposito as well as this post by Scott Hanselman. The change I made to my code behind based on Dino’s recommendation is the following:

protected override void OnInit(EventArgs e) {
  ViewStateUserKey = Session.SessionID;
  base.OnInit(e);
}

With this change in place, the CSRF attack I put in place no longer works.

When you go to a real bank site, you’ll learn they have all sorts of protections in place above and beyond what I described here. Hopefully this post and the previous one provided some insight into why they do all the things they do. :)

Technorati Tags: asp.net,security

asp.net, code, asp.net mvc comments edit

A Cross-site request forgery attack, also known as CSRF or XSRF (pronounced sea-surf) is the less well known, but equally dangerous, cousin of the Cross Site Scripting (XSS) attack. Yeah, they come from a rough family.

CSRF is a form of confused deputy attack. Imagine you’re a malcontent who wants to harm another person in a maximum security jail. You’re probably going to have a tough time reaching that person due to your lack of proper credentials. A potentially easier approach to accomplish your misdeed is to confuse a deputy to misuse his authority to commit the dastardly act on your behalf. That’s a much more effective strategy for causing mayhem!

In the case of a CSRF attack, the confused deputy is your browser. After logging into a typical website, the website will issue your browser an authentication token within a cookie. Each subsequent request to sends the cookie back to the site to let the site know that you are authorized to take whatever action you’re taking.

Suppose you visit a malicious website soon after visiting your bank website. Your session on the previous site might still be valid (though most bank websites guard against this carefully). Thus, visiting a carefully crafted malicious website (perhaps you clicked on a spam link) could cause a form post to the previous website. Your browser would send the authentication cookie back to that site and appear to be making a request on your behalf, even though you did not intend to do so.

Let’s take a look at a concrete example to make this clear. This example is the same one I demonstrated as part of my ASP.NET MVC Ninjas on Fire Black Belt Tips talk at Mix in Las Vegas. Feel free to download the source for this sample and follow along.

Here’s a simple banking website I wrote. If your banking site looks like this one, I recommend running away.

banking-login-pageThe site properly blocks anonymous users from taking any action. You can see that in the code for the controller:

[Authorize]
public class HomeController : Controller
{
  //...
}

Notice that we use the AuthorizeAttribute on the controller (without specifying any roles) to specify that all actions of this controller require the user to be authentication.

After logging in, we get a simple form that allows us to transfer money to another account in the bank. Note that for the sake of the demo, I’ve included an information disclosure vulnerability by allowing you to see the balance for other bank members. ;)

bank-transfer-screen

To transfer money to my Bookie, for example, I can enter an amount of $1000, select the Bookie account, and then click Transfer. The following shows the HTTP POST that is sent to the website (slightly edited for brevity):

POST /Home/Transfer HTTP/1.1
Referer: http://localhost:54607/csrf-mvc.html
User-Agent: ...
Content-Type: application/x-www-form-urlencoded
Host: 127.0.0.1:54607
Content-Length: 34
Cookie: .ASPXAUTH=98A250...03BB37

Amount=1000&destinationAccountId=3

There are three important things to notice here. We are posting to a well known URL, /Home/Transfer, we are sending a cookie, .ASPXAUTH, which lets the site know we are already logged in, and we are posting some data (Amount=1000&destinationAccountId=3), namely the amount we want to transfer and the account id we want to transfer to. Let’s briefly look at the code that executes the transfer.

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Transfer(int destinationAccountId, double amount) {
  string username = User.Identity.Name;
  Account source = _context.Accounts.First(a => a.Username == username);
  Account destination = _context.Accounts.FirstOrDefault(
    a => a.Id == destinationAccountId);
            
  source.Balance -= amount;
  destination.Balance += amount;
  _context.SubmitChanges();
  return RedirectToAction("Index");
}

Disclaimer: Do not write code like this. This code is for demonstration purposes only. For example, I don’t ensure that amount non-negative, which means you can enter a negative value to transfer money from another account. Like I said, if you see a bank website like this, run!

The code is straightforward. We simply transfer money from one account to another. At this point, everything looks fine. We’re making sure the user is logged in before we transfer money. And we are making sure that this method can only be called from a POST request and not a GET request (this last point is important. Never allow changes to data via a GET request).So what could go wrong?

Well BadGuy, another bank user has an idea. He sets up a website that has a page with the following code:

<html>
<head>
    <title></title>
</head>
<body>
    <form name="badform" method="post"
     action="http://localhost:54607/Home/Transfer">
        <input type="hidden" name="destinationAccountId" value="2" />
        <input type="hidden" name="amount" value="1000" />
    </form>
    <script type="text/javascript">
        document.badform.submit();
    </script>
</body>
</html>

What he’s done here is create an HTML page that replicates the fields in bank transfer form as hidden inputs and then runs some JavaScript to submit the form. The form has its action set to post to the bank’s URL.

When you visit this page it makes a form post back to the bank site. If you want to try this out, I am hosting this HTML here. You have to make sure the website sample code is running on your machine before you click that link to see it working.

Let’s look at the contents of that form post.

POST /Home/Transfer HTTP/1.1
Referer: https://haacked.com/demos/csrf-mvc.html
User-Agent: ...
Content-Type: application/x-www-form-urlencoded
Host: 127.0.0.1:54607
Content-Length: 34
Cookie: .ASPXAUTH=98A250...03BB37

Amount=1000&destinationAccountId=2

It looks exactly the same as the one before, except the Referer is different. When the unsuspecting bank user visited the bad guy’s website, it recreated a form post to transfer funds, and the browser unwittingly sent the still active session cookie containing the user’s authentication information.

The end result is that I’m out of $1000 and BadGuy has his bank account increased by $1000. Drat!

It might seem that you could rely on the checking the Referer to prevent this attack, but some proxy servers etc… will strip out the Referer field in order to maintain privacy. Also, there may be ways to spoof the Referer field. Another mitigation is to constantly change the URL used for performing sensitive operations like this.

In general, the standard approach to mitigating CSRF attacks is to render a “canary” in the form (typically a hidden input) that the attacker couldn’t know or compute. When the form is submitted, the server validates that the submitted canary is correct. Now this assumes that the browser is trusted since the point of the attack is to get the general public to misuse their own browser’s authority.

It turns out this is mostly a reasonable assumption since browsers do not allow using XmlHttp to make a cross-domain GET request. This makes it difficult for the attacker to obtain the canary using the current user’s credentials. However, a bug in an older browser, or in a browser plugin, might allow alternate means for the bad guy’s site to grab the current user’s canary.

The mitigation in ASP.NET MVC is to use the AntiForgery helpers. Steve Sanderson has a great post detailing their usage.

The first step is to add the ValidateAntiForgeryTokenAttribute to the action method. This will validate the “canary”.

[ValidateAntiForgeryToken]
public ActionResult Transfer(int destinationAccountId, double amount) {
  ///... code you've already seen ...
}

The next step is to add the canary to the form in your view via the Html.AntiForgeryToken() method.

The following shows the relevant section of the view.

<% using (Html.BeginForm("Transfer", "Home")) { %>
<p>
    <label for="Amount">Amount:</legend>
    <%= Html.TextBox("Amount")%>
</p>
<p>
    <label for="destinationAccountId">
      Destination Account:
    </legend>
    <%= Html.DropDownList("destinationAccountId", "Select an Account") %>
</p>
<p>
    <%= Html.AntiForgeryToken() %>
    <input type="submit" value="transfer" />
</p>
<% } %>

When you view source, you’ll see the following hidden input.

<input name="__RequestVerificationToken" 
  type="hidden" 
  value="WaE634+3jjeuJFgcVB7FMKNzOxKrPq/WwQmU7iqD7PxyTtf8H8M3hre+VUZY1Hxf" />

At the same time, we also issue a cookie with that value encrypted. When the form post is submitted, we compare the cookie value to the submitted verification token and ensure that they match.

Should you be worried?

The point of this post is not to be alarmist, but to raise awareness. Most sites will never really have to worry about this attack in the first place. If your site is not well known or doesn’t manage valuable resources that can be transferred to others, then it’s not as likely to be targeted by a mass phishing attack by those looking to make a buck.

Of course, financial gain is not the only motivation for a CSRF attack. Some people are just a-holes and like to grief large popular sites. For example, a bad guy might use this attack to try and post stories on a popular link aggregator site like Digg.

One point I would like to stress is that it is very important to never allow any changes to data via GET requests. To understand why, check out this post as well as this story about the Google Web Accelerator.

What about Web Forms?

It turns out Web Forms are not immune to this attack by default. I have a follow-up post that talks about this and the mitigation.

If you missed the link to the sample code before, you can download the source here (compiled against ASP.NET MVC 2).

Technorati Tags: aspnetmvc,asp.net,csrf,security

code, humor comments edit

I’ve been relatively quiet on my blog lately in part because of all the work on ASP.NET MVC. However, the ASP.NET team is a relatively small team so we often are required to work on multiple features at the same time. So part of the reason I’ve been so busy is that while we were wrapping up ASP.NET MVC, I was also busy working on a core .NET Framework feature we plan to get into the next version (it was a feature that originated with our team, but we realized it belongs in the BCL).

The goal of the feature is to help deal with the very common task of handling string input. In many cases, the point is to convert the input into another type, such as an int or float. However, how do you deal with the fact that the string might not be convertible to the other type.

We realized we needed a type to handle this situation. A type that would represent the situation after the user has submitted input, but before you attempt the conversion. At this point, you have a string or another type.

clip_image004_thumb

For more details on the StringOr<T> Community Technology Preview (CTP), please see details on lead developer Eilon Lipton’s Blog (he’s a big fan of cats as you can see). He provides source code and unit tests for download. As always, please do provide feedback as your feedback is extremely important in helping shape this nascent technology.

Tags: framework , .net

asp.net mvc, asp.net comments edit

First let me begin by assuring you, this is not an April Fool’s joke.

2871423645_2f690a0c61Exciting news! Scott Guthrie announced today that we have released the source code for ASP.NET MVC 1.0 under the Ms-PL license, an OSI approved Open Source license with all the rights that license entails.

You can download the Ms-PL licensed source package from the download details page here. Just scroll down and look for the file named AspNetMvc1.Ms-PL.source.zip. My baby is growing up!

A big thanks must go out to everyone involved in making this happen and to those who approved it. It’s truly a team effort. When I joined Microsoft, I remember walking into ScottGu’s office to try and plant the seed for releasing ASP.NET MVC under the Ms-PL license. I came in armed with reasons why we should, but found him to be immediately receptive, if not already thinking along those lines. In fact, a lot of people such as Brian Goldfarb, my management chain, our LCA contact, etc… were completely on board, which was unexpected (though maybe it should not have been) and encouraging to me.

However, there’s agreement to do something and the actual doing. It still a lot of people to do the leg-work to make it happen. I personally was kept me very busy in the days leading up to the official RTM release. Let’s just say I feel like I’m one course away from getting a law degree.

I know one of the first questions some of you will ask is will we accept source code contributions (I’ve already seen the question on Twitter :). Unfortunately, at this time the answer is no, we do not accept patches. Please don’t let that stop you from contributing in other ways. The terms of the license do mean we need to stay on our toes to keep putting out compelling releases and we will work hard not to disappoint.

Personally (and this is totally my own opinion), I’d like to reach the point where we could accept patches. There are many hurdles in the way, but if you went back in time several years and told people that Microsoft would release several open source projects (Ajax Control Toolkit, MEF, DLR, IronPython and IronRuby, etc….) you’d have been laughed back to the present. Perhaps if we could travel to the future a few years, we’ll see a completely different landscape from today.

However, it is a complex issue and I don’t want to downplay that, but there are many of us who are looking for novel solutions and trying to push things forward. I really think in the long run, it is good for us and four our customers, otherwise we wouldn’t care.

But coming back to the present, I’m extremely pleased with where we are now and look forward to what will happen in the future. Someone once expressed disappointment that my involvement in open source projects seriously declined after joining Microsoft. It was my hope at the time that by the time it released, it would be clear that technically, I had been working on OSS. :)

subtext comments edit

Simo beat me to the punch in writing about this, After many long years being hosted on SourceForge, the Subtext submarine is moving into a new project hosting port.

We’ve finally moved off of SourceForge and onto Google Code’s project hosting. Our main site (primarily for end users) is still at http://subtextproject.com/ and I’ve hopefully updated every place it points to SourceForge to now point to Google Code.

Subtext-moves Image stolen from Simo’s blog. ;)

This was a very tough decision between CodePlex and Google Code. CodePlex is a great platform and I really like what they’ve done with being able to vote on issues etc… They seem to be innovating and adding new features at a rapid clip. I host Subkismet, a smaller project, on CodePlex and probably would choose it for a brand new project.

My one big complaint with CodePlex is that we really want native Subversion access, not a subversion bridge to TFS. For example, I was able to run the svnsync command to get the entire SVN history for Subtext into Google Code. That’s not something I could do today with CodePlex.

One other thing I really like with Google Code is that it’s fast. When you go to our project page, and click on the tabs, notice how fast the transition is. Click on an issue and see how fast you get there. Make a change and save it and it just snaps back. I spend a lot of time triaging and organizing issues etc… so this snappiness is really important to me.

Another great feature I love is how well code review is integrated into Google Code. For example, you can use the web interface to look at any revision in our repository. Take a look at r3406 for example.

Click on the diff link next to each file that was changed. For example, the diff for AkismetClient.cs. You get a nice side-by-side diff of the changes. You can double click on any line of code to leave a comment. Scroll down to line 160 and take a look at a comment. Don’t worry, I was the original author of that file so I’m not offending anybody but myself with that comment.

So there’s a lot I’d love to see improved with Google Code, but I’m pretty happy with the usability of the site overall. It’s a far improvement over SourceForge where I started to viscerally hate managing issues and doing any sort of administrative tasks over there.

We’re now using Google Groups for our Subtext discussion list and we have a separate group for notification emails such as commit emails. I’m going to leave the tracker and file releases on at SourceForge for a while longer until we’ve moved everything over. Unfortunately, there’s no automatic import from SourceForge for bug reports. But if you’re interested in keeping tabs on the progress Subtext is making, feel free to join the groups.

code comments edit

Recently, I tried to accomplish a simple task on a website which frustrated me because what should have been simple, was not. All I wanted to do was go to the Mix website and quickly find links to my sessions so I could post them here. Even I should be able to figure this out.

As a note, I’m using the Mix site as my illustration here, but I do it out of love and not mean spiritedness. Mix is my favorite conference, but its website…leaves something to be desired.

It seems particularly interesting that I’d run into this with the Mix site because the whole conference caters to a web design audience as well as web development. It just goes to show that even the best designers sometimes lose sight of what makes a user interface usable in the pursuit of cool flashy design. After all, designers often are trying to impress their designer friends when they should be creating a site that allows its audience to accomplish something?

Let’s take a look at my experience. Here’s the front page. Where do I start?

mix-site

Notice that there’s no search feature (I already tried Google). Fine, so I click all sessions and get this timeline view. There’s a search button there but when I type “MVC” and hit GO, nothing happens. I also try my last name. No go.

Sessions - Windows Internet
Explorer Near the bottom, I click on SPEAKERS and find my name. I then try clicking on one of my sessions which is highlighted as a link, and nothing happens (it’s since been fixed). When I highlight the session, a pop-up which appears to have links shows up, but I can’t seem to move my mouse over it because it disappears before my mouse gets there.

Speakers - Windows Internet
Explorer

After a moment of pondering, it occurs to me that maybe the video of my talk was not yet available at the time (it is now as I write this). It would have been nice if the site clearly indicated this, but instead, they were providing a link that went nowhere, giving me the impression that the video was available. Very confusing!

Now contrast that to this great post by Greg Duncan.

Mix 09 Quick Video Link List - Gregs Cool [Insert Clever Name] of the
Day - Windows Internet
Explorer

Notice that it’s the height of simplicity. It’s a list of all sessions (after all, the list of sessions wasn’t all that long) with headings showing you which video format the session is available in. I would have loved to see something like this on the Mix site.

A quick F3 to bring up my browser’s search feature, type in MVC, and boom goes the dynamite, I’ve found my sessions and am happily dissecting my speaking performance in disgust.

Kudos to Greg for putting this together. The fact that he even needed to put this together is a major indication that there’s a problem over at the Mix site.

The problem here is that in the pursuit of cool design, designers sometimes confuse ornamentation with good design. The Mix site has all sorts of flashy elements showing off a mastery of jQuery. Whoopee! And typically, I love those elements because when done well, they can make a site more usable. But in this case, I much prefer Greg’s simpler approach.

There’s not that much data to display, so rather than chop it up into pages, he just puts it all in one page which allows me, the reader, to make use of the familiar tools built into my browser such as F3 to search. Bam! Done! I can move on now.

Keep that in mind next time as you put together your next great user interface. How can you make it simpler and leverage the tools already in the client?

asp.net mvc comments edit

After my critical post of the Mix website, I found this other site, http://sessions.visitmix.com/, which should have been prominently linked to from the main site because it has a working search bar and is fairly usable and flashy!

I gave two sessions on ASP.NET MVC at Mix.

As you can see, we tried to have a bit of fun with the session titles. If you’re not tired of hearing me talk about MVC, you can also see an interview I did with Adam Kinney on Channel 9.

I will be posting my demos on my blog sometime soon hopefully. I want to give a few of them the full blog treatment. Partly because all of my demos are built live and I don’t keep the final product around, so I need to redo the steps. And I’m lazy. There. I said it.

comments edit

subtext200x200One of the cool products that I’m personally excited about announced at Mix is the updated Web Platform Installer.

I’m not going to lie. Part of the reason I’m excited about it is that it includes the latest version Subtext! The Web PI tool is a really nice way of installing and trying out various free and open source applications out there. It installs everything you need to get Subtext up and running on your local machine.

All you have to do is go to the Web App Gallery, find an application and click the Install button and it will install the application (if you have Web PI already installed). If you don’t have Web PI installed, it will prompt you to install Web PI and then install the app.

In this screenshot, you can see the dependencies needed to run Subtext are already listed.

Install
(2)

Subtext 2.1.1 is a very minor update to Subtext with a few bug fixes. The major fix is that the “forgot password” feature now works properly.

This was a little last minute surprise for the Subtext team as I literally put the required install package together in the last minutes leading up to Mix. In the meanwhile, major refactoring work is ongoing in our subversion repository. For example, the trunk now uses a custom Routing implementation (not yet built on ASP.NET MVC, but moving that way) Feel free to join in and help fix bugs and test. :)

asp.net, asp.net mvc comments edit

newdotnetlogo_2_thumb Today I’m happy to write that ASP.NET MVC 1.0 RTW (Release To Web) is now officially released.

This was one of several announcements ScottGu made at the Mix 09 conference today, which I unfortunately missed because I was on a plane to Vegas enroute to Mix 09. I was busy  back at the mother ship making sure everything was in order for the release.

Woohoo!

It’s been nearly a year and a half since I joined Microsoft and started working on it and what a ride it’s been.

Some highlights during that time:

With ASP.NET MVC, we wanted to release early and often providing a lot of transparency with our design process. We made a lot of changes based on user feedback. All in all, I counted 10 releases:

  1. December 2007 CTP
  2. Preview 2
  3. Preview 2.5 (April CodePlex release)
  4. Preview 3
  5. CodePlex Preview 4
  6. Preview 5
  7. Beta
  8. RC 1
  9. RC 2
  10. RTM!

A great way to learn about ASP.NET MVC is to go to the website, http://asp.net/mvc/. Also be sure to check out the free eBook which contains Chapter 1 of Professional ASP.NET MVC. This chapter contains an end-to-end walkthrough of building an application with ASP.NET MVC.

We also have an updated set of documents on MSDN worth checking out.

A great way to install ASP.NET MVC is via the new Web Platform Installer. I highly recommend it. Not only can you install ASP.NET MVC using it, but many other free applications such as one of my favorites, Subtext!

Technorati Tags: aspnetmvc,asp.net,subtext

code, asp.net mvc comments edit

I don’t know about you, but a great way to learn a new technology is to start using it. But to even start using it, it helps to be able to look at a real-world running application built on that technology. Combine that with source code and a walkthrough, and I think you have a winning combination.

That’s where NerdDinner comes in.

NerdDinner.com is the brainchild (and a big child at that) of Scott Hanselman. The concept is simple, let’s get nerds together over dinner so great ideas can flourish. The site is a great way to organize nerd dinners all over the place. The site is live and built using ASP.NET MVC, so go check it out.

But don’t stop there. Now that you’ve seen the site, go check out the source code on CodePlex. What better way to understand how the pieces fit together than to browse the source code for NerdDinner.

And I hope you don’t stop there either. There’s often a tendency to impart too much authority and expertise to an author. But as I’ve learned from writing this book among others, being an author doesn’t require any special expertise, gift, or ability. It just requires a love for self-inflicted pain. My personal pain threshold has been surpassed, so if you hear me talking about writing another, smack me…please.

In the spirit of Nerd Dinners, let’s get the ideas rolling! Create issues and let us know what you like and don’t like and what you think works and doesn’t work. We’re all in this together learning and refining our craft.

book-coverLooking at the site and source will show you what NerdDinner.com is, but to learn how it was built, I highly recommend checking out ScottGu’s blog post which presents a brisk end-to-end walkthrough of building NerdDinner.com.

His post is a preview of Chapter 1 of our book, Professional ASP.NET MVC 1.0. This chapter gets you started, while the rest of the book (still in production) dives deeper into each of the areas and concepts of the framework. And by the way, the eBook (aka Chapter 1) is licensed under a Creative Commons Attribution No Derivatives license, so feel free to redistribute.

So if you’ve been wondering why my blogging frequency declined this past year, now you know. Getting a release ready for RTM is a lot of work. Writing a book on that release at the same time is pure insanity.

Fortunately, I was in very good company with my esteemed co-authors, Rob “I Feel your pain” Conery, Scott “Five-head” Hanselman, and Scott “The GU” Guthrie, all of whom are completely insane! You heard it here first.

asp.net mvc comments edit

Yesterday, I wrote about troubleshooting Windows MSI Installers and talked about the pain we here feel when an installation fails. Turns out, it’s not always our fault. ;) It appears there’s a hotfix released for Visual Studio which addresses a problem with installing ASP.NET MVC when you have a third party add-in installed. I mentioned the three above because they are among the most commonly used add-ins which run into problems.

You can read about the Hotfix on the Visual Web Developer blog or simply go here to download it.

Note, that this doesn’t solve the problem for all add-ins. For example, someone reported an installation failure when they had Clone Detective installed. Uninstalling Clone Detective, installing ASP.NET MVC, and then reinstalling Clone Detective solved the problem. We’re still looking into why our installers are having problems with these add-ins.

asp.net mvc, asp.net comments edit

UPDATE: I updated this post slightly to address some good criticsm from Rob Mensching by removing the MsiZap section. Note that this post does not blame the Windows Installer for the few problems we have with ASP.NET MVC installations. The major culprit tends to be either devenv /setup or ngen.exe.

The point in this post is to provide tools for those who are very careful, know what they are doing, and really want to take a peek at how the installer works. These tools can help provide insight to whether the two culprits I just mentioned really are the issue causing the installation to fail in your particular case. Everything I point out here IS AT YOUR OWN RISK! :)

For the most part, the installations for ASP.NET MVC have been quite stable and we’ve tested the installer at every release and 99% of the problems we’ve run into fall into those two buckets. I did not intend to give the impression that we saved installation testing for the last moment, because that’s just not true. We merely had a last minute requirement change for our installer. RC 2 was a response to that change, not to a bug found. Now back to the post. :)

Having an installer crap out on you when you’re excited to try out a new piece of software is an incredibly frustrating experience. Frustrating both for the user as well as for the product team. Every time I read on Twitter that someone is having trouble installing ASP.NET MVC, a new ulcer throbs in my side.

A big part of the frustration is the lack of control and insight into what’s going wrong. Jacques (no blog), a developer on the ASP.NET team has put together a troubleshooting guide based on his research into what makes installers tick to help alleviate some of this lack of control. While his focus was primarily on the ASP.NET MVC installer, much of this information is useful for all MSI installers.

Windows Installer Log Files

Log files are not automatically generated by an MSI. To generate a log file, you will need to use msiexec from a command prompt to install the MSI, for example

msiexec /i AspNetMVC1-RC2.msi /l*v .\install.log

Alternatively you can enable logging by default by configuring a registry key for this. See this article on enabling Windows Installer Logging or if you are using Windows XP, take a look at this article on the same topic specific to Windows XP. Please note that enabling this feature can have an impact on system performance.

The MSI logs are probably the best place to start when trying to figure out why an installation failed. At the very least you will be able to identify the step in the installer that caused the problem.

For example, one common source of trouble is when a required service is not started such as:

  • .NET Optimization Service
  • ASP.Net State Service

Visual Studio Log Files

The ASP.NET MVC specific context menus in Visual Studio are installed by executing devenv.exe with the /setup switch. When the installer executes this command it automatically generates a log file at the location

%TEMP%\ MvcTemplates.log

The log file can be consulted for more details in case this step of the installation failed.

Orca

Orca is an editor for Windows install packages (MSI files) and is part of the Windows Installer SDK (the Orca MSI is located at %Program Files%\Microsoft SDKs\Windows\v6.0A\bin). While we don’t generally encourage people to edit the ASP.NET MVC installer, for those willing to take matters into their own hands (at your own risk!) Orca can be used to disable some of the steps executed by the installer. When you open the MSI you will see all the tables used by the installer. The feature table is probably the most interesting since it shows everything that will be installed.

clip_image002

Notice that by default, the Level attribute of all the features are set to 1. This means that the feature is enabled to be installed. We have some logic that will disable some of the features based on the information that we gather about the system on which were are installing. For example, the VWDExpress_Feature will be disabled if a user does not have Visual Web Developer installed. Similarly we will disable one of the MvcGacNgenXX_Features depending on whether the underlying OS is a 64-bit or 32-bit version.

Let’s say that you’ve tried to install MVC, but for some reason the installer fails to create a native image for System.Web.Mvc.dll using NGEN. Using Orca you can disable the MvcGACNgen32_Feature and MvcGACNgenAll_Feature by deleting these two rows from the MSI and saving it under a different name. Of course the best thing to do is to investigate why NGEN is failing in the first place.

Editing the MSI is not really encouraged since it may cause other problems such as failing to uninstall properly.

NGEN failures

We automatically GAC and NGEN System.Web.Mvc.dll during the setup process. Installing into the GAC (Global Assembly Cache) is a relatively painless operation. NGEN on the other hand is more prone to causing the installer to fail.

When installing via double clicknig the MSI, you will see an error message before the installation is rolled back if NGEN fails. The error message itself is not that useful as it will most likely just show a cryptic message and an HRESULT value (You can do a web search for the HRESULT and see whether there are workarounds available). To investigate the failure, take a look at the log generated by the MSI (assuming you had logging turned on when you made the install). Open the log file and search for ExecNetFx (this is the name of the WiX component the installer uses to run NGEN).

ExecNetFx:  Microsoft (R) CLR Native Image Generator 
  - Version 2.0.50727.3053
ExecNetFx:  Copyright (c) Microsoft Corporation.  All rights reserved.
ExecNetFx:  Installing assembly System.Web.Mvc, Version=1.0.0.0, 
  Culture=neutral, PublicKeyToken=31BF3856AD364E35
ExecNetFx:  Catastrophic failure (Exception from HRESULT: 0x8000FFFF 
  (E_UNEXPECTED))
ExecNetFx:  Error 0x8007006d: failed to allocate output string
ExecNetFx:  Error 0xffffffff: Command line returned an error.
ExecNetFx:  Error 0xffffffff: failed to execute Ngen command: 
  C:\Windows\Microsoft.NET\Framework\v2.0.50727\ngen.exe install 
  "System.Web.Mvc, Version=1.0.0.0, Culture=neutral, 
  PublicKeyToken=31BF3856AD364E35"

The example above is a very difficult problem to troubleshoot, but there are a few things you can try:

  • Open a command prompt, go to %WINDIR%\Microsoft.NET\Framework\v2.0.50727 and execute the following commands and then try to install MVC again
    • ngen ExecuteQueuedItems
    • ngen Update
  • Examine the NGEN log files located in %WINDIR%\Microsoft.NET\Framework\v2.0.50727. There are two files, ngen.log and ngen_service.log. The logs may contain information about other problems in the system that caused the failure, for example a missing DLL that may cause an update operation to fail when NGEN attempts to update invalid native images.
  • Make sure that the .NET Runtime Optimization service is running clip_image004

Windows Event Viewer

The installer executes a number of external tasks during the installation process.

  • devenv.exe /installvstemplates: This step is used to register the MVC project templates in Visual Studio. (For Visual Web Developer the executable is called VWDExpress.exe).
  • devenv.exe /setup: This step is executed to merge all the metadata in Visual Studio and is used by the MVC packages to register the context menus.
  • ngen.exe install: Used to generate native images of the System.Web.Mvc assembly. See this article for more details.
  • ngen.exe update: Updates any native images that have become invalid.

You will most likely see multiple warning events such as the example below. Visual Studio will log warning events for unknown attributes it encounters in templates and usually just moves past them. These warnings can be safely ignored.

clip_image006

But you may see other events that may cause the install to fail such as the example below:

clip_image008

Solving this problem is easy enough; restart the Cryptographic Service and run the installer again.

Visual Web Developer Express

A few users have reported that after installing MVC, they don’t see an option to create an MVC Web Application Project in Visual Web Developer. If you run into this problem, try the following:

  • Open VWD.
  • Go to Tools and select Import and Export Settings.
  • Select Reset all settings and click Next to complete the wizard.

Third Party Utilities

A number of users have reported problems during the installation of MVC or when trying to use some of the shortcuts inside Visual Studio. In many cases this was resolved by removing certain add-ins:

  • PowerCommands
  • Clone Detective
  • Spec# and F#

If you review the MSI logs you will most likely see something like the following:

MSI (s) (5C:70) [13:27:26:106]: Executing op: CustomActionSchedule(Action=VisualStudio_VSSetup_Command,ActionType=3122,Source=C:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE\devenv.exe,Target=/setup,)

MSI (s) (5C:70) [13:28:41:075]: Note: 1: 1722 2: VisualStudio_VSSetup_Command 3: C:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE\devenv.exe 4: /setup 
Error 1722. There is a problem with this Windows Installer package. A program run as part of the setup did not finish as expected. Contact your support personnel or package vendor. Action VisualStudio_VSSetup_Command, location: C:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE\devenv.exe, command: /setup 

MSI (s) (5C:70) [13:28:42:716]: Product: Microsoft ASP.NET MVC RC 2 -- Error 1722. There is a problem with this Windows Installer package. A program run as part of the setup did not finish as expected. Contact your support personnel or package vendor. Action VisualStudio_VSSetup_Command, location: C:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE\devenv.exe, command: /setup

If installing MVC fails in this manner, try the following:

  • Create a log file, for example, devenv.log.
  • Open a Visual Studio command prompt and execute devenv /setup /log devenv.log. Make sure that you have administrator rights since that’s required by the /setup switch.
  • Scan the log file and look for any <description> elements that contain errors. This may point to problematic packages that are causing devenv.exe to fail when MVC is trying to configure its context menus.

Another option to try is the following:

  • Open a Visual Studio command prompt.
  • Start Visual Studio by executing the command devenv /ResetSkipPkgs.
  • Close Visual Studio.
  • Execute devenv /setup.

Tags: aspnetmvc , msizap , installation

asp.net mvc, asp.net comments edit

UPDATE: This post is outdated. ASP.NET MVC 1.0 has been released already!

Today we’ve made the Release Candidate 2 for ASP.NET MVC available for download.

This post will cover some of the changes with ASP.NET MVC we made in response to internal and external feedback since our last Release Candidate.

Let me provide the quick and dirty summary, and then fill in the details.

  • Setup will now require .NET 3.5 SP1
  • Bin deployment to 3.5 host without SP1still possible
  • New server-only install mode

Now onto the details

Setup Requires .NET Framework 3.5 SP1

The new installer will require that .NET Framework 3.5 SP1 be installed on your machine. For your development environment, we recommend that you also install Visual Studio 2008 SP1, but this is not required.

The reason we made this change is that we were including the System.Web.Routing.dll and System.Web.Abstractions.dll assemblies with the MVC installer. However, it does not make sense for us to co-ship assemblies which are part of the Framework as this would negatively affect our ability to service these two assemblies.

Bin deployment to 3.5 host without SP1 Still Possible

We are not taking a runtime dependency on SP1 other than our existing dependency on System.Web.Routing.dll and System.Web.Abstractions.dll. Thus you can still bin deploy your application to a hosting provider who has .NET 3.5 installed without SP1 by following these instructions.

Note that in such a configuration, you take on the risk of servicing those assemblies. Should we release any important updates to any of these assemblies, you’ll have to manually patch your application. However, you will still enjoy full CSS (formerly PSS) support for this configuration.

New Server-Only Install Mode

We’re adding an option to the installer that enables installing on a server that does not have Visual Studio at all on the machine, which is useful for production servers and hosting providers.

The installer will no longer block on a machine that does not have Visual Studio installed. Instead, it will continue the standard MVC installation without installing the Visual Studio templates. The assemblies will still be installed into the GAC and native images will also be generated.

Certain other requirements have also been relaxed. For example, if the machine on which the installation is performed contains Visual Web Developer Express Edition 2008 without SP1, the installation will still proceed, but with a warning prompt. You can also automate this installation by invoking the installer using the command line (all on one line):

msiexec /i AspNetMvc-setup.msi /q /l*v .\mvc.log MVC_SERVER_INSTALL="YES"

Summary

As a result of these changes, we realized it would be prudent to have one more public release candidate. As I mentioned, there are very few runtime and tooling changes. Most of the changes are in the installer and we want to make sure that the installer is rock solid before we call it an RTM.

Based on all your feedback from the first Release Candidate, as well as our own investigations and testing, we are confident that the Release Candidate 2 will be solid and lead to a strong RTM.

In case you missed it above, here’s the link to the download page. You can find out what else has changed in the RC 2 release notes.

And before I forget, as usual, we published the source code and our MvcFutures assembly on CodePlex.

asp.net mvc, asp.net comments edit

MIX09_SpeakerBling_VegasStrip_136x186 I finally have my registration worked out and I’m officially going to Mix09 this year! Woohoo! Not only am I going, but I’ll be speaking at Mix for the first time, so be sure to come by and say hi.

I’ve mentioned this before, but Mix is easily one of my favorite Microsoft conferences. Jeff Atwood said it well:

MIX is by far my favorite Microsoft conference after attending the ’06 and ’07 iterations…

What I love about Mix is that it …

  • is relatively small and intimate, at around 2,000 attendees.
  • seamlessly merges software engineering and design.
  • includes a lot of non-Microsoft folks, even those that are traditionally hostile to Microsoft, so there’s plenty of perspective.

I’ve been to every one so far:

I’ll be giving the following two sessions at Mix this year:

MIX09-T50F ASP.NET MVC: America’s Next Top Model View Controller Framework

See how to build a simple application that highlights some of the key capabilities of ASP.NET MVC. Also, learn how to improve productivity using some of the cool new tooling features

MIX09-T44F Microsoft ASP.NET Model View Controller (MVC): Ninja on Fire Black Belt Tips

See a walkthrough of several tips and tricks for getting the most out of the ASP.NET MVC framework.

The first talk is an introductory overview and the second one allows me to dig in a bit more.

I’ve been working hard on putting together some demos so I will hopefully have something interesting to show off. In any case, if you’re going to the conference, leave a comment and when you’re there, be sure to come by and say hello.

Also, let me know if there’s anything specific you’d like me to cover. This should be a fun one.

personal comments edit

Day two of ALT.NET is over and I’m already pooped (for you non-English speakers, that means tired, not something else that might come to mind).

Once again, photos by our Chronicler, Brad Wilson. As a testament to how engaging the sessions were, there are a lot fewer photos from day two in his photostream.

Encouraging Open Source on .NET by Brad
Wilson.

The first session I went to was on the topic of Encouraging Open Source in the .NET Space as seen above, which veered all over the place. Many felt the industry is shifting towards more and more Open Source software so those who can leverage that will be better off than those who can.

One interesting idea that came out of it was there’s a need for more education regarding Open Source. For example, understanding licensing is very challenging. It’d be great to have simple tools like a compatibility matrix or a license chooser (ala Creative Commons license generator).

In the meanwhile, I’ve tried to do my best to explain what little I know of software licensing in the past.

Another interesting point tied into our TDD discussion later on in the day related to the fact that for many shops, it doesn’t exist unless Microsoft endorses it.

.NET on the Mac, Linux, and iPhone by Brad
Wilson.

The next session I attended was “.NET/Mono on the Mac, Linux, and iPhone” facilitated by the always entertaining Miguel De Icaza and Joseph Hill. I’m quite certain that everyone was there because they wanted to pull in $10,000 a day writing the next Fart app for the iPhone using C#.

TDD and Microsoft by Brad
Wilson.

Later in the day, Karen Liu (a PM on the Managed Languages/IDE team), Euan Garden (PM for Visual Studio Test), and I (photo above) gave a wide ranging session on TDD and Microsoft, which covered investments we’re making across Developer Division to help make the experience for writing proper unit tests better for developers such as ASP.NET MVC, WPF’s Model-View-ViewModel, Visual Studio improvements, Silverlight, etc….

The focus of our efforts has been addressing the need for our tools and frameworks to support all developers who write automated tests. But the bar set by the expectations of a TDD developer is typically very high, and by striving to meet those expectations, we feel all developers benefit.

I showed off a few slides to set the context for what groups we’ve talked to and what improvements we’re seeing start to happen for the next wave of products.

Karen Liu gave a few demos of how Visual Studio 2010 greatly improves the workflow for a test-first developer and Euan Garden led a discussion about the Visual Studio unit testing framework.

We discussed where we’d all like to see Visual Studio take unit testing in the future. There were quite a few voices who said they’d like to see Visual Studio include something like xUnit.NET, much in the same way that ASP.NET MVC includes jQuery, because for the places where they work, for better or worse, it doesn’t exist unless it’s part of Visual Studio. This is a common theme I’ve heard when it comes to people wanting to promote a development tool at their workplace for which Microsoft does not have an alternative.

To illustrate this point, one person came up to me and told me he had never used jQuery (and didn’t write a lot of JavaScript) until it was included in ASP.NET MVC and now he’s very happily using jQuery with ASP.NET MVC.

To me, that’s a great testimonial for how leveraging Open Source in smart ways can make customers happier.

personal comments edit

The third and last day of ALT.NET Seattle was a short one for me. My poor extremely patient wife was not feeling well today so I had to leave right at lunch time. But before I left, I did manage to attend a great session by John Lam and Jimmy Schementi on “Adding Scripting Support to .NET Applications”. In fact, you can watch the session here via Kyte.tv.

John and Jimmy covered the topic of hosting IronRuby to provide “end-user” ability to script an application. The classic example is that many 3-D games, Half-Life for example, write their core 3-D engines etc… in C++. However, they often provide a scripting language such as LUA which allows others to script the behavior of objects in the game, as these types of things change often and you want the flexibility to do so in a lightweight language.

The same may be true in an enterprise application where you want to write the whole app in C#, but perhaps allow configuring the rules engine using IronRuby.

I showed up to the session late and asked if John and Jimmy were going to show a demo. Unfortunately, they didn’t have one prepared, so I gave everyone a sneak preview of a demo where I have an ASP.NET MVC app hosting IronRuby in a manner where I think some C# developers will see the value. It was just a little something I’ve been hacking away at in my copious free time and hope to present at the MVP Summit and Mix. I won’t talk about it yet as I have a bit more work I want to do before I put it on my blog.

Before the session Aaron Jensen showed me some really cool stuff he’s doing with Spark View Engine and ASP.NET MVC. After the session, Eric Hexter showed me some neat stuff his company has been doing with T4 templates and ASP.NET MVC. This really got me fired me up with ideas for the next version of ASP.NET MVC to help support such efforts.

One of the coolest things at this conference was the usage of Kyte.tv. I honestly hadn’t heard of it until last week, but everyone was recording sessions live via Kyte.tv. After going home early, I was able to get back online and watch a couple more sessions recorded by Scott Hanselman when my son and wife took a nap. How cool was that.

personal comments edit

 

ALT.NET Opening Ceremonies by Brad
Wilson

Day one of the ALT.NET Seattle conference is over and I’m looking forward to tomorrow’s sessions.

As an Open Spaces event, the first order of business was for us, the attendees, to set the session agenda for the rest of the conference. In the above photo, you can see Scott Hanselman proposing a topic in one of my favorite conference photos taken by Brad Wilson. This process took about two hours after which many of us headed out to Red Robin for a nerd dinner.

This is my second ALT.NET Open Spaces event and I really like the principles set forth:

  • Whoever comes is the right people
  • Whatever happens is the only thing that could have happened
  • Whenever it starts is the right time
  • When it’s over, it’s over

In some ways, it reminds me of the 10 Principles of BurningMan, specifically these two:

Radical Inclusion

Anyone may be a part of Burning Man. We welcome and respect the stranger. No prerequisites exist for participation in our community.

Participation \ Our community is committed to a radically participatory ethic. We believe that transformative change, whether in the individual or in society, can occur only through the medium of deeply personal participation. We achieve being through doing. Everyone is invited to work. Everyone is invited to play. We make the world real through actions that open the heart.

There’s no hard line drawn between attendees and speakers. Everyone is welcome to be both attendee and speaker as everyone generally has something interesting to share, teach, and learn.

The other part I love about this conference is seeing familiar faces as well as meeting collaborators from around the world I’ve never met in person until now. For example, Steve Harman and I finally meet Simone Chiaretta in person, the third Musketeer of Subtext, who apparently can’t keep his eyes open for a photo after being up for over 30 hours due to flying in from Italy.

3315077517_855eae566b

I look forward to seeing what tomorrow brings.

Technorati Tags: alt.net,altnetseattle

asp.net mvc, asp.net, dlr comments edit

Last July, I blogged about an IronRuby ASP.NET MVC prototype Levi and I put together with John Lam and Jimmy Schementi of the DLR team. It was really rough around the edges (and still is!)

IronRuby on ASP.NET MVC
DemoOne of the benefits of doing that prototype was that it inspired all the work around action and controller descriptors in ASP.NET MVC (something I need to write more about later) which decoupled us from exposing reflection in our public API and improved the overall design of ASP.NET MVC greatly. This had the nice side-effect of making the implementation of IronRuby on top of ASP.NET MVC much cleaner.

In this updated prototype, I’ve now implemented support for ASP.NET MVC filters. You can define action filters and authentication filters (I need to test the other filter types). Keep in mind, this is a very rough prototype code still. I’ve just been swamped up to my neck lately and this is a spare-time labor of love.

I’ve only implemented one type of filter so far. You can specify a class to apply to an action method and the class implements a specific filter interface. I haven’t done anything like the more rails-y filter_before and filter_after thing.

Here’s an example of an action filter in IronRuby. This one simply writes something to the response in the before method, and does nothing in the after method.

class MyFilter < IronRubyMvc::Controllers::RubyActionFilter
    def on_action_executing(context)
      context.http_context.response.write 'MyFilter '
    end
    
    def on_action_executed(context)
      # noop
    end
    
    def method_missing(name, *args)
        show_action_info name, args
    end
end

(Gee, I wish I had a ruby syntax highlighter plug-in for WLW)

And here’s the use of that filter within a controller.

require 'HomeModel'
require 'MyFilter'

class HomeController < Controller
  filter :index, MyFilter

  def index
    view nil, 'layout', HomeModel.new
  end  
end

Notice that the way you define a filter on the index action is:

filter :action_name, FilterClassName

In the sample code I uploaded, you can see the effects of the filter at the top of the page. :) Hopefully I’ll find more time to update this, but as I said, it’s a labor of love, but time is in short supply.

In the meanwhile, I also need to look into whether there’s enough interest to make this a CodePlex project. There’s a bit of due diligence I have to do before I put code up on CodePlex, which is why I haven’t done it already because I’ve been busy.

And before I forget, here’s the download location for the sample.

Ivan Porto Carerra has taken this prototype and is running with it. To download the latest, check out his IronRubyMVC GitHub project.