Posts Tagged ‘MVC’

May 11th, 2009

Creating Your First MVC ViewEngine

A question that I have been hearing a lot lately is:

How do I change the view location in MVC?

But what they really mean to say is:

How do I create a new ViewEngine that uses the view locations of my choosing?

It is actually very simple to do, and once you see it, I think you will agree with my assessment.  The first thing we are going to do to create our custom ViewEngine, is define the paths that we want to use for our master pages, view pages, and shared pages.  I have taken the liberty to define the following paths, you can customize them however you wish:

  • Master Pages:
    ~/Templates
    it use to be ~/Views/Shared or the controllers view
  • View Pages:
    ~/Views
  • Shared Pages:
    ~/Common
    it use to be ~/Views/Shared

The next thing we need to do is create a new class for our ViewEngine, for this example we are going to call it SimpleViewEngine.

public class SimpleViewEngine : VirtualPathProviderViewEngine
{
}

As you might have noticed from above our SimpleViewEngine inherits from VirtualPathProviderViewEngine, this is the root ViewEngine that uses the VirtualPathProvider (VPP). The VPP provides a way for web applications to read files off the file system in their local web application, so it is perfect for what we are doing. If you don’t want a file system based ViewEngine, and maybe want a ViewEngine based from the database, you can use the IViewEngine interface to create your own custom ViewEngine that fits your needs. (MVC is very flexible, by design)

The next thing we need to do is code our paths in to our SimpleViewEngine. We will do this in the constructor, so that they only have to be initialized once for the entire life span of our SimpleViewEngine.

public SimpleViewEngine ()
{
	/* {0} = view name or master page name
	 * {1} = controller name
	 */

	// create our master page location
	MasterLocationFormats = new[] {
		"~/Templates/{0}.master"
	};

	// create our views and common shared locations
	ViewLocationFormats = new[] {
		"~/Views/{1}/{0}.aspx",
		"~/Common/{0}.aspx",
	};

	// create our partial views and common shared locations
	PartialViewLocationFormats = new[] {
		"~/Views/{1}/{0}.ascx",
		"~/Common/{0}.ascx"
	};
}

As you can see the format is pretty straight forward. We create a string[] array with the paths of where our master pages, views, and common views are located. The only thing that we need to do is set place holders in our path so the the VirtualPathProviderViewEngine can replace the master name, view name, and controller name to construct our appropriate path.

  • {0}: is the view name or master page name.
  • {1}: is the controller name.

After we have done the hard part, which honestly wasn’t that hard, of creating the constructor with the paths, we just need to return the view objects from the constructed partial paths. Since we are using the standard ASP.NET Web Form (ASPX/ASCX) rendering engine. We are able to leverage the work already done by the MVC team and just return a new instance of the WebFormView object.

protected override IView CreatePartialView(ControllerContext controllerContext, string partialPath)
{
	return new WebFormView(partialPath, null);
}

protected override IView CreateView(ControllerContext controllerContext, string viewPath, string masterPath)
{
	return new WebFormView(viewPath, masterPath);
}

Nothing really earth shattering here, just simply filling out the constructor with the proper parameters from our method, and then returning the newly created view. If you wanted to create a view based out of the database, or off your own syntax (meaning not ASP.NET syntax) then you would have to create your own view based off of the IView interface. But for this example we are only concerned with changing where our views are located.

There is one more thing that we need to do, and that is register our new SimpleViewEngine for use in the framework. The registration of view engines is done in the Global.asax, similar to the same way we register new routes.

public static void RegisterViewEngines(ViewEngineCollection viewEngines)
{
	viewEngines.Clear();
	viewEngines.Add(new SimpleViewEngine());
}

public static void RegisterRoutes(RouteCollection routes) { ... }

protected void Application_Start()
{
	RegisterRoutes(RouteTable.Routes);
	RegisterViewEngines(ViewEngines.Engines);
}

