Archive for the ‘ASP.NET’ Category

June 24th, 2008

MVC CAPTCHA for Preview Release 3

Since my last release of the MVC toolkit some major changes have taken place in the MVC Framework. I am going to do a quick run through of how they changed the MVC CAPTCHA for the better.

Originally in MVC Preview Release 1 for the MVC CAPTCHA many of you remember that the indicator for a valid CAPTCHA was passed through the parameters of the action method like so:

[ControllerAction]
[CaptchaValidation("captcha")]
public void Register(bool captchaValid, string otherParameters)
{
    // do stuff
}

However when Preview Release 2 came out the ability to pass the parameter through the action method was broken. So I had to create a hack around this:

[CaptchaValidation("captcha")]
public void Register(string otherParameters)
{
    bool captchaValid = (bool)RouteData.Values["captchaValid"];
    // do stuff
}

Apparently without realizing it in Preview Release 1, I had discovered a major feature that everybody that I explained it to saw great potential in. So I submitted a feature request and waited for the ASP.NET Team to get back to me. With the release of Preview Release 3, they finally answered my prayers and added the parameter injection feature back in to the framework.

So now this code works again in the Preview Release 3 version of the MVC CAPTCHA control.

[CaptchaValidation("captcha")]
public void Register(bool captchaValid, string otherParameters)
{
    // do stuff
}

This works because of a new property called ActionParameterson the ActionExecutingContext. It can be used to test and change any of the action methods parameters before the action method has been executed. For the purpose of the MVC CAPTCHA control it allows me to inject a true or false value in to a parameter called captchaValid, so that the action method knows that the CAPTCHA validation passed or failed.

public override void OnActionExecuting(ActionExecutingContext filterContext)
{
	// make sure no values are getting sent in from the outside
	if (filterContext.ActionParameters.ContainsKey("captchaValid"))
		filterContext.ActionParameters["captchaValid"] = null;

	// get the guid from the post back
	string guid = filterContext.HttpContext.Request.Form["captcha-guid"];

	// check for the guid because it is required from the rest of the opperation
	if (String.IsNullOrEmpty(guid))
	{
		filterContext.RouteData.Values.Add(”captchaValid”, false);
		return;
	}

	// get values
	CaptchaImage image = CaptchaImage.GetCachedCaptcha(guid);
	string actualValue = filterContext.HttpContext.Request.Form[Field];
	string expectedValue = image == null ? String.Empty : image.Text;

	// removes the captch from cache so it cannot be used again
	filterContext.HttpContext.Cache.Remove(guid);

	// validate the captch
	filterContext.ActionParameters["captchaValid"] =
		!String.IsNullOrEmpty(actualValue)
		&& !String.IsNullOrEmpty(expectedValue)
		&& String.Equals(actualValue, expectedValue, StringComparison.OrdinalIgnoreCase);
}

Notice in the code above all the filterContext.ActionParameters references, that is the CAPTCHA validation checking for the parameter in the method parameters list and adding the value of the CATPCHA validation to the list. Note that in order for this to work you must already have the captchaValid attribute present in your method, these actions merely fill in the value of the captchaValid placeholder.

For anybody who hasn’t used my MVC CAPTCHA control before, you only need to do two things:

1. You need to register the CAPTCHA image handler.

<httpHandlers>
    <add verb="GET" path="captcha.ashx" validate="false" type="ManagedFusion.Web.Handlers.CaptchaImageHandler, ManagedFusion" />
</httpHandlers>

2. Add the following to the View that you want the CAPTCHA to show in. Note the extension, CaptchaTextBox in HtmlHelper, generates a text box with autocomplete=”off” so that the CAPTCHA box will not have an auto-complete show up.

<label for="captcha">Enter <%= Html.CaptchaImage(50, 180) %> Below</label><br />
<%= Html.CaptchaTextBox("captcha") %>

Which generates the following.

Example of CAPTCHA

If you would like to download the latest copy of the MVC CAPTCHA it is available in my MVC Toolkit.

Download: Coder Journal MVC Toolkit
Source: Coder Journal MVC Toolkit

Tags: , ,

Posted in ASP.NET, C#, How To | kick it on DotNetKicks.com | Bookmark | View blog reactions | 4 Comments »

June 12th, 2008

Turn Google App Engine into your own Personal Content Delivery Network (CDN)

As anybody who has run a growing website or blog knows, response time is going to get worse with the more users you have visiting your site. The users come from all angles, RSS feeds, homepage visits, search engine visits, people sealing your static files that you host, and pretty much anything else that can be served over HTTP. The solution to this problem is to off load your static content on to a Content Delivery Network or CDN. CDN providers cost a lot of money though, so it is nothing for us mere mortals with one server can afford.

