Team Foundation Error – BasicAuthCredential is not marked as serializable

I was working on a project hosted in a git repo in Team Foundation and wanted to update the build process. Scroll down for two different fixes if you’ve got the error, or read on to see if it’s applicable to your situation.

When I navigated to the step to configure the process template parameters, I ran into the following error:

image

The text was:

Team Foundation Error – Type ‘Microsoft.TeamFoundation.Client.BasicAuthCredential’ in assembly ‘Microsoft.TeamFoundation.Client, Version=12.0.0.0, Culture=neutral, PublicKeyToken=’[token] is not marked as serializable.

I’m not aware of any recent changes or updates to my machine, my dev environment or the TFS server in question. I tried restarting Visual Studio, but the error persisted.

I then remembered that about three months ago I ran into a similar problem (though I can’t quite recall if it was the same error) when I started using a VM that had a co-worker’s credentials pre-baked into VS. To fix this problem I removed the credentials in Windows, and it resolved the issue, prompting me to sign in as myself when I next launched VS.

Solution 1 – Reset Your Credentials

Rather than removing the account, I wanted to first try to just poke it by re-entering my password or  To reset your credentials, try this:

  1. Close all instances of Visual Studio.
  2. Tap your Windows key, then type “Credentials”. The Credential Manager app link should show up in your list.
  3. Check out your “Windows Credentials”. Under Generic Credentials, you should see your TFS account.
  4. Click on the twirldown next to the entry and select “Edit”.
  5. Retype your password.

Solution 2 – Delete the Credentials from Windows

imageIf the reset doesn’t work, you can try this instead.

  1. Close all instances of Visual Studio.
  2. Tap your Windows key, then type “Credentials”. The Credential Manager app link should show up in your list.
  3. Check out your “Windows Credentials”. Under Generic Credentials, you should see your TFS account.
  4. Click on the twirldown next to the entry and select “Delete”.
  5. You may need to do this for more than one account, especially if you have a git:http:// account saved as well.
  6. Confirm the delete operation.

Whichever solution you have to go with, this should fix things up. Note that in solution 2, you’ll be prompted for your credentials when you open up Visual Studio and try to navigate to a team project.

Cheers, and happy coding! Smile

Day 2 – Adding Entities to a Storage Account Table

In this series we are looking at the basic mechanics of interacting with cloud-based Table Storage from an MVC 5 Application, using the Visual Studio 2013 IDE and Microsoft Azure infrastructure.

We’ve got some basics in place, namely loading up all resources from a table, but it turns out that users want to be able to add records, too. Who knew?  To allow this to happen, we’re going to need to update our view a little and add an appropriate method on our controller.  Let’s make that happen, then we’re going to take a look at why our approach is breaking down.  Don’t worry, we’ll start fixing things up in Day 3!

Updating Our View

We’re going to keep working off of the view we created in Day 2, just simply by adding a form below the existing UI. 

<h2>Like Kittehs? Add a Kitteh!</h2>
@using (Html.BeginForm("Index", "Home", FormMethod.Post))
{
    <div class="form-group">
        <label for="ImageUrl">What kind of Kitteh is it?</label>
        <select class="form-control" name="PartitionKey">
            <option value="FunnyKittehs">Funny Kitteh</option>
            <option value="CuteKittehs">Cute Kitteh</option>
        </select>
    </div>
    <div class="form-group">
        <label for="RowKey">Kitteh Name</label>
        <input type="text" class="form-control" id="RowKey" name="RowKey" placeholder="SeriousKitteh">
    </div>
    <div class="form-group">
        <label for="ImageUrl">Image URL</label>
        <input type="url" class="form-control" id="ImageUrl" name="ImageUrl" placeholder="http://awesomekittehs.org/pic1.jpg">
    </div>
    <button type="submit" class="btn btn-default">Submit</button>
}

If you’re new to Bootstrap, it may seem like there’s a lot going on there, but you get used to it pretty quickly. Our form has three “groups” in it.  This is a construct in Bootstrap that allows us to associate controls and labels and get the CSS styling we expect.   Each form group has a label and a control, in our case, and we’re simply putting in the properties we need in order to create a new row in our Azure Table.

The form is configured to POST to the Index action on the Home controller, so let’s set up someone to answer when the calls start coming.

Updating Our Controller

The next piece is just as easy. We want to accept the form information (our controller will leverage MVC’s model binding) and then create a new entity in the Table.

