JavaScript Views for Easier Ajax (with JQuery)

I tweeted Phil Haack a while ago asking for a new feature in Asp.Net MVC 3. That feature was JavaScript views. What the heck is a JavaScript View? Well first, let’s define what the problem is and then you will see how JavaScript views can be very helpful. Let’s look at how we make an ajax request in JQuery


$.ajax({
  url: "test.html",
  cache: false,
  success: function(html){
    $("#results").append(html);
  }
});

Do you see a problem? You might not, because this is a valid statement. The problem is with the url property. It is hard coded to be “test.html” which might be ok for simple applications, but this can be problematic as your application gets larger.

Asp.Net 4 (or 3.5) to the Rescue

If you’ve been keeping up with Asp.Net then you know there is something new called routing. It allows you to define friendly urls. It is integral to Asp.Net MVC. From this point on, I will assume you know about Asp.Net MVC and routing. I have a complex site that has actions, several of which are purely for Ajax. The issue is that my routing scheme is still very experimental and I am still deciding on how to get the prettiest urls I can. What is very solid is the functionality each of these actions perform. So what is the challenge.

How do I dynamically inject urls into JavaScript by utilizing the Routes I have already defined?

Luckily the solution is very straightforward and easy to implement. Let’s look at how your JavaScript file might look like.

<%@ Page Language="C#" Inherits="System.Web.Mvc.ViewPage" %>

$(document).ready(function() {
  $(".button").click(function() {
        $.ajax({
            type: "POST",
            url: "<%= Url.Action("Ajax","Home") %>",
            success: function(response){
            $(".result").html(response.message);
            }
        });
  });
});

Sweet right! Well it isn’t that easy. You have to set somethings up in your MVC project before this works.

Step 1 – Create a Controller

Create a controller specifically for handling dynamic JavaScript views.


public class JsController : Controller    {

public ViewResult Index(string file)        {

return View(file);

}

}

Step 1 is complete. We need a controller so that a RequestContext is passed to our JavaScriptView, without this our views will bomb. Let’s move on to Step 2.

Step 2 – Specify the Route


routes.MapRoute(

"JavascriptViews",

"js/{file}.js",

new { controller = "Js", action = "Index", file = UrlParameter.Optional });

We need this route, so that MVC handles requests and points them to our controller.

Step 3 – Create Your JavaScript View and Link it

Add a new view under a “Js” folder under the “Views” folder. That’s it! All you need now. You can start utilizing the tools inside of Asp.Net MVC to start generating routes. Technically, you could do a lot more than just generate routes, but I wouldn’t go crazy with using C# to generate your JavaScript files.


<script src="js/master.js" type="text/javascript"> </script>

Conclusion

This is a great way to manage the Urls in your JavaScript files without the concern of worrying about modifying all your JavaScript files just because you want a different route. Download my sample and see if you like it or you think I’ve gone completely insane.

JavascriptViewExample

FluentSitemap: Build Sitemaps for Asp.Net MVC

Building your site is only half the battle. Getting people to know it exists is the other half. If you are creating a public facing site, or even an intranet that utilizes an in-house search server then I have created a library just for you. The library is FluentSitemap. This library is designed to help you easily build sitemaps to be utilized by major search engines. The great thing about this library is that utilizes all your existing routes and controllers to build a sitemap even for the most complex Asp.Net MVC sites.

The FluentSitemap library can be found at GitHub Here.

How to use you, Let me count the ways

There are several ways you can utilize this library. The first is to specify each node manually. Let’s look at how that looks.

           // You can pass in a HttpContext from anywhere
            // in you application
            ISitemapConfigurator configurator = new SitemapConfigurator(HttpContext);

            // create sitemap node and set
            ISitemap sitemap = configurator.Create()
                .WithLocation("http://localhost.com/")
                .WithPriority(0.3)
                .WithChangeFrequency(ChangeFrequencyType.Never)
                .Set().Export();

The second is to use a controller/action pair.

        // You can pass in a HttpContext from anywhere
            // in you application
            ISitemapConfigurator configurator = new SitemapConfigurator(HttpContext);

            // Add From a controller and action
            ISitemap sitemap = configurator.Add("Home", "Index")
                .Add("Home", "About").Export();