But thanks to Google anyone can now run their own CDN for free on Googles servers. Lucky for you and me Google has made the process really painless and you can even have the CDN under you own domain name. In my case static.coderjournal.com.

What Is A Content Delivery Network?

According to Wikipedia:

A content delivery network or content distribution network (CDN) is a system of computers networked together across the Internet that cooperate transparently to deliver content most often for the purpose of improving performance, scalability, and cost efficiency, to end users. The first web content based CDNs were Speedera, Sandpiper, Mirror Image and Skycache, followed by Akamai and Digital Island.

Basically it is a network of computers around the world that serves your content to the end user closest to one of those many servers around the world. This method of delivery cuts down on server overload, DNS hops, and delivery time.

When sites like Microsoft, Yahoo, Google, or Amazon delivery content they use Content Delivery Networks (CDN’s) to host most of their content, especially static files such as images, stylesheets, downloads and anything else you can think of. The reason they do this is to reduce load on their application servers, that serve dynamic content, such as PHP or ASP.NET pages.

What Is Google App Engine?

So you may ask what is Google App Engine:

Google App Engine lets you run your web applications on Google’s infrastructure. App Engine applications are easy to build, easy to maintain, and easy to scale as your traffic and data storage needs grow. With App Engine, there are no servers to maintain: You just upload your application, and it’s ready to serve your users.

You can serve your app using a free domain name on the appspot.com domain, or use Google Apps to serve it from your own domain. You can share your application with the world, or limit access to members of your organization.

App Engine costs nothing to get started. Sign up for a free account, and you can develop and publish your application for the world to see, at no charge and with no obligation. A free account can use up to 500MB of persistent storage and enough CPU and bandwidth for about 5 million page views a month.

Google has also announced a very very affordable price plan that any mere mortal can afford. They are not ready to start charging people yet, but here are the details:

  • $0.10 - $0.12 per CPU core-hour
  • $0.15 - $0.18 per GB-month of storage
  • $0.11 - $0.13 per GB outgoing bandwidth
  • $0.09 - $0.11 per GB incoming bandwidth

How do I setup my own CDN using Google App Engine?

To use Google App Engine you need to do a couple things that readies you computer to publish your static content to Google. Please take note that my setup is for Windows, but you can easily modify the process for any other OS.

Setup

  1. You need to download and install Python on your computer. You may already have it if you are using a Unix environment (i.e. Linux or Mac OS X). If you need to download it or would just like to check to see if it is up to date, please visit http://www.python.org/download/ and download the correct version for you operating system.
  2. Install Python to c:\Program Files\ (all my scripts that I have designed to make the publishing to Google are going to be using this path).
  3. You will also need Google App Engine SDK which is available at http://code.google.com/appengine/downloads.html. Download the version that is for you OS. Note that the SDK will check for the Python install, so make sure you install it before the SDK.
  4. Sign up for Google App Engine at http://appengine.google.com/, you will need a valid Google account. I suggest you sign up for a Google Apps account and use that as your Google account. Why I suggest this will become apparent later on.
  5. Once you are done with the setup process you need to create an application. Click the “Create an Application” and give your application a name (called “application identifier”). This is a unique name for all Google App Engine applications. For example I set my application identifier to “coderjournal”. Click though to the next part of the application, if this is your first time registering an application you need to specify your cell phone number and confirm your account with a SMS code that Google sends you.

Publish To Your CDN

  1. Download my publishing files, hosted on my CDN, at http://static.coderjournal.com/downloads/coderjournal-cdn.zip
  2. Create a directory on your computer specifically for you CDN files. My directory is c:\websites\static.coderjournal.com. Fill this directory with all your static files you want hosted on your CDN. Fill it full of all your css, downloads, flash, images, javascripts, videos, and anything else you want hosted.
  3. Unzip the files I provided to you in step 1 into the directory you created in step 2.
  4. Next we need to edit the YAML configuration file. Open the app.yaml file in your favorite text editor and change application: coderjournal to application: {your application identifier}.
  5. Next go down and edit your static directories, in mine I have css, downloads, flash, images, and js. You can create your own by just modifying the ones I put in the file.
  6. If you installed the Google App Engine SDK in the default directory and Python in c:\Program Files\ then skip to step 7. The next part is also required if you are using the x64 version of Windows, because Google App Engine SDK installs in c:\Program Files (x86)\. So change the paths in publish-cdn-coderjournal.bat to your actual paths.
  7. Now double click on publish-cdn-coderjournal.bat and a command window will display. Fill in your Google account and password that you used to sign up for the Google App Engine account. And you content will start to publish.
  8. You now have you own private CDN that can be accessed at http://application-identifier.appspot.com.