[HttpPost]
public ActionResult Index(KittehEntity entity)
{
    var storageAccount = CloudStorageAccount.Parse(CloudConfigurationManager.GetSetting("StorageConnectionString"));

    var client = storageAccount.CreateCloudTableClient();
    var kittehTable = client.GetTableReference("PicturesOfKittehs");

    var insert = TableOperation.Insert(entity);
    kittehTable.Execute(insert);
            
    var kittehQuery = new TableQuery<KittehEntity>()
        .Where(TableQuery.GenerateFilterCondition("PartitionKey", QueryComparisons.Equal, "FunnyKittehs"));

    var kittehs = kittehTable.ExecuteQuery(kittehQuery).ToList();

    return View(kittehs);
}

The insert is a type of TableOperation that we get by calling the static method aptly named “Insert” and passing in our entity. Our kittehTable object here is created in the context of a table reference that we load from our storage account by name.

At the tail end of the insert operation, we reload the list of kittehs (everyone is here to see the kittehs, after all) and return the view to render the list.

It’s Falling Apart!

Good grief, Charlie Brown, you’ve repeated all your code!  Our controllers should handle the mapping of requests and related payload to service endpoints, and direct users to the correct views.

Putting application logic into our methods is a dangerous slope, and anytime our actions start doing more than one thing we start making it hard to test and maintain our software.  This is ungood.

Next Steps

A lot of times tutorials and blog posts fall short in the area of best practices, and I don’t want to go there for this one. In tomorrow’s exercise we’re going to break our problem down into better pieces that more accurately represent what you’d be doing in a real-world application.

Microsoft Virtual Academy – A Lap Around Azure Websites – All the Questions and Links From the Talk

On January 14th, 2015 Jon Galloway and Cory Fowler presented a live “Lap Around Azure Websites” on Microsoft Virtual Academy. I was the online “Community Expert” for the live event and fielded questions in the chat.

The Links Shared from the Session

Some questions were more easily answered just by sharing a link! Here are the links that I mentioned in the chat or that were cited by Jon and Cory:

As well, here are some other really great MVA sessions you should take advantage of:

  • Building Apps with Node.js Jump Start (Course)
  • Introduction to Creating Websites Using Python and Flask (Course)
  • What’s New in Visual Studio 2013 Jump Start (Course)
  • Microsoft Azure Fundamentals (Course)

And, if you’re into the whole reading thing, I published a book on Azure Websites that is still really relevant, in spite of all the new features and changes the portal’s seen.

The Common and Predominant Questions

I grabbed the questions that stood out the most from the chat and am posting them below, along with my answers.

Can Javascript run on .NET platform also?
No, JavaScript doesn’t run natively on .NET. But Azure != .NET, and Azure Web Sites has many options for web stacks, including Node.js. Remember that JS has traditionally been a client-side language, so it of course can be used in any web application created with .NET

Do we need SDK’s and command line tools with Visual Studio 2015 Preview.
No, you don’t need it. But the SDK adds some extra (really useful) tooling, and the command line tools gives you options from a console or PowerShell script.

What are your thoughts on using WebMatrix? How does it compare to VS in terms of workflows you are going to talk about?
WebMatrix is a great tool for working with non-.Net stacks and has language support beyond what you’ll find in VS. However, if you’re working with .NET langauges (as well as many other non-.NET languages), VS gives you probably the IDE experience, hands-down.

When signing up for the free trial on Azure Websites it still asks me for entering my credit card details on the trial registration page. Is it going to charge me?
Even if they do collect the CC info, there will no charges. By default there is a spending limit of $0 on your account. Unless you remove that, there will not be any charges incurred. You can sign up with confidence!

How can you deploy to two Azure websites? One for Staging and another one for Production.
The easiest way is to use two different branches in source control, then you can automate everything about deployment to two entirely different websites. You can use slots and swapping to help with this.

My trial period has expired and I have converted my subscription to Pay-As-You-Go subscription. When will I have to pay something?
You’ll have to pay if you want to start adding “real-world” value to your project. Things like scaling, dedicated domain names, load balancing and the like.

Are MySQL databases hosted on Azure the same as SQL server? What’s the deal with these 3rd party partners? How is it different?
The third-party DB providers are from partners that may or may not use Azure resources. They provide an integration mechanism with Azure, but don’t necessarily spin up Azure resources. With MySQL, you just need a connection string to get at the data. It is not hosted on the same server as Azure SQL. And in the case of ClearDB, they are actually hosted on an Azure cluster.

Should a team have their GIT repository in VS online or Azure for an Azure site?
There is no preference. In fact, I have on-prem git repos, VS Online hosted and even repos (the majority) hosted on GitHub. You are free to choose what works with your team.

Should I add my packages to .gitignore when working with GitHub and Azure Websites? Does Kudu install the packages for me? If so, wouldn’t it be faster to deploy by NOT adding the packages to .gitignore?
It’s possible that you might save time, but deploying to different regions may mean greater latency as you deploy. Local cached packages can be quickly retrieved by Kudu, which could result in time saving for you.