The third is to use a route

       // You can pass in a HttpContext from anywhere
            // in you application
            ISitemapConfigurator configurator = new SitemapConfigurator(HttpContext);

            // Add From a controller and action
            ISitemap sitemap = configurator
                // Add From a Route
                .AddFromRoute("Default", new {id = "2"}).Export();

The last is to use the ISitemetadata. This is specifically there for IoC.

public class HomeControllerSitemapMetadata : ISitemapMetadata
    {
        private const string Home = "Home";

        #region ISitemapMetadata Members

        public void Create(ISitemapConfigurator sitemap)
        {
            sitemap.Add(Home, "Index")
                .Add(Home, "Scanner")
                .Add(c =&gt; c.Metadata());
        }

        #endregion
    }

    public class OtherControllerSitemapMetadata : ISitemapMetadata
    {
        private const string Other = "Other";

        #region ISitemapMetadata Members

        public void Create(ISitemapConfigurator sitemap)
        {
            sitemap.Add(Other, "Index")
                .Add(c =&gt; c.Test(1, "dude"));
        }

        #endregion
    }
            // An example, you'll probably use your favorite
            // IoC container to resolve all the metadata classes
            var metadata = new List
                               {new HomeControllerSitemapMetadata(), new OtherControllerSitemapMetadata()};

            ISitemap sitemap = new SitemapConfigurator(HttpContext).FromMetaData(metadata).Export();

There is more API sugar, so go download it and give it a try.

MVC Turbine – A Great Platform

I love Asp.Net MVC, that isn’t a secret. Although the framework isn’t perfect, it is a great leap in the right direction. When I start an Asp.Net MVC project there are things I always have to do just to jump into the meat of the new site. These things include replacing the ControllerFactory with a IoC enabled ControllerFactory, changing routing, and other boiler plate actions. This is where MVC Turbine comes in, and I am liking it more and more the deeper I dive into it. Javier Lozano, the creator, defines MVC Turbine as

MVC Turbine is a plugin for ASP.NET MVC that has IoC baked in and auto-wires controllers, binders, view engines, http modules, etc. that reside within your application. Thus you worry more about what your application should do, rather than how it should do it.

image

If you consider ASP.NET MVC as a stock Nissan 370z, then MVC Turbine is the Nissan 370z with the Nismo package. Ultimately the same car, but the tweaks make the ride so much more fun to drive. Everyday I find something cool in this framework, but these are my favorite features so far.

Services Registration and IoC

I love IoC, because it makes testing your applications easier and shrinks your code base over the long run. What I hate is having to wire it up every time I start a new project. With MVC Turbine, it is already handled for you. Just create classes that implement the IServiceRegistration interface. You will be passed your favorite IoC and you can do what you need to do to register your services.

Inferred Actions

If your controller actions just return a view, then you are going to love this. You can create a controller class with no actions, and MVC Turbine will look in your views folder and display that view. Check it out here.

Route Registration

When you have a large Asp.Net MVC application, then you’ll probably have a lot of routes. MVC Turbine allows a great facility for registering routes, while keeping you project clean.

I can definitely get behind MVC Turbine and I recommend you check it out.

ASP.NET MVC 2 RTM, Content Management System, & ValidateInput

I have a lot of clients asking whether I can enable them to edit their own content. Most of the time I ask questions that make them realize that they don’t really need it, but sometimes they really do want it. I’ve been developing ASP.NET MVC web applications in VS2008, but as VS2010 comes closer to being released and with ASP.NET MVC 2 hitting release, I am starting to focus my efforts on using both technologies. So I sat down today and looked at CKEditor, a WYSIWYG editor that is embeddable into your site.

The issue that I found is that ASP.NET 4.0 is really concerned about Security, so much so that it ignores my ValidateInputAttribute on my controllers. When I submit my HTML content from the client, the MVC application throws a red screen of death. By default, ASP.NET will validate all incoming requests to make sure there are no malicious things coming in.  The ValidateInputAttribute was designed to tell ASP.NET that this request is meant to contain things that might be dangerous.

There is a really simple fix to this, and it is one line long.

Solution:

  1. Open up your web.config
  2. Under System.Web add a httpRuntime node.
  3. Add requestValidationMode attribute and set it to “2.0”

image

The solution defaults back to ASP.NET 2.0’s request validation, which will respect your ValidateInputAttribute on your controller actions.

Hope this helps.

-Khalid Abuhakmeh