Using Your Own Domain (Optional)

  1. If you created your own Google App as suggested up in Setup step 4, you can create your own custom domain for your CDN. If you didn’t, don’t worry just create one, and follow the steps below.
  2. Go to the dashboard of your Google Apps and click “Add more services”.
  3. Under other services you will see Google App Engine and a place to enter your application identifier. Enter you application identifier and click “Add It Now”.
  4. It will take you to the next page where you enter in the domain you want for your CDN, I suggest something simple like static.yoursite.com.
  5. Then you just need to follow the steps for adding a CNAME to your DNS and you are ready to go with you custom domain.

IdeaPipe Logo

How do I use my own CDN?

Well this is the cool part! You just use the absolute path to your files. For example if you wanted to host the image to your right you would just use the following in your HTML:

Potential Gotcha: I forgot to mention that currently the files hosted statically are case-sensitive. I have reported this issue to Google, hopefully they will correct it soon. http://code.google.com/p/googleappengine/issues/detail?id=466

<img src="http://static.coderjournal.com/images/ideapipe-logo.png" />

It is really that simple. Now comes the cool part that I need your help with, and proof that this is really a true CDN. I would like to see how many different IP Addresses my CDN points to. So far I was able to find the following IP addresses:

  1. 72.14.207.121
  2. 64.233.179.121
  3. 66.249.91.121

That point to:

static.coderjournal.com

To see what IP Address you get on your local machine just pull up the command prompt and type:

ping static.coderjournal.com

Please report your findings in the comments below. I am sure everybody would love to see how big Google’s CDN really is.

Tags: , , ,

Posted in ASP.NET, How To, JavaScript, Programming, SEO | kick it on DotNetKicks.com | Bookmark | View blog reactions | 31 Comments »

June 6th, 2008

MVC + Facebook == Wonderful Development Platform

Just recently I started experimenting with the ASP.NET MVC Framework and the Facebook Development Platform, it has been a very bumpy road, but I have ironed out some major issues that I would like to share with you today. I will start with a little history of what I am trying to do. For about a month and a half I have had one of my IdeaPipe interns, Dimitry, experimenting with creating a FBML (Facebook Meta Language) Application with MVC. MVC is an ideal platform for FBML because with MVC you have total control over your markup which is needed to have a lean FBML application. I am not going to go in to the differences of developing an FBML vs IFrame Facebook Application, because that information is easily found with a Google Search. What I am going to talk about is the hurdles I overcame and the custom software I had to develop to get MVC working smoothly with Facebook.

In my last post on the subject I was using the Facebook Developer Toolkit, however because of various implementation problems that were at the foundation of the software when working with MVC, I moved to Facebook.NET which is a object based model for implementing the Facebook Session instead of an inheritance model. What you will need in order to get started is:

One of the problems I ran into was creating a Facebook Session from my Action Method. To remedy this issue I created a FacebookAttribute that is an ActionFilterAttribute and a FacebookWebSession based off of the work done on Facebook.NET.

FacebookAttribute

The FacebookAttribute is added to your Action Methods and will look like the following:

[Facebook(ApplicationName = "IdeaPipe")]
public ActionResult SomeAction(FacebookService facebookService, FacebookSession facebookSession, int myOtherVariables)
{ … }

As you can see the FacebookAttribute just attaches to the Action Method and you just have to specify your ApplicationName that you want to instantiate. The FacebookAttribute also passes in a FacebookService and FacebookSession object for use in your method. The other keys get set in your Web.Config as any standard Facebook.NET application would.

<facebook>
    <application name="IdeaPipe" apiKey="1234" secret="5678" type="GlobalApplication" />
</facebook>

The magic behind this attribute is pretty simple.

public override void OnActionExecuting(ActionExecutingContext filterContext)
{
	FacebookApplicationSettings settings = FacebookSection.GetApplication(ApplicationName);

	ApplicationKey = ApplicationKey ?? settings.ApiKey;
	Secret = Secret ?? settings.Secret;

	FacebookWebSession session = new FacebookWebSession(ApplicationKey, Secret);
	session.Initialize(HttpContext.Current);

	FacebookService service = new FacebookService(session);

	if (filterContext.ActionParameters.ContainsKey(ActionParameterFacebookSession))
		filterContext.ActionParameters[ActionParameterFacebookSession] = session;

	if (filterContext.ActionParameters.ContainsKey(ActionParameterFacebookService))
		filterContext.ActionParameters[ActionParameterFacebookService] = service;
}

Download: FacebookAttribute.cs

FacebookWebSession

The FacebookWebSession was developed out of necessity because the only other FacebookSession objects in Facebook.NET are strongly tied to a WebForms Control that couldn’t be created as easily as I did in the FacebookAttribute. I am going to fore go the source code since much of this is a copy, paste, and rearrange from the Facebook.NET source. Plus much of it is just boring if-then-else statements that go on for awhile and just do a technical setup from the query string fields.

Download: FacebookWebSession.cs

FacebookSection