So we are now done. You have created a new view engines, defined your own routes, and registered this view engine with the MVC framework. Some other types of paths you may want to consider trying for your applications, using a custom ViewEngine, are special folders for your mobile or Facebook versions of your website.

  • Mobile: ~/Views/{1}/Mobile/{0}.aspx
  • Facebook: ~/Views/{1}/Facebook/{0}.aspx

I told you it was simple and straight forward, and I hope you agree that the MVC team has done an awesome job at providing a very flexible framework for us to tweak and customize it so it fits our applications.

Tags: , ,

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

October 28th, 2008

ASP.NET MVC Has Changed My Life

Lately I have been neglecting my blog and not posting as often as I would have liked.  I have had some very exciting things start up, at the begining of the summer, in my life that 6 months ago I would have said “no way is that going to happen.”  These new adventures are the growing popularity of my blog, public speaking engagements, and a new book I was asked to write on ASP.NET MVC. Many of you picked up on the fact that I was writing a book based on my profile on the Philly.NET website, but I had officially announced it until this post.  Many of my friends and family don’t even known I am writing a book so feel lucky in knowning you guys are some of the first people to know.

As you can imagine writing a book is about the same as writing a detailed blog post only 10,000% harder, because a two page post now needs to be extended out in to a 600 page book that needs to flow just as easily as the 2 page post did.  Luckily for me my best friend, Al Katawazi who I have known since 9th grade, is also a pretty decent programmer from the Rochester, NY area and he agreed to help me get this book out the door by the end of the year to align with the ASP.NET MVC release.

The book is titled ASP.NET MVC Website Programming: Problem - Design - Solution, and can currently be found at the following places for pre-order:

Sorry about the lack of a book picture, I haven’t had the time to go out and get a professional photo taken of me for the cover.  That will be coming pretty soon.

The current description of the book according to the Wiley site is, which also pretty well sums up the book as a whole in my opinion:

The utility of this book will be a nuts and bolts how-to guide on creating a website using MVC.  It will solve some of the most common problems that programmers run into when creating their first application or when trying to upgrade a current application to this new technology.

The book, much like the first one, will break each section down into 3 parts: the Problem, the Design, and the Solution.  For the most part, the chapter outline will be mostly the same, because the majority of the chapters are still just as important now to web developers as they were when the book was originally written. However, this edition includes MVC updates within these chapters.

Some of the site features covered in the book and provided in the TheBeerHouse example/framework code are:

  • registration and membership system and user-selectable themes
  • content management system for articles and photos
  • polls, mailing lists, and forums
  • e-commerce store, shopping cart, order management with real-time credit-card processing
  • localization

In building and working with these features the site developer will learn:

  • Master pages, themes, membership, and profiles
  • Server-side UI controls
  • Compilation, deployment, instrumentation, error handling and logging
  • Data access
  • The MVC (model view controller) approach to separation of the site UI and presentation layer from the pluggable data access layer and business logic layer

The code for the book will be published to CodePlex probably this weekend, that is if you want a sneak peak at what has taken me away from posting on my blog for the past couple of months.

http://www.codeplex.com/TheBeerHouse

If you want to wait for the book I totally understand, because who wants to spoil Christmas by peaking at the presents.  I am just kidding, I don’t think my code can be compared to Christmas morning, but maybe the 3rd Tuesday morning of October.

All kidding aside I really have to thank Scott Guthrie, Phil Haack and the whole ASP.NET MVC, because with out the great support for this product and the fore sight of Microsoft to actually create a product that ALT.NET developers like my self have been crying out for. I wouldn’t be in this place in my life.  I never thought that an interest in a small alpha release of a product back in December 2007 would lead me to writing a book, but it has been a great ride and I only hope it continues.

I am going to continue to try and post content that is useful to other developers like myself as much as I can, but please bear with me until the end of the year when all my chapters will be written and the book will be getting ready for the presses.

Tags: , , , ,

Posted in News, Personal | kick it on DotNetKicks.com | Bookmark | View blog reactions | 7 Comments »

October 16th, 2008

ASP.NET MVC Goes Beta (Part 2)