C4MVC Presentation on Database Migrations

Hello everybody. It has been about a week since I gave my C4MVC presentation on database migrations. The video is below, and the code is also downloadable below.

Migrations Example (VS2010)

Asp.Net MVC 2 Quick and Simple Site – v1

*Note: Asp.Net MVC 2 project in Visual Studio 2010

I sat down last night and was thinking about how I could get a simple starter site up and running for a client, until I could design something more tailored to their needs. There is nothing worse than having a “under construction” page or a “coming soon” page. It doesn’t really say much about what is happening or what might be coming. So I sat down and came up with the basics of what a client might want right from the start, here were my requirements.

  • Set a Logo, Name, and Subtitle
  • Be able to quickly edit a small about section (Content)
  • Quickly add some of the more important social networks (Twitter, YouTube, FeedBurner, Delicious, MySpace, and Facebook).
  • Be able to add Google Analytics (Optional)
  • A dynamic image gallery (drop images in a directory and everything is done for you).
  • Basic contact information. Email, Phone, and Website.
  • No external libraries to install (this hurts but is helpful).

So I sat down and started writing. I wanted someone to be able to push this site without editing a lot of files or having to setup a database. I opted to put a lot of the client’s settings in configuration. Yes configuration sections are not the new hotness but they can still serve a powerful purpose.

My first iteration had me using controller actions for each part of the site, but I slowly realized it was overkill. I opted to have one controller action from my index, and then break sections up into partial views that would be all rendered at the same time. Then those sections would be hidden and made visible using JQuery. After a little design, I ended up with this.

image

Let’s look at how to set this up.

Step 1 – Setup the Configuration

There are some pretty simple configuration sections in the web.config included with this project. You will see two App settings: WorkImagesDirectory and GoogleAnalyticsCode. The WorkImagesDirectory is used to find all the images in your gallery. Thumbnails for all your images will be automatically created if they are missing. The GoogleAnalyticsCode setting should be set to your Google Analytics code UA-XX-XXXX (or something like that). If you leave out the Google Analytics code then the script won’t be output to the page.

Next you will see a ContactInformation section. In this section you can set the name, site subtitle, email, phone, and website.

Finally, you will see a SocialNetworks section. Only the social network usernames you set will show up on the page. You can set Twitter, Facebook, YouTube, Delicious, MySpace, and FeedBurner(a blog maybe).

Step 2 – Setup Content

Once the configuration is done, then you probably want to change some of the content to reflect some good information.

All tabs are separated into partial views: About, Contact, Work, Social. Just replace the HTML content in here with what you want, leaving the nested RenderPartials.

Step 3 – Modify Colors and Images

All the images and style sheets you need to modify are under the Content directory. If you like the color and just want to modify the avatar at the top, just overwrite the avatar.png under Content/img.

Step 4 – Deploy It

Just publish what is there to your hosting provider and you are ready to go.

Conclusion

This is a good little site to get up and running for your clients, but it isn’t anything ground breaking. The code is straight forward, so even a novice can get in there and change things. The point here was not to over complicate the solution with third party libraries. It is to get a site up with in minutes, while still giving some great functionality to the people that need it.

AquaBird.StarterSite

Attack of the Bots! – Stop Them With ReCAPTCHA in ASP.NET MVC

As developers sometimes we forget that there are bad people out there. Nefarious people waiting for you to mess up, just so they can exploit your weaknesses. One of the biggest problems with the internet today is the use of bots. If you have ever run a publicly open site like a blog, forum, or contact form then you know what I mean. You get flooded with junk that you didn’t even know existed. This can be a huge problem, because it essentially makes the data coming in hard if not impossible to sort. So how do you stop these advanced monsters from reeking havoc on your public facing site?

We first have to understand how they exploit your site. You probably have some kind of form on your site. It is there for anyone and everyone to use, just like you intended. You spent hours meticulously crafting this form with valid HTML and readable labels. There is your first problem. Bots traverse your page looking for FORM tags. Then they proceed to look for INPUT tags which match their criteria. If you use a popular CMS or Blogging engine then you are already at a disadvantage. These systems are known by bots and there are no surprises on how your system works. Then the bots proceeds to submit the form. All this occurs in a matter of nanoseconds. Remember computers are fast, even when they are evil. Now the bots have a choice, leave your defenseless site in search of another or proceed to submit your form mercilessly until your site collapses and your inbox is filled with worthless junk.