This is the file that I had to change the one method from internal to public so that I could get the information contained in the Web.Config configuration for my application. Note this file will not be necessary in the future if my changes get accepted in to the Facebook.NET source tree.

This file replaces the \Web\Configuration\FacebookSection.cs of the Facebook.NET source.

Download: FacebookSection.cs
Download: Facebook.NET Binaries For MVC

So that is all that you should need in order to start working with Facebook Applications in MVC. Note that it is still a good idea to include the FacebookApplication control on your pages because it is still needed. The primary goal of the source code above was to allow the use the the FacebookSession in the Action methods. If you have any questions please post them below.

Tags: , ,

Posted in ASP.NET, C#, How To, Programming | kick it on DotNetKicks.com | Bookmark | View blog reactions | 5 Comments »

June 5th, 2008

Give Your ASP.NET Applications Velocity

Scaling ASP.NET Application just got easier with a new technology that Microsoft has just released that they have dubbed codename “Velocity”. This product is still in the early stages of development, but it is meant as a direct competitor against memcached. If you are not familiar with memcached, here is how it is described in Wikipedia:

memcached (pronunciation: mem-cache-dee) is a general-purpose distributed memory caching system that was originally developed by Danga Interactive for LiveJournal, but is now used by many other sites. It is often used to speed up dynamic database-driven websites by caching data and objects in memory to reduce the number of times the database must be read. Memcached is distributed under a permissive free software license.

So basically it allows you to create a distributed memory cache across your server farm, that allows any computer in the server farm to access the data in the cache. So there is no more issues with storing session data on server farms, or worrying about setting up common SQL stores of temporary data. This is also very practical for reducing database stress on Web 2.0 sites, many of the top Web 2.0 sites use this to reduce reads on the database.   The biggest user of memcached to date is Facebook.  This diagram below gives a basic idea of how distributed caching works.

Diagram of Velocity

There have been many Open Source projects for getting memcached working on C#, and most have been pretty successful, but because memcached was designed for the UNIX environment, porting memcached to a Windows Service has always lagged behind the actual releases of the required libraries to get memcached working. Enter Velocity, as the Velocity team describes:

Velocity is intended to provide distributed caching (in memory) for all .NET applications – from enterprise scale to web-scale. We believe that there are many applications that need a distributed caching mechanism, and that there is, therefore, a need for distributed caching as a core part of the .NET platform. We expect to have more integrated support for this functionality with other parts of the .NET platform in our upcoming releases.

There is also a pretty nice Velocity writeup on MSDN that goes in depth about how Velocity works as well as providing some basic code examples on how to get data into and out of your Velocity Cache. The current set of features looks pretty nice, and I can’t wait for Velocity to become more stable so I can introduce it in to the IdeaPipe mix.

Here is a breif overview of the Current Features:

  1. Support for different cache types, partitioned and local
  2. Support for different client types, simple and routing
  3. Load Balancing & Dynamic Scaling
  4. ASP.Net Integration, currently there is only a Session Provider
  5. Key and Tag based Access

And Beyond

  1. Availability - support for Failover when machines go down
  2. Replicated Cache - another cache type
  3. Embedded Topology - run the cache embedded within you application instead of as a cache service
  4. Notifications - Get notified when a object in the cache is updated
  5. Consistency Models - Support for both weak and strong consistency when doing reads/writes
  6. Native client access to the cache service (E.g - PHP, C++ etc)
  7. Manageability & Administration

Tags: , , , , , ,

Posted in ASP.NET, C#, Review | kick it on DotNetKicks.com | Bookmark | View blog reactions | 5 Comments »

May 27th, 2008

ASP.NET MVC Preview 3 Released

The ASP.NET MVC Team has released an refresh of MVC. To all those that are interested the new Preview Release is posted at:

http://www.codeplex.com/aspnet/Release/ProjectReleases.aspx?ReleaseId=13792

The new release contains many new features over the 2nd Preview Release and the Interim Release from a month a half ago. In this post I am going to outline the features that are new from the Interim Release to Preview Release 3.

Action Method and Result Changes

As you remember from the previous release, you are now required to return an ActionResult. Many of the ActionResults were renamed to the following types:

  • ViewResult: Renders the specified view to the response.
  • EmptyResult: Does nothing. Returned if the action method must return a null result.
  • RedirectResult: Performs an HTTP redirect to the specified URL.
  • RedirectToRouteResult: Given some routing values, uses the routing API to determine the URL and then redirects to that URL.
  • JsonResult: Serializes the specified ViewData object to JSON format.
  • ContentResult: Writes the specified text content to the response.