From what I can tell ASP.NET MVC Beta is just ASP.NET MVC PR5 with a couple bug fixes.  So the good news is that the interface has finally solidified and we shouldn’t see anymore breaking changes before the final release.

New features:

  • MvcFutures.dll is not included in the beta (as it wouldn’t be included in the final release)
  • The Beta installer installs the ASP.NET MVC assemblies (System.Web.Mvc.dll, System.Web.Routing.dll, and System.Web.Abstractions.dll) into the GAC.
  • New Simple Membership Features in the Default Project Template
  • New Filter Types for Authorization and Exception Handling
  • New Output Cache Filter
  • Changes for ASP.NET AJAX
  • Namespaces in Routes
  • New Interface for Enhanced Testability of TempData
  • ActionInvoker Extensibility Improvements
  • ViewDataDictionary (minor change)
  • ViewEngine Improvements
  • Helper Improvements
  • Controller and Filter Improvements

Bug fixes:

  • Fixed a bug in which the ignore-routes setting (created by using the IgnoreRoute extension method) affected URL generation.
  • Fixed a view engine caching bug when the application is not in debug mode (that is, when debug=”false” is set in the Web.config file). This bug occurred if different action methods in different controllers had the same name. In that case, an action method could render the view for the wrong controller.
  • Fixed a bug in OutputCacheAttribute in which cached authenticated content did not require authentication. Even though the content is cached, if it requires authentication, the user should be required to authenticate first before seeing the cached content.
  • Fixed a bug in which RenderPartial does not work when tracing is turned on.
  • Fixed a bug in the Html.TextArea helper method in which an overload was not looking in ViewData for its value when the provided value is null.
  • Fixed the OutputCacheAttribute.CacheProfile property so that it works in Medium Trust.

Update: Derik at Dimecast.net has found some things I overlooked.  Nothing life changing, just some house cleaning on the teams part.

Tags: ,

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

October 16th, 2008

ASP.NET MVC Goes Beta

Wow has it really been 10 months since I first started using MVC. We have hit our first beta today. No information about what has changed, I will make sure to keep you all updated. But get it while it is hot: http://www.microsoft.com/downloads/details.aspx?familyid=a24d1e00-cd35-4f66-baa0-2362bdde0766

For everybody who hasn’t heard of MVC, how couldn’t you have heard about it now if you are a regular reader of my blog.  But for all the new people visiting, here is an overview:

Overview
The ASP.NET MVC Beta release provides a new Model-View-Controller (MVC) framework on top of the existing ASP.NET 3.5 runtime. This means that developers can take advantage of the MVC design patterns to create their Web Applications which includes the ability to achieve and maintain a clear separation of concerns (the UI or view from the business and application logic and backend data), as well as facilitate test driven development (TDD). The ASP.NET MVC framework defines a specific pattern to the Web Application folder structure and provides a controller base-class to handle and process requests for “actions”. Developers can take advantage of the specific Visual Studio 2008 MVC templates within this release to create their Web applications, which includes the ability to select a specific Unit Test structure to accompany their Web Application development.

The MVC framework is fully extensible at all points, allowing developers to create sophisticated structures that meet their needs, including for example Dependency Injection (DI) techniques, new view rendering engines or specialized controllers.

As the ASP.NET MVC framework is built on ASP.NET 3.5, developers can take advantage of many existing ASP.NET 3.5 features, such as localization, authorization, Profile etc.

Tags: ,

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

September 28th, 2008

jQuery and Visual Studio Shipping Together

I have been a huge fan of jQuery ever since I started working on IdeaPipe about 10 months ago. Mostly because of its simplistic DOM access using standard CSS syntax that we all have to learn anyways in the modern Web 2.0 world. In addition to the ease of finding elements on your page, it also works very nicely with other frameworks, I have used it in combination with Microsoft AJAX, Google’s GData JavaScript, and TinyMCE.

Personally I found this to be amazing news, because Microsoft is shipping an Open Source project, licensed under MIT License, with its flag ship developer tool, Visual Studio.  Maybe if we play our cards right, we can start seeing other projects like NUnit and Moq start to ship with Visual Studio.  I have my fingers crossed.

