Amadiere.com

Fourteen and a half crazy frog burpers

30th August 2011

ASP.NET MVC 3: Drop Down Lists / SelectLists

Filed under: JQuery,MVC — Tags: , — Alex Holt @ 10:42 pm

There are a number of very useful helpers that come as default with the ASP.NET MVC framework, but one that always seems to get people confused is the Html.DropDownListFor() helper method. So in this post, I’ll quickly go over the steps I use to populate the list, as well as some of the more funky features once it’s up and running!

In our example, there will simply be a single drop down list on a form that shows a list of countries, from which you can select and submit.

First, we need to build a view model that is going to be the contract that determines the data that the view can display.

1
2
3
4
5
6
7
8
9
public class IndexViewModel
{
    // Stores the selected value from the drop down box.
    [Required]
    public int CountryID { get; set; }
 
    // Contains the list of countries.
    public SelectList Countries { get; set; }
}

Once we’ve sorted that, we can create the action result methods for our index page.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class HomeController : Controller
{
    [HttpGet]
    public ActionResult Index()
    {
        IndexViewModel viewModel = new IndexViewModel();
        viewModel.Countries = new SelectList(GetCountries(), "ID", "Name");
        return View(viewModel);
    }
 
    [HttpPost]
    public ActionResult Index(IndexViewModel viewModel)
    {
        viewModel.Countries = new SelectList(GetCountries(), "ID", "Name");
        if (!ModelState.IsValid)
            return View(viewModel);
 
        //TODO: Do something with the selected country...
        CMSService.UpdateCurrentLocation(viewModel.CountryID);
 
        return View(viewModel);
    }
}

You’ll notice there are two instances where we populate the Countries property on the viewModel, one in the HttpGet method and the other in the HttpPost. We do this so that the list of countries is available throughout our process. You see, unlike the CountryID which is submitted as part of the Request object (it’s part of the form collection), our list is never stored – it’s lost as soon as the user navigates away from that page. So we need to repopulate it. In reality, you may only need to repopulate it when the validation fails an you have to redraw the screen in the HttpPost method, so that could be moved.

Then, it’s just a simple case of adding this to my view:

@Html.DropDownListFor(x => x.CountryID, Model.Countries)

Or you could forcably add a blank value to the top with some “please select me, pretty please”-type text. e.g.

@Html.DropDownListFor(x => x.CountryID, Model.Countries, "- please select -")

And there you have it! A working drop down box using MVC 3 and Razor views.
Now for some more fancy stuff. If you’re interested in styling your menu, then you can’t really go far wrong with jQuery UI SelectMenu (of which there are a few demos available, as well as a separate tutorial). To set up, you only need to do a few things:

  • Download JQuery & JQueryUI and add to your solution. You can now do this step through NuGet, or manually by “Add Existing Item” and downloading from the respective site.
  • Add a reference to the .js and .css files to the header of your html header, often set by the _Layout.cshtml file. Something like the following:
   <link type="text/css" rel="stylesheet" href="@Url.Content("~/Content/themes/base/jquery.ui.all.css")" />
   <script type="text/javascript" src="@Url.Content("></script>
   <script type="text/javascript" src="@Url.Content("></script>
  • Download and add the SelectMenu .js and .css files in much the same way.
<link type="text/css" rel="stylesheet" href="@Url.Content("~/Content/selectmenu.css")" />
<script src="@Url.Content("~/Scripts/selectmenu.js")" type="text/javascript"></script>
  • Then all that lies to do is to set it off going:
<script type="text/javascript">
   $('select').selectmenu();
</script>

The last bit we added there simply makes this apply for every single select box that is on the page. As an aside, when doing AJAX or JQuery where you may potentially add an additional drop down list, you will need to call .selectmenu() to ensure that your new box appears like the others. It’s also worth noting that you may find if your page isn’t a fast loader, the standard drop down box (unstyled) will appear for a brief period.

20th June 2011

Unobtrusive JavaScript in ASP.NET MVC3 with JQuery

Filed under: ASP.NET,C#,HTML,JQuery,MVC — Tags: , , , , , — Alex Holt @ 9:45 pm