The popular solution to combating bots  has been CAPTCHA systems. CAPTCHA stands for “Completely Automated Public Turing test to tell Computers and Humans Apart.” It usually involves a challenge-response test. The most popular kind is to show scrambled words in an image, which can be seen below. Some CAPTCHA systems can also get very strange. I have seen one that shows you screenshots of cute fuzzy animals and asks you to pick the kitten. This really is a interesting subject and I suggest you read the Wikipedia page on CAPTCHA.

KCAPTCHA_with_crowded_symbols

Let’s get started in developing a solution. You might be thinking to yourself, “I don’t want to write a crazy CAPTCHA system.” Well you are in luck, there are several services on the internet that let you utilize their system. My favorite service is ReCAPTCHA. It offers both image based CAPTCHA tests along with audio tests for better accessibility. Let me show you what the final product will be like. I will be using the ASP.NET MVC sample project and modifying the registration page to add CAPTCHA checking. Dilled Fresno!?!? What the heck is that?

image

Step 1 – Getting Your ReCAPTCHA account.

Go to the ReCAPTCHA site and sign up for your keys. You will get a private key and and a public key. Copy these to notepad, you will need them.

Step 2 – Download the .Net Library for ReCAPTCHA

You will need to download the ReCAPTCHA .NET Library. Technically you don’t need this, you could write your own wrapper, but this makes it much easier. Go ahead and add this to your ASP.NET MVC project as a reference.

Step 3 – Implement the Client-Side

You want the ReCAPTCHA red box to show up on your site. So we are going to have to put some code in your view. ReCAPTCHA has already provided this code for for you. I have placed it below for faster access. Place this code within your Form tag, it is critical that you do so. Ok you are done. I also placed a ValidationMessage underneath the ReCAPTCHA code so that I could see my message.

                <script type="text/javascript"
                   src="http://api.recaptcha.net/challenge?k=<YOUR PUBLIC KEY>">
                </script>

                <noscript>
                   <iframe src="http://api.recaptcha.net/noscript?k=<YOUR PUBLIC KEY>"
                       height="300" width="500" frameborder="0"></iframe><br>
                   <textarea name="recaptcha_challenge_field" rows="3" cols="40">
                   </textarea>
                   <input type="hidden" name="recaptcha_response_field"
                       value="manual_challenge">
                </noscript>
                <%= Html.ValidationMessage("ReCaptcha") %>

Step 4 – Implement the Server-Side

When the form is submitted, there will be two extra inputs submitted to your controller action. The “recaptcha_response_field” value and the “recaptcha_challenge_field” value. We will be using these to verify that the user is really human. So for the code that performs the CAPTCHA.

 private bool PerformRecaptcha()
        {
            var validator = new RecaptchaValidator
                                {
                                    PrivateKey = "<YOUR PRIVATE KEY>",
                                    RemoteIP = Request.UserHostAddress,
                                    Response = Request.Form["recaptcha_response_field"],
                                    Challenge = Request.Form["recaptcha_challenge_field"]
                                };

            try
            {
                var validationResult = validator.Validate();

                if (validationResult.ErrorCode == "incorrect-captcha-sol")
                    ModelState.AddModelError("ReCaptcha", string.Format("Please retry the ReCaptcha portion again."));

                return validationResult.IsValid;
            }
            catch (Exception e)
            {
                ModelState.AddModelError("ReCaptcha", "an error occured with ReCaptcha please consult documentation.");
                return false;
            }
        }

RecaptchaValidator is from the assembly you referenced. Notice that we need to set the private key, and that we are getting the user’s I.P. address. We also set the fields that we got from the form. Now we just need to ask the service if everything is ok. The rest is trivial ASP.NET MVC code.

Conclusion

You can get ReCAPTCHA into your site in about 5 minutes, but it might take some time to perfect how you want it to integrate with you current scheme. For me, I don’t make a call to ReCAPTCHA if my model is not valid (see code below), this saves me an expensive and unnecessary internet call. I am also considering placing similar code in an ActionFilter, in the same fashion as ValidateAntiForgeryTokenAttribute. It should be pretty simple to do that.

 if (ModelState.IsValid && PerformRecaptcha())
   {
    ...
    }

So now you have the power to stop those evil bots and take bake your site. Hope this helps.