John Resig the developer of jQuery had this to say on his blog:

Microsoft is looking to make jQuery part of their official development platform. Their JavaScript offering today includes the ASP.NET Ajax Framework and they’re looking to expand it with the use of jQuery. This means that jQuery will be distributed with Visual Studio (which will include jQuery intellisense, snippets, examples, and documentation).

And according to Scott Guthrie, Microsoft is also extending the standard product support to jQuery:

We will also extend Microsoft product support to jQuery beginning later this year, which will enable developers and enterprises to call and open jQuery support cases 24×7 with Microsoft PSS.

This is probably some of the most exciting, because it means that jQuery will be a supported stack in some of the more rigid enterprise development environments that won’t install anything that isn’t supported by Microsoft.  I also beleive this is great news for MVC, because jQuery makes MVC just that much more useful for the average developer.

Tags: , ,

Posted in News | kick it on DotNetKicks.com | Bookmark | View blog reactions | No Comments »

September 11th, 2008

Philly .NET User Group Meeting for September 2008

I will be presenting September 17, 2008 at Philly .NET User Group Meeting.  My talk will be on:

Creating a modern, web 2.0, application with MVC and jQuery with a focus on doing this in a RESTful manor.  My goal is for the developers in attendance to learn how to create a RESTful website design using MVC and implement that RESTful design on the front end with some simple jQuery. These principals will be demonstrated by creating a simple Twitter like application for sharing messages. All the source code will be available via my website at http://www.coderjournal.com after the presentation.

The group will be meeting at the Microsoft Malvern Campus, located at 45 Liberty Blvd, Malvern, PA 19355.

If you think you might attended the meeting please make sure to register, so that Bill has an accurate count for the food order.

philly.net

User Group News

* Please distribute this notice throughout your development community!
We have some great meetings lined up for the next few months. Please take a look at the upcoming schedule on the web site.
September 17 ASP.NET Dynamic Data, MVC & Web 2.0
Wednesday

Malvern, PA

Our monthly meeting will be held at the Microsoft Greater PA Office in Malvern, PA on Wednesday, September 17 from 5:30-8:30. Refreshments are provided courtesy of Vovéo Marketing Group. Please register on our web site. Detailed directions are on the Microsoft Greater PA web site.
5:30 Rachel Appel, Appel Consulting An Introduction to ASP.NET Dynamic Data
Rachel Appel, Appel Consulting If you are tired of the same old ASP.NET webforms, GridViews, and ADO.NET data access code that make up your current applications, then you’ll want to take a closer look at ASP.NET Dynamic Data.  ASP.NET Dynamic Data is Microsoft’s new technology that provides a template infrastructure for your application, page and fields based on your application’s data model. In this session you will learn concepts and use of application templates to create ASP.NET dynamic data web application. We’ll then create customizations at the application and page levels showing how easy website maintenance is when using ASP.NET Dynamic Data. We’ll also cover field level customizations by supplying data display formats, custom field types, and data validation based on the application’s data model.

Rachel Appel lives in Northeastern Pennsylvania and is the senior technology consultant at Appel Consulting. Rachel is an MVP and a member of ASPInsiders, and holds the MCT MCAD & MCSD certifications.  She has been working as an instructor, software developer, architect and DBA for a wide variety of organizations. She is the Vice President and a regular speaker of the dotNetValley user’s group, as well as an active member in other local user groups of Northeastern Pennsylvania and the tri-state area.  Rachel’s expertise lies within developing solutions that align business and technology using the Microsoft .NET family of products.

6:45 Q&A Rob Keiser & Dani Diaz, philly.net co-leaders, ask questions, get answers from your peers!
7:00 Break Meet your peers. Refreshments and drinks courtesy of Vovéo Marketing Group.
7:15 Nicholas Berardi, Vovéo Marketing Group MVC & Web 2.0
Nicholas Berardi, Vovéo Marketing Group Creating a modern, web 2.0, application with MVC and jQuery with a focus on doing this in a RESTful manor.  My goal is for the developers in attendance to learn how to create a RESTful website design using MVC and implement that RESTful design on the front end with some simple jQuery. These principals will be demonstrated by creating a simple Twitter like application for sharing messages. All the source code will be available via my website at http://www.coderjournal.com after the presentation.