There were also new helper methods added to the Controller class for these new ActionResult types.

  • View: Returns a ViewResult instance.
  • Redirect: Redirects to the specified URL. Returns a RedirectResult instance.
  • RedirectToAction: Accepts an action (and optionally a controller) and redirects to another controller action. Returns a RedirectToRouteResult instance.
  • RedirectToRoute: Redirects to a URL that is determined by the routing API. For example, this method lets you specify a named route. Returns a RedirectToRouteResult instance.
  • Json: Returns a JsonResult instance.
  • Content: Sends text content to the response. Returns a ContentResult instance.

One of the more interesting ActionResults is the JsonResult which returns a serialized form of your ViewData object using the JavaScriptSerializer class. I don’t know why they didn’t use the DataContractJsonSerializer, but the team probably had their reasons.

View Data Changes

There is also the addition of implicit conversion for Action methods that return anything other than an ActionResult.

If an action method returns null (or has a return type of void), the action invoker implicitly provides an EmptyResult instance, which does nothing. If an action method returns anything other than an ActionResult instance, the action invoker calls ToString(CultureInfo.InvariantCulture) on the instance and then wraps the return value with a ContentResult object, which writes the content to the response.

A Model property was added to ViewDataDictionary. For ViewDataDictionary, the type of this property is System.Object. For ViewDataDictionary<T>, the type of this property is T.

The ViewData property of ViewPage<T> is no longer replaced by T. In Preview 2, the MVC framework replaced the ViewData property with the specified strongly typed view data (that is, the T in ViewPage<T>). In Preview 3, the Model property of ViewData is set to the instance of type T.

Route Changes

An IRouteConstraint interface was added.

If a constraint value is specified as a string, the string is interpreted as a regular expression. If the constraint value is specified as an instance of IRouteConstraint, route processing calls the Match method of IRouteConstraint.

A new HttpMethodConstraint type was added, which changes the way you constrain routes on the HTTP method. Unlike previous versions of ASP.NET routing, in this release, the constraint name “httpMethod” is no longer special. Instead, use the HttpMethodConstraint to add a constraint based on HTTP verbs. The following example shows how to use the HttpMethodConstraint type.

routes.MapRoute(
    "route-name",
    "{controller}/update",
    new {action = "update"},
    new {httpMethod = new HttpMethodConstraint("PUT", "POST")}
);

Other Changes

The versions of the System.Web.Abstractions and System.Web.Routing assemblies that are included with the MVC project template have been changed to version 0.0.0.0. The versions that are included in the Preview 3 release are newer than those that ship in the .NET Framework version 3.5 Service Pack 1 Beta. Therefore, they were assigned a private version number so that no conflict occurs between the assemblies in this release and the assemblies installed by the .NET Framework 3.5 SP1 Beta release.

And a ton of bug fixes

So in conclusion the ASP.NET MVC team has released another great release. Many of the new features have been on the request list of many of the active MVC developers. I still have to try out a couple of my requests to see if they are included, but I will make sure to provide a new post with those details.

Update: ScottGu has just released his notes on the MVC Preview Release 3, which I must admit are more in depth than my own.

Update 2: I have also updated IdeaPipe to reflect the latest PR3 changes. It took me about an hour to go through all my code and then test it. I am pleased to report the default page is now working, so that you don’t need the Default.aspx page anymore.

Tags: ,

Posted in ASP.NET, C#, Programming, Review | kick it on DotNetKicks.com | Bookmark | View blog reactions | 1 Comment »

May 18th, 2008

How to create a YUI Compressor MSBuild Task

Recently for IdeaPipe I have been looking for ways to deliver my content more quickly and reduce unnecessary bandwidth use.

According to Yahoo’s Performance Team more than half of the viewers of the Yahoo websites start with an empty cache, which means the browser has to download all the resources for the first time. This combined with a high traffic website and unneeded white space and comments can really add up to a significant bandwidth use. There are many popular ways to minify your static content tax on your bandwidth, using many popular tools, as described in this excerpt from Yahoo:

In terms of code minification, the most widely used tools to minify JavaScript code are Douglas Crockford’s JSMIN, the Dojo compressor and Dean Edwards’ Packer. Each of these tools, however, has drawbacks. JSMIN, for example, does not yield optimal savings (due to its simple algorithm, it must leave many line feed characters in the code in order not to introduce any new bugs).

The goal of JavaScript and CSS minification is always to preserve the operational qualities of the code while reducing its overall byte footprint (both in raw terms and after gzipping, as most JavaScript and CSS served from production web servers is gzipped as part of the HTTP protocol).

The cream of the crop seems to be a tool Yahoo developed to deliver its own static text content scripts and styles, the YUI Compressor:

The YUI Compressor is JavaScript minifier designed to be 100% safe and yield a higher compression ratio than most other tools. Tests on the YUI Library have shown savings of over 20% compared to JSMin (becoming 10% after HTTP compression). Starting with version 2.0, the YUI Compressor is also able to compress CSS files by using a port of Isaac Schlueter’s regular-expression-based CSS minifier.