Open Flash Chart in ASP.NET MVC

If you’ve ever developed an application of any type, you know that the business function of that application is only half the story. Most business applications also have to take into mind that your business user is going to want reporting. As a developer I find reporting the most boring part of the development process, but it is becoming less and less painful for me as a developer to implement it into my applications. Within the last year Microsoft has released a charting addition to the .Net framework based on the Dundas charts package, but they only output static images. In most cases this is ok, but it doesn’t make for a very compelling experience. Open Flash Chart is one alternative to the .Net charting; it is interactive and dynamic, which can help you build those compelling interfaces that your clients look for. So the point of this walkthrough is to show you how to implement Open Flash Chart into your MVC application.

image

Step 1 – Download the Open Flash Chart package

Obviously you’ll need Open Flash Chart, you can download it from the Official Open Flash Chart. When you download it there is going to be a lot of files, but don’t worry about it I’ll tell you which ones you need.

Step 2 – Import The Files You Need

You are going to need two files at a minimum. There is a .Net library in the package but I’ll show you, you don’t need it. The first file is the open-flash-chart.swf. This file is the major component of the open flash chart package. I transferred this file directly into my content folder in my ASP.NET MVC project.

image

image

The next file you’ll need is the swfobject.js file, this will make placing your charts on the page much cleaner and simpler. Transfer this file into your scripts folder.

image

image

Step 3 – Integrating Open Flash Chart into your View

There are a couple things that I do to get Open Flash Chart into my view. I first modify my master page and add a new ContentPlaceHolder called “Scripts”. This allows me to inject custom scripts per view if necessary. My head tag in the master page looks like the following.

<head runat="server">
    <title><asp:ContentPlaceHolder ID="TitleContent" runat="server" /></title>
    <link href="/Content/Site.css" rel="stylesheet" type="text/css" />
    <script src="/Scripts/swfobject.js" type="text/javascript"></script>
    <asp:ContentPlaceHolder ID="Scripts" runat="server" />
</head>

The next step is to inject the Chart into the page. The following code does that.

<asp:Content ContentPlaceHolderID="Scripts" runat="server">
    <script type="text/javascript">
        swfobject.embedSWF(
              "/Content/open-flash-chart.swf", "my_chart", "550", "200",
              "9.0.0", "expressInstall.swf",
              { "data-file": "Home/GetData" }
              );
    </script>
</asp:Content>
 

Notice what is done here. You first point to the open-flash-chart.swf in your content folder. Next you specify the div you would like to inject the chart into. Thirdly, you specify the size. Right after that is about the flash version and the install if your client is missing flash on their machine. Lastly, the most important thing, the location of your data. Notice that it points to a controller action. I’ll show you how to code that next.

Step 4 – Data, Data, Data

A chart wouldn’t be a chart without data. This is where we will leverage the power of the newest .Net frameworks with anonymous types. Open Flash Chart uses JSON objects to create you chart, but we don’t want to spend hours creating a library or adding references to assemblies we don’t need. So I went ahead and created an action relating to the one seen above. The code looks like this.


        public JsonResult GetData()
        {
            var data = new
            {
                title = new { text = "Many data lines", style = "{font-size: 20px; color:#0000ff; font-family: Verdana; text-align: center;}" },
                y_legend = new { text = "Open Flash Chart", style = "{color: #736AFF; font-size: 12px;}" },
                elements = new object[] {
                        new { type = "bar", alpha = 0.5, colour = "#9933CC", text = "Page views", values = new []   {9,6,7,9,5,7,6,9,7}},
                        new { type = "bar", alpha = 0.5, colour = "#CC9933", text = "Page views 2", values =  new [] {6,7,9,5,7,6,9,7,3}}
                },
                x_axis = new { stroke = 1, tick_height = 10, colour = "#d000d0", grid_colour = "#00ff00",
                    labels = new {
                        labels = new[] { "January", "February", "March", "April", "May", "June", "July", "August", "Spetember" }
                    }
                },
                y_axis = new { stroke = 4, tick_length = 3, colour = "#d000d0",  grid_colour = "#00ff00", offset = 0, max = 20 }
            };

            var result = Json(data);

            // Allow Open Flash Chart to
            // make request for data through GET
            result.JsonRequestBehavior = JsonRequestBehavior.AllowGet;

            return result;
        }