I’ve recently experimented a little bit with some of the new unobtrusive JavaScript stuff that is now included as part of the default ASP.NET MVC 3 project template. While not an overly complex subject, it’s been one of them plugins I wanted to have a dabble with, but I didn’t quite find the time until now. And I must say, it was a lot easier to sort out than I thought it might be! I should point out that although this is an ASP.NET MVC 3 example, the concepts and the fact that this is mostly just JQuery means that it’s not limited to that, earlier versions of ASP.NET MVC can use happily, as can WebForms, PHP, Ruby and even Classic ASP!

Some things we’ll try and do in this blog post:

  • Setup a simple form with server-side validation of input fields which redirects to a ‘Success’ page or re-renders the form depending on whether it was successful or not.
  • Add JQuery validation for simple client side validation to the form.
  • Add Unobtrusive JavaScript support which will submit the form via AJAX.

Creating a basic application:

Firstly, I created a ASP.NET MVC 3 Web Application (Empty) in VS2010 and got to work updating the JavaScript libraries that were in it. This can be done via the NuGet Console, or by right clicking “References” in the Solution Explorer, “Add Library Reference” and then clicking the update side-tab. From there you can update all the default stuff.

Done that? Good. Next we’ll add a default controller, a view model to pass the data around & two views (one for allowing us to edit the form and the other as a success page). It’s worth noting that I’m doing nothing that special on these and that I’m using the default _Layout.cshtml to apply the header and footer as it sees fit.

/Controllers/BlackCoffeeController.cs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
using System.Web.Mvc;
using UnobtrusiveAjaxExample.ViewModels.BlackCoffee;
 
namespace UnobtrusiveAjaxExample.Controllers
{
    public class BlackCoffeeController : Controller
    {
        [HttpGet]
        public ActionResult Rocks()
        {
            RocksViewModel viewModel = new RocksViewModel();
            return View(viewModel);
        }
 
        [HttpPost]
        public ActionResult Rocks(RocksViewModel viewModel)
        {
            if (!ModelState.IsValid) return View(viewModel);
            // Do something Database-y here.
            return View("Success");
        }
    }
}

/ViewModels/BlackCoffee/RocksViewModel.cs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
using System.ComponentModel.DataAnnotations;
 
namespace UnobtrusiveAjaxExample.ViewModels.BlackCoffee
{
    public class RocksViewModel
    {
        [Required]
        public string Forename { get; set; }
 
        [Required]
        public string Surname { get; set; }
 
        [Required]
        public string Message { get; set; }
    }
}

Then the two views, firstly: /Views/BlackCoffee/Rocks.cshtml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
@model UnobtrusiveAjaxExample.ViewModels.BlackCoffee.RocksViewModel
 
@{
    ViewBag.Title = "Rocks";
}
<h2>Black Coffee Rocks?</h2>
<div id="content">
@Html.ValidationSummary()
@using(Html.BeginForm())
{
<ul>
	<li>
            @Html.LabelFor(x => x.Forename)
            @Html.EditorFor(x => x.Forename)
            @Html.ValidationMessageFor(x => x.Forename)
        </li>
	<li>
            @Html.LabelFor(x => x.Surname)
            @Html.EditorFor(x => x.Surname)
            @Html.ValidationMessageFor(x => x.Surname)
        </li>
	<li>
            @Html.LabelFor(x => x.Message)
            @Html.EditorFor(x => x.Message)
            @Html.ValidationMessageFor(x => x.Message)
        </li>
</ul>
<div><input name="Continue" type="submit" value="Continue" /></div>
}
</div>

And then /Views/BlackCoffee/Success.cshtml

1
2
3
4
5
@{
    ViewBag.Title = "Success";
}
<h2>Success</h2>
<p>Congratulations! You've successfully declared BLack Coffee as being totally rockin'!</p>

At this point now, you should be able to build and run your application and navigate to /BlackCoffee/Rocks and verify that the page redraws the form unless all boxes are filled in. If you do fill them all in, you should get the success page.

Adding JQuery Validation with barely any effort for standard Data Annotations.

With certain DataAnnotations such as the [Required] attribute and [StringLength], you should be able to get simple JQuery client side checks, which while not a replacement for server side checks, add some speedy feedback which will be especially welcomed by users who find themselves struggling over long distance or slow connections. The key point to note here is that the checks are performed both sides (client and server) – so it doesn’t matter if the user has JavaScript disabled or is using a browser not capable of running it – the checks will still get done. It’s just an added bonus.