The YUI Compressor is a Java JAR file that can be download from Julien Lecomte Blog.

The YUI Compressor yielded exceptional results, however it was missing one thing. Integration in to my build and deployment process. In IdeaPipe I use a MSBuild script to compile, manipulate, and prepare for publishing. So naturally I built a MSBuild Task to minimize my JavaScript and CSS files.

The magic actually happens by invoking Java in an external process for each file passed in to the task.

Process process = new Process();
process.StartInfo = new ProcessStartInfo {
	FileName = @"c:\program files\java\jdk1.6.0_06\bin\java.exe",
	Arguments = String.Format(
		@"-jar ""C:\development\tools\yuicompressor-2.3.5.jar"" --type {0} --charset utf8 {1} -o ""{2}"" ""{3}""",
		type,
		ShowWarnings ? "--verbose" : String.Empty,
		newFile,
		oldFile
		),
	UseShellExecute = false,
	CreateNoWindow = true,
	RedirectStandardOutput = true,
	RedirectStandardError = true
};
process.Start();
process.WaitForExit(5000);

Then I read the warning from the standard error output and send them back to Visual Studio as a compile warning if the ShowWarning property is true.

string[] warnings = process.StandardError.ReadToEnd()
	.Replace(”\r”, String.Empty)
	.Split(new string[] { “\n\n” }, StringSplitOptions.RemoveEmptyEntries);

foreach(string warning in warnings)
	Log.LogWarning(null, null, null, oldFile, 1, 1, 1, 1, FormatWarning(warning), null);

To integrate this in to my MSBuild script I had to first register my task:

<UsingTask TaskName="ManagedFusion.Build.YuiCompress" AssemblyFile="$(ProjectDir)..\ManagedFusion.Build\bin\$(ConfigurationName)\ManagedFusion.Build.dll"/>

Then setup my ItemGroup for the files:

<ItemGroup>
	<JavaScriptContent Include="$(SourceWebPhysicalPath)\**\*.js" />
	<CssContent Include="$(SourceWebPhysicalPath)\**\*.css" />
</ItemGroup>

Then finally I setup my task to perform the minimization against the JavaScript and CSS files seperately:

<Target Name="AfterBuild">
	<!-- do other stuff to prepare for publishing -->
	<YuiCompress Files="@(JavaScriptContent)" Type="JS" />
	<YuiCompress Files="@(CssContent)" Type="CSS" />
</Target>

You can easily incorporate this in to your own MSBuild scripts or even your Visual Studio Project which is just an MSBuild file for compiling your source code for the project. I have included my source code below:

Download: YUI Compressor MSBuild Task Source

Note: There are a couple of static paths to be on the look out for and modify as necessary for your own code. In my code the Java runtime is loaded at c:\program files\java\jdk1.6.0_06\bin\java.exe and the YUI JAR is located at C:\development\tools\yuicompressor-2.3.5.jar.

Update (2008-5-21): Thanks George, apparently IIS doesn’t like serving straight C# files. So I added the code to my Coder Journal Source Control, so that it can be downloaded from there.

Tags: , , , , ,

Posted in ASP.NET, How To, Programming | kick it on DotNetKicks.com | Bookmark | View blog reactions | 7 Comments »

April 16th, 2008

ASP.NET MVC Interim Released

The ASP.NET MVC Team has released an refresh of MVC. To all those that are interested the new Interim Release is posted at:

http://www.codeplex.com/aspnet/Release/ProjectReleases.aspx?ReleaseId=12640

The new release seems to rely on a non-CodePlex open source project.  Is this the first sign of Microsoft’s commitment to open source?

The Release Notes have a lot of good information about new features and bug fixed included in this release:

This CodePlex refresh of the ASP.NET MVC source code includes a number of key changes and refactorings.
To see a full list of API changes, take a look at the attached zip file produced using
Framework Design Studio.

MVC Changes Since Preview 2

  • Action methods on Controllers now by default return an ActionResult instance, instead of void.
    • This ActionResult object indicates the result from an action (a view to render, a URL to redirect to, another action/route to execute, etc).
    • Each “result” is a type that inherits from ActionResult. To render a view, return a RenderViewResult instance.
  • The RenderView(), RedirectToAction(), and Redirect() helper methods on the Controller base class now return typed ActionResult objects (which you can further manipulate or return back from action methods).
  • The RenderView() helper method can now be called without having to explicitly pass in the name of the view template you want to render.
    • When you omit the template name the RenderView() method will by default use the name of the action method to determine the view template to render.
    • So calling RenderView() with no parameters inside the About() action method is now the same as explicitly writing RenderView(’About’).
  • Introduced a new IActionFilter interface for action filters. ActionFilterAttribute implements IActionFilter.
  • Action Filters now have four methods they can implement representing four possible interception points.
    • OnActionExecuting which occurs just before the action method is called.
    • OnActionExecuted which occurs after the action method is called, but before the result is executed (aka before the view is rendered in common scenarios).
    • OnResultExecuting which occurs just before the result is executed (aka before the view is rendered in common scenarios).
    • OnResultExecuted which occurs after the result is executed (aka after the view is rendered in common scenarios).
    • NOTE: The OnResult* methods will not be called if an exception is not handled during the invoking of the OnAction* methods or the action method itself.
  • Added a MapRoute extension method (extension on RouteCollection) for use in declaring MVC routes in a simpler fashion.