Nicholas Berardi works for Vovéo Marketing Group in Malvern, PA as a Software Architect.  He is the co-author of ASP.NET MVC Website Programming, Problem, Design, Solution published by Wrox and will be released early 2009.  He received his BS in Information Science and Technology from The Pennsylvania State University in 2003.  Nick has been using C# and the .NET framework since its beta and has over 10 years of experience in web development and related technologies. He helped to develope one the first websites on the internet to use the ASP.NET MVC framework, in a production environment, at http://www.ideapipe.com.  He blogs at http://www.coderjournal.com.

8:30 Closing & Raffle! Books, software, and other goodies!

Tags: , , ,

Posted in News, Personal | kick it on DotNetKicks.com | Bookmark | View blog reactions | No Comments »

August 29th, 2008

ASP.NET MVC Preview Release 5

Looks like the MVC team has put out preview release 5 of the MVC Framework today.  You can get the latest version from CodePlex.

Here is what I can tell has changed from the release notes.

What’s New

  • Added global registration of view engines
  • Changed the IViewEngine interface to add the RenderParial method
  • Added support for rendering partial views
  • Added a parameter to specify a default option label for DropDownList controls
  • Moved ASP.NET AJAX extension methods to a separate namespace
  • Added helpers for RadioButton and TextArea controls and made overall improvements to other helpers.
  • Removed helper method overloads to avoid ambiguity
  • Added array support for action method parameters
  • Removed the ActionMethod property from action filter context objects
  • Added support for custom model binders
  • Added an IActionInvoker interface
  • Added an UpdateMode method to the Controller class
  • Changed HandleErrorAttribute so that it does not handle exceptions when HttpContext.IsCustomErrorEnabled is false
  • Added a new AcceptVerbs attribute
  • Added a new ActionName attribute

Known Issues and Breaking Changes

  • Controller class now is derived from ControllerBase class
  • Controller.Execute as removed, it is not called ExecuteCore.
  • Controller initialization steps should be done in Initialize method now.
  • IViewEngine interface is now responsible for finding views, not rendering them.
  • Some overloads to some helper methods have been removed.
  • AJAX helper methods have been moved to a new namespace.
  • This version is incompatible with Visual Studio 2008 SP1 Beta

Upgrading from Preview 4 to Preview 5

  • System.Web.Abstractions and System.Web.Routing have been changed to version 3.5.0.0
  • Assemblies are located at %ProgramFiles%\Microsoft ASP.NET\ASP.NET MVC CodePlex Preview 5

Derik also noticed that many of the classes are still sealed, and is requesting that the team un-seals all classes, and I agree with him.

Breaking and mysterious changes that I have submitted a bug request for:

Update (2008-8-31): Also Derik found a replacement for RenderUserControl, very minor change, but it is the difference between a error and having the thing work.

Tags: ,

Posted in News | kick it on DotNetKicks.com | Bookmark | View blog reactions | 3 Comments »

August 13th, 2008

Using a Parameter Attribute to set a Default Value in MVC

A couple days ago I came across a breaking change in ASP.NET MVC PR4 that wasn’t reported.  The breaking change is that defaults from routes are no longer used as defaults for parameters in the action method, if no appropriate parameter is found in the request.  Basically what this means is the following:

I have the following route:

URL: /home
Controller: Home
Action: Index
Defaults = page: 1

I set the page so that it always defaults to “1″ if no value is found in the query string for “page”.

So when a request is executed, the Route passes back the RouteData.Values = controller: “Home”, action: “Index”, page: 1. Then it goes through it’s normally processing and the value of the page’s query string is passed in to my action method for the page parameter. So if query string page = 1 then 1, query string page = 2 then 2, and so on. This is how it worked in PR3 and how I understood it was suppose to work as a concept.