To do, simply add references to the JavaScript files to your html’s <head> tag. In this case, I’m going to add them directly to the _Layout.cshtml file.

6
7
8
9
    <script src="@Url.Content("~/Scripts/jquery-1.6.1.min.js")" type="text/javascript"></script>
    <script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript">></script>
    <script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
    <script src="@Url.Content("~/Scripts/jquery.unobtrusive-ajax.min.js")" type="text/javascript"></script>

You’ll spot that there are 4 included files there – the last one (the JQuery.unobtrusive-ajax.min.js) is for the next part – but we’ll put it in now in preparation.

You should find that the Web.Config file already has the following lines in already (specifically lines 10 & 11), but have a gander for the following and if it doesn’t exist or is set different to this, update the file appropriately.

8
9
10
11
12
<appSettings>
    <add key="webpages:Version" value="1.0.0.0"/>
    <add key="ClientValidationEnabled" value="true"/>
    <add key="UnobtrusiveJavaScriptEnabled" value="true"/>
</appSettings>

We’re now cooking with gas! Save, Build and try out your application. You should be able to spot that when clicking your submit button, the page doesn’t go away to the server at all to check the field validates, it’s doing it on the client. Good stuff!

Adding Unobtrusive AJAX into the mix.

This should be a relatively easy process, but there are a few things we need to consider sorting out before we continue too much further:

  • Update the views to make the Form work via AJAX (without breaking non-JavaScript/AJAX support)
  • Update the controller to detect whether the request is an AJAX request and if so, avoid sending the header / footer / other stuff back with it.

The first part is quite simple. Within the Rocks.cshtml we created earlier which is our edit form view, we used the HtmlHelper class to create the form tag. All we need to do now is change that to use the AjaxHelper class and pass in some options and we’re off to a winner!

10
@using(Ajax.BeginForm(new AjaxOptions() { HttpMethod = "Post", UpdateTargetId = "content" }))

You should be able to see there that there is AjaxOptions class “newed up” directly in the view. If you’re uncomfortable with doing this, you could create it directly in the view model and pass it in from there. There are a ton of options that you can go into, most of which are touched upon on Brad Wilson’s blog post on this subject (if you haven’t read Brad Wilson’s blog, you probably should add it to your reader – it’s exceptional and includes a good chuck of stuff relating to ASP.NET MVC and related topics). You’ll also spot we provide a UpdateTargetId – this represents the HTML element into which all the view result is going to get dumped into. In this case, our DIV on our Rocks.cshtml page – but this could be anything and in fact nothing, if you don’t want to spew out content back to the user for whatever reason.

If you ran the application now, you’d find that all the AJAX and the JQuery would work great, but as part of the Ajax Request, the header and footer would be returned and very soon you’d end up with a webpage that looks like it’s been designed by someone who’s been watching Inception too much. This thankfully (or more specifically thanks to the ASP.NET team), isn’t a problem as we can do a little check before returning the view while in the appropriate controller method. Using the example above, you’d be able to change it to something like this:

15
16
17
18
19
20
21
22
        [HttpPost]
        public ActionResult Rocks(RocksViewModel viewModel)
        {
            if (!ModelState.IsValid) return View(viewModel);
            // Do something Database-y here.
            if (Request.IsAjaxRequest()) return PartialView("Success");
            return View("Success");
        }

You’ll spot with this example we are returning exactly the same view. However, by returning it as a Partial view, we are ensuring it does not get rendered as part of a bigger page, so all of the headers / footers and other things included via layout pages are ignored.

Other things you can do to improve stuff:

There are a plenty of other very easy things you can add too, such as:

  • Loading image: Simply provide it with a content div to display while loading (and a timeout if you want) and in will show() that while that particular AJAX call is made. Meaning that if you want to, you can lock the UI or provide visual feedback that the users request is currently in progress.
  • There are four callback methods you can set for OnBegin, OnSuccess, OnFailure and OnCompleted which will trigger as appropriate. This allows you to add all sorts of extra functionality to the application in those instances you want to do more than simply “add some HTML to a div”. However, two things to note regarding these function calls:
    • The functions you declare should not live inside of the JQuery document.ready() method or other shorthand notation for that. Just plain functions in a .js file is fine (though, you can of course, still use JQuery – that’s not a problem).
    • You might find that the $(this) object within the JavaScript is not populated by the time you get to the methods. You can solve this to some degree by changing the following line from:
      244
      
              options.data.push({ name: "X-Requested-With", value: "XMLHttpRequest" });

      to:

      244
      245
      
              options.data.push({ name: "X-Requested-With", value: "XMLHttpRequest" });
              options.context = element;

      If I’m honest, I don’t know why this line is missing from the file in the first place. I can’t imagine it’s just been forgotten as it seems like such a key thing to be able to trigger events based on the click events (especially on pages where there are lots of controls which may call the AJAX request). I suspect there is a good reason – but I don’t know it yet.

  • You can use this on more than just <form> tags. For example, it’s just as easy to use the Ajax.ActionLink method which works in a very similar way and has some of your favourite overloads still available!
  • As mentioned at the top, this is mostly just JavaScript. If you wanted to do this with any other server side technology, all you’d need to do is replace the AjaxHelper methods with your own way of outputting the specific HTML “data-” based attributes and you’re up and running!

The full source code is available in a zip file here – though, as you can see above – it’s not a great deal different to the bog standard project!

4th March 2011

The 10 Best YouTube Video’s (Even Better Than That Other List You Read)

Filed under: Internet,Jokes — Alex Holt @ 9:48 pm

Right, I know you read about all these other lists of “top 10 videos ever” blah-blah! But seriously. They never seem to satisfy me. They always leave out the ones that I think were freakin’ amazing. So, in true “OMG! Sum1 on the Intert00bs is wong!!one!”… here is my subtle attempt at bashing them.

Firstly, an honorable mention for Numa Numa –  a classic bizarre video from long before the realms of YouTube! Additionally – Charlie and Susan Boyle (both of the YouTube era), although not my favourites – do get a hat tip for being interesting for a watch at least once.

But now, in reverse order – the top 10!

10 – Ring, Ring, Ring, Ring, Ring, Ring, Ring: Banana Phone!

This is truely, truely the most frusting song on the internet. Once you’ve heard it, you cannot get it out of your head for the rest of the day.

9 – Mario A Capella

A group effort showing a bunch of people singing the Super Mario tune, providing all the parts and the entertainment – with none of the expensive woodwind section

8 – Leeeeeeeroy Jeeeeenkins!

Ask any World Of Warcraft player if they have heard of Leeroy Jenkins and 99% will say yes. So utterly famous he appeared in a recent update and you can now get an in-game achievement with his name.

7 – Rick Rolling!

A meme of the most annoying type. Used normally to trick people into listening to it – I’m offering it to you this time with a warning: This video contains Rick Astley.

6 – Boo. Hahahahahaha! Baby

This quite simply makes you smile and is one of the rare videos on the internet that doesn’t involve laughing at someone else’s expense.

5 – Star Wars Kid

The original is amazing! But then there are loads of follow ups (particularly good is the light saber adaption). He became so famous that the Internet bought him a Macbook and Lucas Arts gave him a role in one of the Star Wars films. Epic!

4 – The Muppets: Bohemian Rhapsody

If I’m not mistaken, the first full 1080P YouTube video (be sure to set it to HD before you watch!) – and it’s awesome. I’m a fan of the Muppet’s and Queen separately, so when this came out – my head exploded.

3 – The Ultimate Showdown (of Ultimate Destiny)

From the era of Flash comes this bizarre storyline accompaniment to what appears to be a celebrity-apocalypse. Very fun and very tongue in cheek.

2 – Terry Tate: Office Quarterback

Sensationally funny! I have long since campaigned to get a guy like this into every workplace. Up to yet, I’ve been 100% unsuccessful – but I have not given up hope!

1 – The Evolution of Dance

This guy can SERIOUSLY dance. I don’t mean in a crappy Britain’s Got Talent kinda way! The best few minutes of your day – watch it! It’s the best video in the entire interwebs!

Older Posts »

Theme designed & built for Amadiere.com by Alex Holt. Powered by WordPress