NOTE: It is pretty easy to update existing Controller classes built with Preview 2 to use this new pattern (just change void to ActionResult and add a return statement in front of any RenderView or RedirectToAction helper method calls).

Routing changes since Preview 2

  • URLs may contain any literal (except for /) as a separator between URL parameters. For example, instead of {action}.{format} you can now have {action}-{format}. For more details on changes, see this post.
  • Routing is ignored for files that exist on disk by default. This can be overriden by setting the RouteTable.Routes.RouteExistingFiles property to true (it is false by default).

Tags: ,

Posted in ASP.NET | kick it on DotNetKicks.com | Bookmark | View blog reactions | 2 Comments »

April 13th, 2008

Coder Journal’s MVC Toolkit

Today I decided to release a toolkit that I have been building over the past couple of months. Most of the code in the toolkit is related to MVC. Here is a list of the features:

ActionFilterAttribute’s

  • HttpPostOnlyAttribute
    Only allows POST to be made against the action.
  • CacheAttribute
    Sets the action’s response as cacheable.
  • CompressAttribute
    Compresses the action’s response using GZip or Deflate encoding.
  • ServiceAttribute
    Marks an action as able to provide the ViewData as JSON, XML, or JSONP.
  • ServiceOnlyAttribute
    Marks an action as only able to provide the ViewData as JSON, XML, or JSONP, that means no HTML.
  • ExceptionHandlerAttribute
    Handles any exceptions thrown from an action, and redirects it to another page, or another action.
  • CaptchaAttribute
    I did a whole post on providing a CAPTCHA for your MVC action.
  • AllowedHttpMethodsAttribute
    Only the HTTP methods entered in to this filter are allowed for your action. Available HTTP methods are OPTIONS, GET, HEAD, POST, PUT, DELETE, TRACE, and CONNECT.

ViewEngines’s

  • ServiceViewEngine
    This view engine provides the serialization of the ViewData to JSON, XML, or JSONP. It is set when one of the following is requested from the ServiceAttribute above.

Route’s

Method Extensions

  • Redirect extends HttpResponse
    I have had a long standing discontent with the Redirect method of the ASP.NET. I have talked about good use of HTTP Status Codes before. There are at least 3 status codes that you want to consider before choosing a response status code of 302. Just to reiterate my post on the subject use 303 to redirect from a form POST, use 307 when you want to redirect to a page that is going to change with each request, use 301 if you want to permanently redirect one URL to another.I created the, Redirect, extension method on HttpResponse so that the status code could be set for the redirect.

View Source: Coder Journal MVC Toolkit Source
Download Binary: Coder Journal MVC Toolkit Binary

Read the rest of this entry »

Tags: , ,

Posted in ASP.NET, C#, Personal | kick it on DotNetKicks.com | Bookmark | View blog reactions | 9 Comments »

April 11th, 2008

Creating a Facebook Application using MVC

Facebook has been growing in popularity ever since it was released on February 4th 2004 at an almost unstoppable pace. Up until May 24th, 2007, it wasn’t much different than MySpace (or insert your favorite social network here), however on that day they rolled out a SDK that turned Facebook from a destination website to a platform that let any developer interact with their almost 71 million users. You can read more about the history of Facebook at Wikipedia.

My focus today isn’t on how to develop your first Facebook application in ASP.NET, because there are already many great articles on that, and even some starter kits. My focus is going to be on developing your first Facebook application with ASP.NET MVC, however this article will assume that you have the basic understand FBML (Facebook Meta Language) and MVC. If you do not have one or the other don’t worry, both are very easy to pick up on, and both have a very active developer community to answer questions.

So now that, that is out of the way lets start looking at what we need to make your MVC application in to a Facebook compatible application. The first thing you will need is the Facebook Developers Toolkit which is free on CodePlex. The second thing you will need is my Facebook MVC Web Controls which is a modification of the tookit’s Facebook.WebControls.dll made specifically for MVC. The third thing you need is ASP.NET MVC Preview 2 which is also available for free on CodePlex.