However, in PR4, this doesn’t work anymore because of Line 166 in ControllerActionInvoker. It specifically checks that the value is in the route values. However they are always going to be in the route values if they have been defined as a default.

I reported it as a bug, because it was an obvious break from the last 3 preview releases and nothing was reported about this breaking change, and went on my merry way.  However today I received a message back from auriel confriming that this was the correct process flow, and that I should set the parameter either in my action method or the action filter.

So I decided to take this obvious disapointment and turn it in to something I have been thinking about for a long time, but never really had the motivation to impliment.  In .NET you are allowed to add attributes to anything that can be defined via reflection, including classes, interfaces, structures, and even return types and parameters of methods.  So I created an attribute called DefaultAttribute that is a parameter attribute that can be added to your action methods like this:

public ActionResult Index([Default(1)]int? page)

This method tells us that page has a default value of 1 if the value of page is null or undefined.  The DefaultAttribute is rather simplistic, because it is only suppose to hold the default value:

[AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false)]
public class DefaultAttribute : Attribute
{
	public DefaultAttribute(object @default)
	{
		if (@default == null)
			throw new ArgumentNullException("default");

		Default = @default;
	}

	public object Default
	{
		get;
		private set;
	}
}

As you can see from the above code I have told the attribute to only allow it to be attached to a parameter by specifying this in the AttributeUsageAttribute.  The next and last thing that we need inorder to complete our goal of being able to set the defaults in a parameter attribute is an action filter that can read the DefaultAttribute from the parameter and set the default if the parameter value is null or undefined.  We are going to process the parameter defaults in an action filter called UseActionParameterDefaultAttribute that can be attached to the controller or direction to the action method.  The code to process the defaults is:

public override void OnActionExecuting(ActionExecutingContext filterContext)
{
	var defaults = GetDefaults(filterContext);
	var actionParameters = filterContext.ActionParameters;
	foreach (var value in defaults)
		if (actionParameters[value.Key] == null)
			actionParameters[value.Key] = value.Value;
}

internal static IDictionary>string, object< GetDefaults(ActionExecutingContext filterContext)
{
	string key = filterContext.ActionMethod.ToString() + "_ParameterDefaults";

	// get from application storage
	IDictionary>string, object< defaults = filterContext.HttpContext.Application[key] as IDictionary>string, object<;

	if (defaults == null)
	{
		defaults = new Dictionary>string, object<(filterContext.ActionParameters.Count);
		foreach (var parameter in filterContext.ActionMethod.GetParameters())
		{
			if (parameter.IsDefined(typeof(DefaultAttribute), false))
			{
				DefaultAttribute attr = parameter.GetCustomAttributes(typeof(DefaultAttribute), false)[0] as DefaultAttribute;
				string parameterName = parameter.Name;
				string actionName = filterContext.ActionMethod.Name;

				try
				{
					defaults.Add(parameterName, ConvertParameterType(attr.Default, parameter.ParameterType, parameterName, actionName));
				}
				catch (Exception exc)
				{
					throw new InvalidOperationException(String.Format(
						CultureInfo.CurrentUICulture,
						"The value of the DefaultAttribute could not be converted to the parameter '{0}' in action '{1}'.",
						parameterName, actionName), exc);
				}
			}
		}

		// add to application storage
		filterContext.HttpContext.Application[key] = defaults;
	}

	return defaults;
}

Each parameter of the action method is scanned for a DefaultAttribute and if found is added to the defaults dictionary to be used later when checking if each parameter is null or undefined in the OnActionExecuting method. Creating this code actually led to another request for the MVC team. The request was for a static storage collection for each action method so that compile-time code like attributes on the parameters don’t have to be processed with each request, since they can only possibly change when the code is recompiled. So I have my fingers crossed that they will actually implement this feature. In the mean time I implemented a application level storage for the parameter defaults so I don’t have to reprocess the parameters with each request.

I have added the two source files to my Google Code Project for Coder Journal, you can find them at:

Tags: , ,

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

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 | 14 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 | 10 Comments »