There are two catches here. The first catch is that Open Flash Chart has some properties that have a dash in them, like “font-size”. The other problem is that Open Flash Chart does a GET Request for all data, that is why I have the funky code at the bottom of the action. Don’t forget to look at the Open Flash Chart documentation to get an idea of what you need to get your chart looking like you want it to.

Conclusion

So there you have it. Now you have integrated Open Flash Chart with the addition of two files and a new action. I love how easy it is to use this project in an Asp.net application. Look into the Open Flash Chart package, because I’m sure there are more and better ways to implement this charting package into your applications.

Visual Studio 2010 Without ReSharper 5.0

I’ve started a new project in Visual Studio 2010 because I want to take advantage of the new features in ASP.NET MVC 2. The features I am really interested in are Areas and the support of the new client side validation libraries that utilize the Data Annotations attributes. I sat down and set up my new solution as usual. Everything at this point was going great. Rolling up my sleeves, after several minutes of coding the ReSharper 5.0 nightly build started barfing on me. The shortcut keys barely worked and it would constantly freeze VS2010 when viewing Html pages. Ultimately, I realized that ReSharper 5.0 was not ready for VS2010, although it works great in VS2008. Now I was faced with the cold reality of having to uninstall ReSharper, for the greater good of the project. I haven’t coded a project without ReSharper in about two years, but now I am venturing forth until ReSharper 5.0 can catch up with me. Below, I’m going to list the things that I miss most about development life with ReSharper.

Visual Studio 2010 Without ReSharper

Visual Studio 2010 Without ReSharper

1. Development Time Error Checking

Resharper tells you that you’ve made a mistake before you ever compile your solution. It is constantly compiling you application in the background and making sure everything is still gravy. This keeps you from hitting f5 or Ctrl+Shift+B every ten seconds. This has to be the feature I miss the most. This is definitely a feature Microsoft should look into building directly into future versions of Visual Studio. Wouldn’t you like to know that you typed something wrong  the second you type it wrong? In addition to finding your mistakes, it places a nice little sidebar to tell you where you can find where you went wrong.

2. Solution Wide Searches for Dependencies

Resharper is really smart about what classes you are using. It can search through your entire solution and add any dependency to your existing project. This greatly reduces the need to right click on a project and click the “Add Reference” option. It even remembers third party assemblies and can add them; assemblies like NUnit or Enterprise Library.

3. Ctrl + Click = Magic

ReSharper lets you hold down the control key on your keyboard and click on a class name, which instantly takes you to the source of that class. Can greatly speed up you navigational abilities.

4. ReSharper Test Runner

ReSharper has a great test runner which runs almost all unit testing frameworks. The alternative for me right now is running tests using TestDriven.Net and Gallio, which isn’t too bad but it isn’t as nice a workflow as using ReSharper.

5. The Super Shortcut Alt+Enter

Alt+Enter, remember that key combination if you want to be a coding ninja. A super shortcut in ReSharper that understands the context you are in and shows you appropriate actions. Want to remove unused namespaces? Move your cursor to the namespaces section of your code and press Alt+Enter. Want to use var instead? Alt+Enter. Want to rename a file to match a class name? Alt+Enter. Want to move a class to a namespace? Alt+Enter. Want to rule the world? Alt+Enter (coming in ReSharper 6).

6. Smarter Templates

If you use code snippets in Visual Studio then you owe it to yourself to look at the templates in ReSharper. You can create really smart templates that include things like namespaces, filename, and much more. This feature has save my fingers countless hours of typing.

Conclusion

I miss ReSharper, but the advantages to using VS 2010 greatly outweigh my selfish need to be comforted by a productivity tool. Until ReSharper 5 becomes more stable I will have to wander the development wilderness alone. Lets hope that isn’t too long.

ASP.NET MVC Clean HTML

I love ASP.NET MVC and I feel it is the future of ASP.NET Web Development, but what I don’t like is trying to get your pages to look nice and I’m not talking about visually for the end user, that actually is very easy and enjoyable. If you are like me, then you probably spend hours looking at the source of web pages. I consider myself a source snob, always wanting to see properly indented tags and elements. Below you’ll see what I’m talking about, a nightmare of bad HTML output. ASP.NET MVC doesn’t modify your HTML, which is great for web developers but it can also frustrate the same people if they suffer from being source snobs. So how do we address this issue without spending hours indenting views and thinking of nesting scenarios. There are two approaches we could take.

        <div id="main">

            <h2>About</h2>
                    <div>