Can I use the Kudu webhooks with a local githook from my Git repo? 
The webhook endpoint is exposed in the API, you can read more about it here.

How do deployment slots work? Can I use separate databases for different slots?
Slots can have their own configuration, so if you need different connection strings for the alternate slots, you can do that. This is also true of app settings and the like.

What does Kudu do?
Kudu is the deployment engine that powers Azure Websites. It’s grown into a great set of services that allow you to manage and customize your deployment process. There is a public API you can use in your own projects, integrate with other web hooks and more.

How does the Kudu Console work in the Browser?
The cool bits to me (as a developer) is the continuous connection to the browser from the server. That’s all powered by SignalR, which is another open source project started by some MS folks. You can find the SignalR GitHub repo here.

What are the costs related to turning on tracing?
There is a very small percentage of a performance hit, but nothing really in terms of monetary costs, it’s included in the platform. The one potential thing to watch for is that there is a cap on website space and the logfiles will count towards that.

How do I analyze the data from my error logs on my site?
You can use the built-in support site from the scm sub-domain on your site. Just navigate to <yoursite>.scm.azurewebsites.net/support and select your hostname. From there, you can drill in and see error and troubleshooting information.

Can I use .NET 3.5 on Azure Websites?
Yes, this is an option from the configuration menu. The only trouble I’ve had in moving to AW is when you have legacy third-party components that need access to unsafe memory or the registry (not supported on websites).

Day 1 – The Basics of the Basics with Azure Table Storage

In this series we are looking at the basic mechanics of interacting with cloud-based Table Storage from an MVC 5 Application, using the Visual Studio 2013 IDE and Microsoft Azure infrastructure.

Before We Get Going…

Let’s not mince words here, the best way to develop in the cloud is with the best and most up-to-date toolset that we have available. You’re going to want to grab these prerequisites as a minimum foundation for following along in this series:

Visual Studio 2013 gives us great templates to start from and by augmenting it with the SDK we also get a rich set of cloud-management features, which we’ll explore in the later parts of the series.

The Straight-Up Attack: Accessing Table Storage from Your Controller

Follow these quick steps to get started:

  • Create a new solution in Visual Studio using the ASP.NET Web Application project template
  • Right-click on your project in Solution Explorer, then Manage NuGet Packages and add “WindowsAzure.Storage” to your dependencies.
  • Alternatively, you can install the package from the Package Manager Console with the following command:
    Install-Package WindowsAzure.Storage

The project is now prepped, so now we can add the needed code bits to start building our app. Let’s start by adding the following class to our project in the Models folder:

public class KittehEntity : TableEntity
{
    public KittehEntity(string kittehType, string kittehName)
    {
        this.PartitionKey = kittehType;
        this.RowKey = kittehName;
    }

    public KittehEntity() {}

    public string ImageUrl { get; set; }
}

Next, replace the code in the HomeController with the code below. Note that you’ll need to add the namespace for the models to the usings at the top.

public ActionResult Index()
{
    var storageAccount = CloudStorageAccount.Parse(
        CloudConfigurationManager.GetSetting("StorageConnectionString"));

    var client = storageAccount.CreateCloudTableClient();

    var kittehTable = client.GetTableReference("PicturesOfKittehs");
    if (!kittehTable.Exists())
    {
        kittehTable.Create();
                
        var thrillerKitteh = new KittehEntity("FunnyKittehs", "ThrillerKitteh");
        thrillerKitteh.ImageUrl = "http://cdn.buzznet.com/assets/users16/crizz/default/funny-pictures-thriller-kitten-impresses--large-msg-121404159787.jpg";

        var pumpkinKitteh = new KittehEntity("FunnyKittehs", "PumpkinKitteh");
        pumpkinKitteh.ImageUrl = "http://rubmint.com/wp-content/plugins/wp-o-matic/cache/6cb1b_funny-pictures-colur-blind-kitteh-finded-yew-a-pumikin.jpg";

        var batchOperation = new TableBatchOperation();

        batchOperation.Insert(thrillerKitteh);
        batchOperation.Insert(pumpkinKitteh);
        kittehTable.ExecuteBatch(batchOperation);

    }

    var kittehQuery = new TableQuery<KittehEntity>()
        .Where(TableQuery.GenerateFilterCondition("PartitionKey", QueryComparisons.Equal, "FunnyKittehs"));

    var kittehs = kittehTable.ExecuteQuery(kittehQuery).ToList();

    return View(kittehs);
}

Admittedly, this is a bit of a naive approach because we’re mixing concerns here and putting storage access and table seeding in a single controller method, but I want to highlight the premise here without adding too much cruft. Through the rest of the series we’ll extract a service to do the heavy lifting and move back towards best practices.