My tookit extension consists of the following classes, that mimic the current classes already in Facebook Developers Toolkit:

  • CanvasFbmlViewPage
  • CanvasFbmlViewPage<TViewData>
  • CanvasFbmlViewMasterPage
  • CanvasFbmlViewMasterPage<TViewData>
  • CanvasIFrameViewPage
  • CanvasIFrameViewPage<TViewData>
  • CanvasIFrameViewMasterPage
  • CanvasIFrameViewMasterPage<TViewData>

Facebook IFrame Application

I will start with the IFrame stuff since that is very easy and doesn’t require FBML knowledge. To create a Facebook IFrame application just follow the directions at Facebooks Getting Started Website for an IFrame. Then create an MVC Preview 2 application in Visual Studio. Then change the following in the CodeBehind for each of your pages.

public partial class Index : ViewPage

to

public partial class Index : CanvasIFrameViewPage

That is all you have to do to get Facebook working with your MVC application through IFrames. You don’t need to change your HTML because you site is going to render through an IFrame so there is no processing that is done in regards to UI rendering for Facebook. This has some drawbacks including not having the familiar Facebook interface, however this is the easiest way to get running on a Facebook app.

Facebook FBML Application

Creating the C# part of an FBML application for MVC is just as easy creating creating the IFrame application.

public partial class Index : ViewPage

to

public partial class Index : CanvasFbmlViewPage

Nothing spectacular there. Before we get started with the FBML application there is a tool that shows you what your FBML will look like when rendered out to HTML. However the real power of MVC is about to shine when we create a simple Facebook application using FBML and the ASP.NET MVC framework. Basically I took the default MVC application and modified the Index.aspx page to look like this.

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Index.aspx.cs" Inherits="MvcFootprints.Views.Home.Index" %>
<div style="padding: 10px">
    <h2>Hi <fb:name firstnameonly="true" uid="<%= this.FBService.UserId %>" useyou="false" />!</h2>
    <form method="post" action="http://apps.facebook.com/coderjournal/">
        Get friend:
        <fb:friend-selector idname="friend" />
        <input value="find" type="submit" />
    </form>
    <hr />
    <fb:if-can-see uid="<%= Request.Forms["friend"] %>”>
    <div style=”clear: both; padding: 3px;”>
        <fb:profile-pic style=”float: left;” uid=”<%= Request.Forms["friend"] %>” size=”square” />
        <fb:name uid=”<%= Request.Forms["friend"] %>” capitalize=”true” />
    </div>
    </fb:if-can-see>
</div>

This isn’t very spectacular, all that it does it provide a friend list drop down, and submit it back to get their picture and name. But it gives the basic idea how to inner-mix FBML markup like <fb:name /%gl; and HTML with MVC. So basically that is your first Facebook application with MVC, nothing to it right?

That is really the beautiful thing about MVC, it makes writing simple applications that much simpler than ASP.NET Web Forms because you don’t have to deal with controls and it is encouraged to do processing inline with your markup. Happy coding. As always you can find the source code to this and my other projects in Coder Journals Source Control Repository.

Tags: , , , ,

Posted in ASP.NET | kick it on DotNetKicks.com | Bookmark | View blog reactions | 6 Comments »

March 31st, 2008

Force MVC Route URL to Lowercase

So one of my pet peeves in web development is mixed case URL’s. And I usually make sure that all my URL’s in my personal projects follow this standard. I also believe, contrary to my URL case standard, that my code should follow standards .NET naming techniques, such as Pascal casing for my method names.

These two naming standards come in to conflict with MVC because the name of the action method in the controller is used in its native Pascal case. Which generates URL’s that look like this:

/Home/Index
/Home/About

However I want them to be generated like this:

/home/index
/home/about

So I developed my own Route based off of the System.Web.Routing.Route to force everything to lowercase.

public class LowercaseRoute : System.Web.Routing.Route
{
	public LowercaseRoute(string url, IRouteHandler routeHandler)
		: base(url, routeHandler) { }
	public LowercaseRoute(string url, RouteValueDictionary defaults, IRouteHandler routeHandler)
		: base(url, defaults, routeHandler) { }
	public LowercaseRoute(string url, RouteValueDictionary defaults, RouteValueDictionary constraints, IRouteHandler routeHandler)
		: base(url, defaults, constraints, routeHandler) { }
	public LowercaseRoute(string url, RouteValueDictionary defaults, RouteValueDictionary constraints, RouteValueDictionary dataTokens, IRouteHandler routeHandler)
		: base(url, defaults, constraints, dataTokens, routeHandler) { }

	public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
	{
		VirtualPathData path = base.GetVirtualPath(requestContext, values);

		if (path != null)
			path.VirtualPath = path.VirtualPath.ToLowerInvariant();

		return path;
	}
}

For anybody as anal as me about stupid stuff such as casing of URL’s you should find this class up above a welcomed addition to your MVC projects.

Tags: , ,

Posted in ASP.NET, C# | kick it on DotNetKicks.com | Bookmark | View blog reactions | 6 Comments »