<div>
                                    <div>
<div>
            <div>
<p>
    Put content here.
</p>
            </div>
</div>
                                </div>
                </div>
</div>

HttpModule

This was the standard way of doing it in a ASP.NET Web Form application. Before any html is spit out to the Response stream, you would modify it to meet your needs. This is partly the right approach for the MVC solution, but HttpModules are indiscriminate and will fire every time a request comes in. You can put logic in our httpmodule but what you will find is that it is very difficult to tell the difference between a ViewResult, JSonResult, or FileResult in an HttpModule.

ActionFilter

We get all the advantages of an HttpModule with the ability to discriminate, either by placing the filter only on actions that return a ViewResult or by accessing properties in the context passed to the filter. So this is the approach to go with, now let’s look at some code.

The Solution

For this solution I am using TidyNet, a great library that let’s you clean up HTML. There are a ton of features in this library but what I am concerned with is indenting, clean html, and making sure there are not stupidly placed tags (look at the above code, we don’t really need all those divs).

So let’s start by thinking about our ActionFilter. We need to access the response stream and modify the HTML right before output. We also need to take into consideration that ViewResults (output that is in html) is our only concern. Other results like JsonResult will be ignored since they aren’t HTML. We also want this to happen after the action is executed (although the approach I’ll take, it probably doesn’t matter). Beep Boop Beep, after some computing we have our action filter. Let’s look at the meat of the filter.

    public override void OnActionExecuted(ActionExecutedContext filterContext)
        {
            if (filterContext.Result is ViewResult)
            {
                var tidy = new Tidy
                               {
                                   Options =
                                       {
                                           DocType = DocType,
                                           DropFontTags = DropFontTags,
                                           LogicalEmphasis = LogicalEmphasis,
                                           XmlOut = XmlOut,
                                           Xhtml = Xhtml,
                                           IndentContent = IndentContent,
                                           HideEndTags = HideEndTags,
                                           MakeClean = MakeClean,
                                           TidyMark = TidyMark,
                                       }
                               };

                filterContext.RequestContext.HttpContext.Response.Filter =
                    new HtmlTidyFilter(filterContext.RequestContext.HttpContext.Response.Filter, tidy);
            }
        }

For this solution, we attach a filter to the response which will run at the time the response is written. Cool right? Let’s look at the meat of the filter itself, which is stream heavy but pretty straight forward. We get the HTML, clean the HTML, and then write the HTML.

            public override void Write(byte[] buffer, int offset, int count)
            {
                var data = new byte[count];
                Buffer.BlockCopy(buffer, offset, data, 0, count);
                string html = Encoding.Default.GetString(buffer);

                using (var input = new MemoryStream())
                {
                    using (var output = new MemoryStream())
                    {
                        byte[] byteArray = Encoding.UTF8.GetBytes(html);
                        input.Write(byteArray, 0, byteArray.Length);
                        input.Position = 0;
                        _tidy.Parse(input, output, new TidyMessageCollection());

                        string result = Encoding.UTF8.GetString(output.ToArray());

                        byte[] outdata = Encoding.Default.GetBytes(result);
                        _stream.Write(outdata, 0, outdata.GetLength(0));
                    }
                }
            }

So now that we have this super sweet ActionFilter, let’s use it. I place the attribute like such.

    [TidyHtml]
    [HandleError]
    public class HomeController : Controller
    {     // Controller Actions
           ...
     }

When all is run and the response is written to the page, we have the following output.

    <div id="main">
        <h2>
          About
        </h2>
        <div>
          <p>
            Put content here.
          </p>
        </div>
        <div id="footer">
        </div>
      </div>

Awesome!!! Clean HTML that makes me feel all warm and fuzzy inside and makes the web designers smile. If you are worried about this running everytime you hit an action then I suggest you use the OutputCacheActionFilter so that your pretty HTML is cached. Download the example and feel free to modify it. I exposed certain properties for TidyNet, but you can remove or add the ones you can see using in your projects. Have fun.

Aqua Bird Clean Html ActionFilter (318 kb)

Update : There is a bug in Tidy.Net that puts a break in your textarea tags. Your textareas will still work, but it will have an indent at the beginning. This can be very annoying.