What we’re doing above is the following:

  • Reading the connection string from our web.config
  • Configuring the client
  • Getting a reference to a table
  • If the table doesn’t exist (it won’t, first time), we build a batch operation and seed it with some data
  • We fetch all records with a “FunnyKittehs” partition key
  • We pass the data to the view

Now, replace the code in the Views\Home\Index.cshtml with the following:

@model IEnumerable<YourNamespace.Models.KittehEntity>
@{
    ViewBag.Title = "Home Page";
}

@foreach (var kitteh in Model)
{
    <div class="jumbotron">
        <h4>@kitteh.RowKey</h4>
        <img src="@kitteh.ImageUrl" />
    </div>
}

Note that you’ll need to update the namespace to match your project’s.

Finally, add a connection string to the AppSettings section of your web.config. This will tell our app to use the local storage emulator provided by the SDK.

<appSettings>
  <!-- other settings... -->
  <add key="StorageConnectionString" value="UseDevelopmentStorage=true;" />
</appSettings>

Finally, run the app! You should see a couple of adorable kittehs in your browser, rendered in a razor view, with data populated by the MVC controller with entities loaded from Azure Storage Tables.

Next Steps

In this post we injected a few entities into our table using a seed method, but what about adding new entities from the UI? In the next article, we’ll beef up the views and controller to allow users to add new documents to our storage account.

(Psst! If you’re just getting started with MVC and want to get your hands real dirty, check out my book on Bootstrap and the MVC Framework).

Day 0: 8 Days of Working With Azure Table Storage from ASP.NET MVC 5

Here’s a short and simple way to get started using Azure Table Storage from ASP.NET MVC 5. Following these brief, task-oriented articles will help you learn the mechanics of working with table storage and give you some pointers on how you might want to approach it in your app.

We’re going to start with the basics, a simple MVC app with a controller that builds the table, inserts a couple of rows and then displays them.

But then we’re going to expand on that, adding other operations to manipulate the data as well as the tables themselves, and then we’ll take it to the next level where we start to apply some better strategies around how we actually access the data.  After all, MVC is all about separation of concerns!

Most of these principles will apply if you need to access a storage table from other areas of .NET as well…you could just as easily apply these to Web API, a console application or your next WinForms project. By the end, we’ll have extracted the important parts out into a reusable block of code that runs equally as well with the Azure Storage Emulator in your development environment as it does in production in the cloud.

Working With Azure Table Storage – Our Agenda

Check back for more on the series in the days ahead, all the links will be posted here.

And hey, if you’d like to ramp up in your MVC skills, please check out my recent book:

banner5

There is Something you Want to Know. So Learn it.

Students, especially, take note of this because you can get all the tools for free, so this is a great way to kick-start your career. This kind of learning was not available, much less for free when I was a kid.

image

That’s it. An email address. That’s all you need to get started.

Of course, this isn’t an offering limited to students, so for you seasoned vets, give up on that treadmill and commit to four weeks of levelling up.

Okay peeps, go rock some awesome!

Shameless plug: if you’re wanting to ramp up your web-dev skills and get in on a 30 day challenge, be sure to check out my book on Bootstrap and the MVC Framework with tons of tips on CSS, JS, jQuery, and ASP.NET’s MVC 5. Each chapter is in digestible snippets that you can rock out in usually 15 minutes or less.

A Lap Around Azure Websites

If you haven’t yet started your free trial of Azure Websites – or even if it’s been a while since you have – you might be surprised to find out just how rich the offering has become. Rather than trying to catch up on your own, invest one day of time into yourself on January 14th!

Register For The Free, Live Event Here!

image

I am thrilled to be joining the two excellent presenters – Jon Galloway and Cory Fowler – on Microsoft Virtual Academy as a Community Expert to help answer questions through the day. You’ll find me in the chat room, directing you to resources, answering questions and, heck, I might even craft up a sample or two along the way. :)

UPDATE: I have posted all the links and questions/answers that came up through the session, be sure to check out the full list here.

Some Background and Some Present Day

It wasn’t too long ago that Azure Websites was an obscure beast in the cloud mix, with awkward deployment requirements, limited language and platform options and plenty of alternatives that required far less effort with better scaling options.

Today’s Azure Websites’ in equally suitable for greenfield development start-ups, enterprise migrations and hobby sites. A myriad of languages, web stacks, versatility in DB connections, a great deployment story and full integration with the world’s best IDE makes Websites a legitimate consideration for your next – or first – project.

Catch you online!

Using Editor Templates Multiple Times on the Same Page in MVC

banner5

In the last post we created a star rating control that can be easily used in model binding and in displaying a record on our page. The rating control used FontAwesome and some CSS hacks to change radio buttons (which are usable from screen readers) into stars. This gave us a reusable rating control in MVC that is accessible and looks pretty darn okay, and meets our needs for model binding.

image_thumb6

But what if you wanted to build out a list of elements that you wanted to rate? Rather than just one movie, you wanted users to be able to rate your whole collection?  Understanding the mechanics of the binding engine are important if you want to POST a list of entities back to an MVC controller.

Getting the Basics

One of the earliest things that attracted me to the MVC Framework was model binding, and the freedom to stop fishing the in the Form object for parameters that may or may not exist. Over time, many of us built libraries of code that we’d suck in to each project so that we could do things like wrap the extraction of a list of checkbox or radio values up into some kind of abstraction. We don’t need to do that in MVC.

You’ll recall that a list of checkboxes in HTML is quite straightforward. The simplest approach might be something like this:

<form method="POST" action="Index3">

    <input type="checkbox" name="movies" title="The Last Starfighter" value="The Last Starfighter" id="movie1" />
    <label for="movie1">The Last Starfighter</label><br />

    <!-- ... -->

    <input type="checkbox" name="movies" title="Amelie" value="Amelie" id="movie2" />
    <label for="movie2">Amelie</label><br />

    <button type="submit">Save</button>
</form>

And to “catch” that data, we need an action (the target of the form above) with the same name that accepts a List<string> with the name of the checkbox. The value attribute of the checkbox will be added to the list parameter in your action. Your action will look something like the following:

[HttpPost]
public ActionResult Index3(List<string> movies)
{
    return View();
}

The model binder allows any of the selected checkboxes to have a landing spot in your list. You don’t have to check for nulls, or iterate through the form collection to discover all that might have been submitted. It’s worth noting here, as well, that if your value attribute were all integers in your form, you could just as easily have the framework bind to a List<int> in your action signature.

So, that’s great for simple values, but…

…What About Binding Complex Objects?

I’m so glad you asked. Smile

imageIf we now look back at our rating control, the control itself is actually ready to go as-is, but we’d need to get a bit more code into our view page (not the partial, but more like, the list of the movies) to get it to tick correctly. 

Here’s what we’ll do:

  • Change our index action to return a list
  • Iterate over the list in our view
  • Pass in some secret magic sauce to the HtmlHelper that renders our stars control

We’ll load up some fake data to push to the view. You would typically want to get this data from a database or an API call of some kind. For now, we’ll go with this:

public ActionResult Index()
{
    var movies = new List<Movie>
    {
        new Movie{Title = "The Last Starfighter", Rating = 4},
        new Movie{Title = "Flight of the Navigator", Rating = 3},
        new Movie{Title = "Raiders of the Lost Ark",  Rating = 4},
        new Movie{Title = "Amelie",  Rating = 5}
    };
            
    return View(movies);
}

Great, now we just need to update our view. Basically, you can take everything out of the form and just replace it with the following, a foreach over the collection we’re passing in:

    @foreach (var movie in Model)
    {
        <div class="row">
            <div>
                <p>@movie.Title</p>
                <input type="hidden" value="@movie.MovieId" name="@string.Format("movies[{0}].MovieId", i)" />
                <input type="hidden" value="@movie.Title" name="@string.Format("movies[{0}].Title", i)" />
                <p>@Html.EditorFor(p => movie.Rating, "StarRating", string.Format("movies[{0}].Rating", i++))</p>
            </div>
        </div>
    }

Also, don’t forget to change the @model on your page to the collection of Movie as so:

@model List<YourApplication.Models.Movie>

Finally, update the code block at the top of the page to declare a variable that we will use as a counter over our collection:

@{
    ViewBag.Title = "My Awesome List of Awesome Movies";
    var i = 0; // movie control index
}

We’re moving along now! There’s two crucial parts in how all this will work when it gets rendered on the client and eventually hits the model binder on the way back in when the form is submitted. The first is the way I’ve constructed the name attribute on our controls. For instance:

name="@string.Format("movies[{0}].MovieId", i)"

In the above code, on the first iteration, the name would be rendered as “movies[0].MovieId”. The prefix “movies” is what our parameter needs to be called on our action (for the POST). The index notation [0] tells MVC which element this object is in our list, and finally, the “MovieId” is simply the property we want to pass in. 

Note: While I’m passing in the ID and the Title as hidden params, I’m only doing so to show the model binder in action. You should always test/cleanse these values in your controller to prevent over-posting of data, where a malicious user could modify the object without your consent.

The second noteworthy point is the overload that I’m calling on the EditorFor method:

@Html.EditorFor(p => movie.Rating, "StarRating", string.Format("movies[{0}].Rating", i++))

That’s important because I’m passing the similarly generated name (as above) as the name of the HTML field name. Remember that in the last post the EditorTemplate contained references to the ViewData.TemplateInfo.HtmlFieldPrefix? That is normally provided for you by default, but in the case of a list of objects, you need to provide it on your own. That code, in the Shared\EditorTemplates folder, was referenced like this:

var htmlField = ViewData.TemplateInfo.HtmlFieldPrefix;

…and it was sprinkled throughout the control template.

Finally, we’re going to need to get that POST action in line.  Update your controller method to look like this:

[HttpPost]
public ActionResult Index(List<Movie> movies)
{
    return View(movies);
}

Now, when the form is submitted each set of indexed form fields will be used to new up an instance of our Movie class and placed in the collection. I’ve set a breakpoint so that you can see it in action:

image

You’d obviously want to do more than just cycle the movies through the controller, so rather than just returning the list you could do your validation, update your database, or aggregate stats from this response to a running average. So much fun to be had.

Summary & Next Steps

I always like to encourage folks to try things out and see if they can get it working on your own. It all starts with File –> New Project. Be sure to check out my Bootstrap series or purchase a copy of my book for more examples like this, and happy coding!

Using Font Awesome in an Accessible, Bindable Star Rating Control


banner

Creating a rating control that works across browsers, looks good and can be taken advantage of by the MVC Framework requires a little CSS know-how, a couple of freely-available frameworks and some convention-following. There’s a bit of work to get it set up, but it’s reusable, accessible and gosh darn it, it looks good, too.

Don’t overlook the accessible bits! It’s important to remember that most organizations and agencies have policies in place ensuring that folks with disabilities can use alternate methods to view your site. While I am by no means an expert in this area I do have the help of a friend who will try things out for me from time to time in a screen reader and I try to keep these concerns at the front of my mind when doing something “off course”.

Our Starting Point

I’m building off of the work in the last post, where I added Font Awesome to our Bootstrap-enabled MVC 5 web site. Let’s drop a model class for a movie in our project in the Models folder that looks like this:

public class Movie
{
    public int MovieId { get; set; }
    public string Title { get; set; }
    [UIHint("StarRating")]
    public int Rating { get; set; }
}

Next, let’s update the HomeController to have the following actions:

public ActionResult Index()
{
    var movie = new Movie
    {
        Title = "The Last Starfighter", 
        Rating = 4
    };
    return View(movie);
}

[HttpPost]
public ActionResult Index(Movie movie)
{
    return View("Index", movie);
}

Nothing too fancy here, just a GET and POST action for Index requests. The GET populates (simulates) someone navigating to an item that they can rate. The POST allows you to set a breakpoint so that you can inspect the movie result when you submit.

Finally, scaffold a view for Index. First, delete the Index.cshtml from the Views/Home folder in your project. Next, right-click on one of the the Index methods above and select Add View, then choose the Edit template (don’t create a partial view here) and let it build the page for you.  Finally, run your project to see what you get; it should look like this:

image

That’s okay, but, here’s what we want to see:

image

Getting Stylish

So, believe it or not, those are just radio buttons! There’s a couple of things we do to make it come together, including the use of a container DIV, but it’s mostly straightforward. Let’s look at the basic HTML structure that makes this tick.

<div class="rating">
  <input type="radio" id="star5-Rating" name="Rating" value="5">
  <label for="star5-Rating" title="Best">5 stars</label>
  
  <!-- ...more like these... -->
  
  <input type="radio" id="star1-Rating" name="Rating" value="1">
  <label for="star1-Rating" title="Pretty Bad">1 star</label>
</div>

The container holds a collection of inputs and labels. These elements are attributed as you’d expect, but are inserted in the document in reverse order so that “5 stars” is at the top and “1 star” is at the bottom. This has to do with CSS bits, which we’ll come to in a minute.

Oh…here we are, the CSS bits!

Right, so we start by setting up the container and getting our input off-screen.

.rating {
    float:left;
}

.rating:not(:checked) > input {
    position:absolute;
    top:-9999px;
    clip:rect(0,0,0,0);
}

This works okay because if a user taps, clicks or selects a label with a screen reader, the input is still appropriately checked. Next, we wire up the label.

.rating:not(:checked) > label {
    float:right;
    width:1em;
    padding:0 .1em;
    overflow:hidden;
    white-space:nowrap;
    cursor:pointer;
    font-size:3em;
    line-height:1.2;
    color:#e0e0e0;
}

.rating:not(:checked) > label:before {
    font-family: FontAwesome;
    content: "\f005";
}

These two styles push the label off-screen and setup the fixings for our star, including the insert of the character from Font Awesome.

We float these to the right so that we correct our order; remember that we inserted the stars in reverse order in our HTML, here we use CSS to correct that. This workaround is needed for the foreseeable future as we do not have CSS selectors to help us resolve things “before” our element, only after. By putting rating 1 after rating 3, we can select 3, 2 and 1 with various combinations of selectors; however, there is no mechanism allowing us to select the other way, i.e., “before”.  (The before psuedo-selector allows us to insert content, but not apply style transformations.)

Finally, we handle the color states with various combinations to handle selected stars, stars that were previously selected and stars that are hovered (but not yet selected).

.rating > input:checked ~ label {
    color: #fa0;
}

.rating:not(:checked) > label:hover,
.rating:not(:checked) > label:hover ~ label {
    color: #fe0;
}

.rating > input:checked + label:hover,
.rating > input:checked + label:hover ~ label,
.rating > input:checked ~ label:hover,
.rating > input:checked ~ label:hover ~ label,
.rating > label:hover ~ input:checked ~ label {
    color: #ea0;
}

It may seem like there’s a lot of action going on in that code, but it’s required. The >, +, ~ and : selectors in there allow us to be very specific about which elements in which state require coloring.

Add all of those CSS bits to your Site.css file (in the Content folder) and your styles will be in place. All that’s left to do now is to take that rough-in of HTML we did before and turn it into something the MVC Framework can use.

Bringing Some MVC to the Equation

You’ll have noticed the attribute UIHint decorating our Rating property on the Movie model class that we created in the first step. That was no accident! Now, let’s get that working for us by creating a reusable partial view in our project. Add a file called StarRating.cshtml to the Views\Shared\EditorTemplates folder. By convention, this is the folder that the MVC Framework checks for custom views used to render properties or models (you can see another sample here from my Bootstrap series).

The StarRating.cshtml should look like this:

@model int

@{
    var chk = "checked";
    var checked1 = Model == 1 ? chk : null;
    var checked2 = Model == 2 ? chk : null;
    var checked3 = Model == 3 ? chk : null;
    var checked4 = Model == 4 ? chk : null;
    var checked5 = Model == 5 ? chk : null;
    var htmlField = ViewData.TemplateInfo.HtmlFieldPrefix;
}

<div class="rating">
<input type="radio" checked="@checked5" id="star5-@htmlField" name="@htmlField" value="5" /><label for="star5-@htmlField" title="Best">5 stars</label>
<input type="radio" checked="@checked4" id="star4-@htmlField" name="@htmlField" value="4" /><label for="star4-@htmlField" title="Good">4 stars</label>
<input type="radio" checked="@checked3" id="star3-@htmlField" name="@htmlField" value="3" /><label for="star3-@htmlField" title="Average">3 stars</label>
<input type="radio" checked="@checked2" id="star2-@htmlField" name="@htmlField" value="2" /><label for="star2-@htmlField" title="Not Great">2 stars</label>
<input type="radio" checked="@checked1" id="star1-@htmlField" name="@htmlField" value="1" /><label for="star1-@htmlField" title="Pretty Bad">1 star</label>
</div>

Here’s a breakdown of the interesting bits that make this work:

  • The model is of type int, allowing it to be rendered for properties of the same type.
  • There is the use of nullable attributes in play, set up with the check against the model so that we can correctly render which star is to be selected. This is important when our model already has a value.
  • The radio buttons are ordered in reverse and take their name from the ViewData.TemplateInfo.HtmlFieldPrefix value.
  • We use an ID on each star, and a label that is related back to that input. This allows selection via the label (you should always use this!)

Viola! With the CSS from above in place, the custom editor template saved and the UIHint on your Movie model class, your page will now be rendered with a star rating control for your movie.

Set a breakpoint in your POST action of your controller. If you submit your form while debugging, you will see that the value you have selected is indeed bound to the property of the Movie class. Huzzah!

Credits

I have leaned on many star rating controls over the last decade, but have come back to variants of this one (based on this work from @Lea Verou) for the last two or three years now. I would like to stress that I haven’t yet found a perfect control (this one, for example works well with up/down arrows, but not left/right) and I am sure this version won’t work for all people in all scenarios. Also, the idea for this example came from the Font Awesome site, but the astute reader would soon realize why the basic example on their site would not be a good candidate for MVC (primarily because of the lack of structure to accommodate multiple controls on the same page).

Next Steps

If you’ve built the sample along with the article, you’ll likely have had at least a few ideas on how you can create reusable controls for your project. Be sure to check out my Bootstrap series or purchase a copy of my book for more examples like this, and happy coding!

Adding Some (Font) Awesome to MVC and Bootstrap

While Bootstrap includes many great icons from Glyphicons baked right in, I’m often left looking for That One Missing Graphic when I try to put a project together. In this post we’ll look at the open source Font Awesome collection of images that serve as a wonderful addition to your site in the form of a font and CSS toolkit.

See more tips, tricks and tutorials like this in my book, Bootstrapping MVC.

Just a quick note: If you already know what Font Awesome is and just want my advice on how to add it to your project via NuGet, skip to the end of the post. If you want more background on what Font Awesome is and why you might want to use it, grab a coffee and have a read!

A Bit About Font Awesome

A Picture of a Heart IconFont Awesome is a font and CSS toolkit that was created by Dave Gandy, originally designed to be a compliment to the Bootstrap library. There is no JavaScript component to it and it does not add any new behaviors to your site, but it does have some great-looking, scalable icons that you’ll likely love.  See what I did there, with the heart? Winking smile

There are two core elements to using the library: the font files themselves and the CSS classes that wire things up for use on your site. With the library in place, you can get the above heart icon to appear simply by adding the following syntax:

<i class="fa fa-heart"></i>

Because it’s implemented as a scalable vector-based font, rather than raster images, the icons look great on any screen type and at any size. You get the base styling, margins, sizing and the like by attributing the <I> element with the fa class, then select your icon by name. There are CSS classes for creating variant sizes (twice as large):

<i class="fa fa-camera-retro fa-2x"></i>

…adding spinner effects (here, a spinning cog):

<i class="fa fa-cog fa-spin"></i>

…or stacking images together to make composite icons, like a flag on a circle:

<span class="fa-stack fa-lg">
  <i class="fa fa-circle fa-stack-2x"></i>
  <i class="fa fa-flag fa-stack-1x fa-inverse"></i>
</span>

…as well as other options, like rotating and flipping, adding borders and pulling the icons to the left or right. You can find the complete source on the Font Awesome examples page.

While these display classes are all built to work with Bootstrap natively, the CSS for Font Awesome also includes everything it needs class-wise (such as pull-left) to work independently of Bootstrap.

The icons tend to be aptly named and terse, so you’re not typing a metric tonne of code. I’m using Visual Studio 2013 and working with the library is a breeze because of the automatic syntax completion offered through IntelliSense.

HTML Code: <i class="fa fa-heart"></i>

If you download the ZIP from the Font Awesome site, you’ll get the CSS (and minified version), the font files for multi-platform and multi-browser support as well as the LESS and SCSS files to customize things should you so need.

A Note on Accessibility

Though the icons and images of Font Awesome are indeed implemented as a font, it’s not like wingdings or anything where a letter becomes repurposed. The author elected to use the standards-based Private Use Area mapping from Unicode, meaning screen readers for accessibility will ignore the characters of the font and not attempt to read random characters off.

The Naked “Installation”

From the docs on the site, the easiest way to start using Font Awesome is just to use the CDN version of the toolkit.

<link href="//maxcdn.bootstrapcdn.com/font-awesome/4.1.0/css/font-awesome.min.css" rel="stylesheet">

Using the CDN version may help improve load times, especially when your users are spread out over multiple geographic regions. Not all corporate policies allow for public CDN use for in-house projects, however, so you still have the option to download and use Font Awesome as an asset in your deployment.

Solution structure for typical installation of Font AwesomeIf you do download the ZIP, you’ll need to execute a couple of familiar and straightforward tasks to use the toolkit:

  • Copy the CSS and Fonts folder into your project, likely under the Content folder
  • Add a new bundle to your site and include the CSS in your _Layout (or modify an existing, in-use bundle to include the CSS).

The only thing to watch for is that you’re going to need to honor the relative path structure of the CSS and Fonts to avoid any rendering problems. The CSS assumes the fonts are in a folder called Fonts at the same level in the path.

Using a NuGet Package

There’s always an easier way to do it, and usually the way to do that with .NET is going to involve a little bit of NuGet.

I found no fewer than half a dozen packages on NuGet for Font Awesome. While they all seem to list Mr. Gandy as the author, none of them appear to be officially part of the project. So, for better or for worse, there’s no officially sanctioned project here. Just the same, the packages are there if you want to use them and I have my opinions on them. Smile

The package I recommend is FontAwesome.MVC by JiveCode aka JustLikeIcarus. This package takes a dependency on his Font Awesome package containing the CSS and fonts, then it adds a class (FontAwesomeBundleConfig) that registers a style bundle for you.

All that’s left to do is to modify your _Layout, adding the following line of code to your HEAD:

@Styles.Render("~/Content/fontawesome")

There are other packages that use Font Awesome and try to augment MVC giving your Razor helper methods, but I’ve got mixed feelings on this approach. A Razor helper that requires me to type more code and allows me to know less about the CSS I’m using doesn’t feel quite right. With IntelliSense support for CSS in VS, I’m not sure I see the need for Razor helpers, and I really like learning the classes I’m using.

Next Steps

With a groovy new set of icons now available to my site, my next post will be on leveraging those to create something interesting with the MVC Framework.

Like this post? You can see more tips, tricks and tutorials
like this in my book, Bootstrapping MVC.

Happy coding! Smile