Day 11: Realistic Test Data for Our View

This is an installment in a 30 day series on Bootstrap and the MVC Framework. To see more, check out Day 0 for an index.

If a controller deals with a certain type of data – say, entities of the Person type – the index will typically contain a collection of data of that type, or perhaps some other related interface (such as search or filter capabilities, or partial views of related data). Let’s add a PersonController and get a feel for what that looks like.

Creating the Person Controller

Back on Day 3 we added a SimpleController to our project. Use the same approach to create a new, empty controller now called PersonController.  The Index method is the only one in the class, but it’s going to need some data.

Generating Realistic Test Data

Now, we have a couple of options to get data. We can hand-bomb 25 (or 5 or 10 or 100) entries into some kind of text file. We can new up dozens of objects with copy & paste and have 60 of the exact same person. Or, we can use a test data generator while we flush out our application and get realistic test data with minimum effort.  Let’s try that!

Go to your Package Manager Console. If you don’t see that window, typically in the bottom of Visual Studio in one of the tabs. If you still don’t see it, try opening it from View –> Other Windows –> Package Manager Console.

Now, let’s install a package that will generate our data for us, called AngelaSmith. Type the following command in the Package Manager Console:

Install-Package AngelaSmith -Version 1.0.1
You should see confirmation that the package is installed. ## Configuring AngelaSmith We’ll need a place to store the data that is generated, so at the class level, add a static field.
private static ICollection<Person> _people;
We’re making it static so that we don’t have to recreate the data on each page load, just when the app starts up.  Now add a static controller to configure the data generator.
static PersonController()
{
    _people = Angie.Configure<Person>()
        .Fill(p => p.BirthDate)
        .AsPastDate()
        .Fill(p => p.LikesMusic)
        .WithRandom(new List<bool>(){true, true, true, false, false})
        .Fill(p => p.Skills, () => new List<string>() { "Math", "Science", "History" })
        .MakeList<Person>(20);
}
It might seem like a lot is going on, but it’s actually quite straightforward. First is a call to the Configure method to enter configuration mode.
_people = Angie.Configure<Person>()
Then we have three Fill statements that demonstrate a few of the ways that we can generate data. For example, you can get a date from the past, fill a property with a random value (60% of the time LikesMusic will be true), or, here, use a lambda to set up an anonymous function to populate the value.
.Fill(p => p.Skills, () => new List<string>() { "Math", "Science", "History" })
Finally, we call the MakeList method to get the list of 20 entities. By default, it will generate 25 but you can specify however many you like.
.MakeList<Person>(20);
## Adding the Index View We’ll need to pass the view some data, when it’s ready, so let’s now update our Index method so that it does that.
public ActionResult Index()
{
    return View(_people);
}
You’re going to like this part. Add an empty View to the project by right-clicking on the Index method of the Person Controller. Then add the following code:
@model IEnumerable<SimpleSite.Models.Person>

@Html.DisplayForModel(Model)

Yeup! That’s it! Run your site to see your list of peeps!

image

Next Steps

Now that we’ve got some data to work with, let’s start exploring the parts of Bootstrap that can be easily used to add some zing to our site. Tomorrow, we’ll create a form that can be used to search our people.

Day 10: HtmlHelper Extension Methods

This is an installment in a 30 day series on Bootstrap and the MVC Framework. To see more, check out Day 0 for an index.

As we extracted our Person template we stubbed in a placeholder for a person’s avatar. Rather than creating our own system for uploading, resizing and storing the images, we’ll use a commonly used service on the internet called Gravatar to display one that many users might already have.

A Gravatar Extension Method

The format for Gravatar images is as follows:

http://www.gravatar.com/avatar/MD5HASH?options

The MD5 hash is computed based on their email address, and there are a few options worth noting. Below are the querystring parameters we’ll be using to generate our image.

  • Default Image: the image or type of image to use or generate if there isn’t a Gravatar for the specified email address.
  • Size: the size of the image to be returned, always a square.
  • Rating: users self-specify their rating and can use different avatars for different audiences.

We’ll represent those options in an class that we’ll use as a parameter.  Create a Helpers folder, then create a class called GravatarOptions in it.

public class GravatarOptions
{
    public string DefaultImageType { get; set; }
    public string RatingLevel { get; set; }
    public int Size { get; set; }

    public class DefaultImage
    {
        public const string Default = "";
        public const string Http404 = "404";
        public const string MysteryMan = "mm";
        public const string Identicon = "identicon";
        public const string MonsterId = "monsterid";
        public const string Wavatar = "wavatar";
        public const string Retro = "retro";
    }

    public class Rating
    {
        public const string G = "g";
        public const string PG = "pg";
        public const string R = "r";
        public const string X = "x";
    }

    internal static GravatarOptions GetDefaults()
    {
        return new GravatarOptions
        {
            DefaultImageType = GravatarOptions.DefaultImage.Retro,
            Size = 150,
            RatingLevel = GravatarOptions.Rating.G
        };
    }
}
And finally, add a class called GravatarHelper, then add the following code:
public static class GravatarHelper
{
    public static HtmlString GravatarImage(this HtmlHelper htmlHelper, string emailAddress, GravatarOptions options = null)
    {
        if (options == null)
            options = GravatarOptions.GetDefaults();

        var imgTag = new TagBuilder("img");

        emailAddress = string.IsNullOrEmpty(emailAddress) ? string.Empty : emailAddress.Trim().ToLower();

        imgTag.Attributes.Add("src",
            string.Format("http://www.gravatar.com/avatar/{0}?s={1}{2}{3}",
                GetMd5Hash(emailAddress),
                options.Size,
                "&d=" + options.DefaultImageType,
                "&r=" + options.RatingLevel
                )
            );

        return new HtmlString(imgTag.ToString(TagRenderMode.SelfClosing));
    }

    // Source: http://msdn.microsoft.com/en-us/library/system.security.cryptography.md5.aspx
    private static string GetMd5Hash(string input)
    {
        byte[] data = MD5.Create().ComputeHash(Encoding.UTF8.GetBytes(input));
        var sBuilder = new StringBuilder();
        for (int i = 0; i < data.Length; i++)
        {
            sBuilder.Append(data[i].ToString("x2"));
        }
        return sBuilder.ToString();
    }
}
Extension methods accept the type you are extending as the first parameter and operate on the instance of the object, though they are defined as a static. This may help understand why you must pass the first parameter as the type you want to extend with the _this_ modifier.  You can then optionally any additional parameters that you will need to work with. For us, we’re just accepting the email address and a GravatarOptions instance. In our helper, we create a tag builder for images, then build the URL based on the options the user has provided. If they haven’t provided the parameter, we simply load a set of defaults from our options class. _**Note**: This is an overly-simplified version of [Andrew Freemantle’s](https://github.com/AndrewFreemantle) work on his [Gravatar-HtmlHelper](https://github.com/AndrewFreemantle/Gravatar-HtmlHelper) project on GitHub. Please visit his project for a more complete implementation._ ## Using the Gravatar in our Person Template Our HTML helper will work like any other HTML helper, but we need to let the MVC Framework know where to find it. To do so, we’ll have to go and add the namespace to our Web.Config in our Views folder (located at Views\Web.Config). We could also add a using statement to each page where we want to use our helper, but adding it to the web config file makes it globally available throughout our views. Add the following to the Razor namespaces section in that file:
<add namespace="SimpleSite.Helpers"/>

We’ll need an email address, so add the following property in Person.cs.

public string EmailAddress { get; set; }

Next, jump back into your SimpleController class and update the instantiation of the person object so that they have a value in there:

var person = new Person
{
FirstName = “Billy Jo”,
LastName = “McGuffery”,
BirthDate = new DateTime(1990, 6,1),
LikesMusic = true,
EmailAddress = Bill@jo.com,
Skills = new List<string>() { “Math”, “Science”, “History” }
};

Now, update your Person.cshtml template by replacing the image tag with the following:

@Html.GravatarImage(Model.EmailAddress)

Then, pop into your browser to see the fruits of your effort!

image

The gravatar image will be updated for any email address that you put in. You can try playing with the different defaults, your own email address or other options.

Another note: I wouldn’t actually advocate creating a full implementation of an HtmlHelper method for Gravatars. The point of this exercise was to walk through a simple implementation, but there are much more complete helpers available on NuGet, ready to be deployed to your app. If you’d like to work on one of them, they are pretty much all open source, so feel free to contribute!

Next Steps

Great, now we have a basic extension method to make outputting a Gravatar much more simply, but we’re going to need to address our Index view. It’s typically a list of entities, with a link to a details view, not just a single item. Tomorrow, we’ll tackle getting that list set up and move the single view version to it’s own action and view.

Day 9: Templates for Complex Types

This is an installment in a 30 day series on Bootstrap and the MVC Framework. To see more, check out Day 0 for an index.

Sites like Facebook and Twitter or any site with a “feed” often present their data in a stream of “cards” or “blocks” that are repeatable and consistent, regardless of where you see the snippet of data. Let’s take the UI we created for the Person, augment it a little bit and then make it reusable wherever we might want it displayed.

Extracting the Person Template

We’re going to build from the idea of using the DisplayTemplates in our Views\Shared folder, and add another file in there called Person.cshtml. Just right-click on the Views\Shared\DisplayTemplates folder and click Add –> View. Name the view Person, use the empty template and create it as a partial.

Now paste the following code into the file:


@model SimpleSite.Models.Person

 

<hr />
<div class=”row”>
<div class=”col-md-2”>
<img src=”http://placehold.it/150x150" />
</div>
<div class=”col-md-8”>
<h3>@Model.FirstName @Model.LastName</h3>
<p>@Model.FirstName was born on @Model.BirthDate.ToString(“D”).</p>
<p>Likes Music: @Html.DisplayFor(model => model.LikesMusic)</p>
@{
ViewBag.ListDescription = “Skills:”;
Html.RenderPartial(“StringCollection”, Model.Skills);
}
</div>
</div>

Most of this you should recognize as fairly close to the code we were using in our Index view for the simple controller. Above, I’ve added some columns and a placeholder image so that we can later give users an avatar. But I’m otherwise continuing to use the same elements we were building off of before, such as the DisplayFor and RenderPartial bits we’ve been working on.

Updating the Index View

The end result is that our Index view can be _much _simpler than it was. Here is what you need for the whole view source of Index.cshtml:

@{
ViewBag.Title = “Index”;
var likesMusic = Model.LikesMusic ? “active” : null;
var notAMusicFan = !Model.LikesMusic ? “active” : null;
}

<div class=”page-header”>
<h1>Welcome to the Person Page <small>Read all about @Model.FirstName</small></h1>
</div>

@Html.DisplayForModel(Model)

The DisplayForModel tries to find a display template that matches the type of model that is passed in, and sure enough, naming our partial view above “Person” and placing it in the Views\Shared\DisplayTemplates folder was all we needed to do to wire that up. It’s another example of “convention over configuration” at work in the MVC Framework.

Next Steps

I’ve used only one set of layout classes as styles for my person template. Later in the month we’ll explore how to make this even more reusable by introducing classes that allow the content to be rendered on different devices and screen sizes.

The placeholder image is okay, but we’d likely prefer to use an image related to the user. Tomorrow we’ll look at a way to implement an extension method that allows us to drop in a Gravatar image for any user.

Day 8: Semi-Automatic Bootstrap – Editor Templates

This is an installment in a 30 day series on Bootstrap and the MVC Framework. To see more, check out Day 0 for an index.

Now that we have a nice way to consistently display our data, what about editing it? A label is fine to indicate what the saved value is, but it doesn’t really solve the issue of input.

Introducing Editor Templates

Much in the same way that a shared view can act as the de facto template for rendering data (as we saw yesterday), you can override the default editor output by the framework. Create a new view in Views\Shared\EditorTemplates called Boolean.cshtml and put the following code in it:

@model bool?

@{
// make use of nullable class attribute values
var yesSelected = Model.HasValue && Model.Value ? “active” : null;
var noSelected = (Model.HasValue && !Model.Value)
|| (!Model.HasValue && ViewData.ModelMetadata.IsNullableValueType)
? “active”
: null;
var noSelection = !Model.HasValue ? “active” : null;

<span class="rem">// get the name of the ID - this is to support multiple fields</span>
var htmlField = ViewData.TemplateInfo.HtmlFieldPrefix;

}

@Html.HiddenFor(model => model)

<div class=“btn-group” data-toggle=“buttons”>
<label class=“btn btn-info @yesSelected”>
<input type=“radio” class=“bool-@htmlField” onchange=“javascript:$(‘#@htmlField’).val(true);” /> Yes
</label>
<label class=“btn btn-info @noSelected”>
<input type=“radio” class=“bool-@htmlField” onchange=“javascript:$(‘#@htmlField’).val(false);” /> No
</label>

@<span class="kwrd">if</span> (ViewData.ModelMetadata.IsNullableValueType)
{
    &lt;label <span class="kwrd">class</span>=<span class="str">"btn btn-info @noSelection"</span>&gt;
        &lt;input type=<span class="str">"radio"</span> <span class="kwrd">class</span>=<span class="str">"bool-@htmlField"</span> onclick=<span class="str">"javascript:$('#@htmlField').val('');"</span> /&gt;Do Not Set
    &lt;/label&gt;

}

</div>

There are two important pieces to note in the above code, namely the inspection of TemplateInfo and ModelMetadata in the ViewData instance presented to our view, and the hidden backing field that is kept in sync via JavaScript. ViewData is a ViewDataDictionary that contains, as those properties suggest, metadata about the type of model being used, information about the template, and other view-specific data.

To see this new template in action we’ll have to get a Create view set up and an action on our controller. Head back to the SimpleController class and add the following code:

public ActionResult Create()
{
var person = new Person();
return View(person);
}

Now, right-click on the name of the method, and select “Add View…”, then set it up to use the Create template for the Person class.

image

Visual Studio will throw you into the editor for your new view, and you can press CTRL+F5 to see your new default control for Boolean values, or navigate to http://localhost:_port_/Simple/Create to see the page.

The scaffolded view contains simple calls to HTML helpers and doesn’t know anything about the instance of the Person that will be created or the fact that you’ve created a new template to render Boolean values. You’ll only see the following:

@Html.EditorFor(model => model.LikesMusic)

As well, the templates are rendered on the fly by the view engine (just like all views) so you don’t need to recompile as you make updates. Feel free to experiment with the template code and just refresh in your browser after you save.

Note that our Person class doesn’t have a nullable Boolean value, but it if did, it would render like so because of our evaluation of the ModelMetadata in the template above:

image

Controlling the Use of Custom Templates

Now these new controls – button groups for input and labels for display – work great, but you may not wish to use them for all Boolean properties. In both the DisplayTemplates and EditorTemplates folders, rename the Boolean template to BooleanButtonLabel.cshtml. Then, return to your Person class and decorate the LikesMusic property as follows:

[UIHint(“BooleanButtonLabel”)]
public bool LikesMusic { get; set; }

There may be scenarios where you wish to use several alternate templates to display or edit data. This attribute gives the MVC Framework directions to use a template of our choosing, rather than having to use the same template for all properties.

Next Steps

You can now render simple properties with whichever template you wish, but what about more complex types? Tomorrow we’ll look at using a custom template at a class level.

Day 7: Semi-Automatic Bootstrap – Display Templates

This is an installment in a 30 day series on Bootstrap and the MVC Framework. To see more, check out Day 0 for an index.

On Day 6 we looked at the idea of using a partial view to make it easier to render certain types of data more easily. We can go even further, and allow the scaffolder and HTML helpers to render what we’re looking for without the need for the additional calls to render partials.

If you provide the MVC Framework with a template to render a type and give the right kind of hints to your class properties you’ll be duly rewarded with ease of effort in bringing a rich UI to the client. For now, we’ll start with the display end of things.

Bootstrap Styling for Checkboxes

We can really use any type that we want, but I’m going to start with Boolean properties. While they seem at first to be straightforward, they also provide a nullable case that we will need to deal with and render appropriately, much like any other type, yet they’re simple enough that we can work through an starter example.

What we’re doing here is creating a Display Template. You can think of it as a partial view in a way, but you usually do a bit more to inspect the properties and interact with data from the view engine in order to properly augment the rendering. We’ll see more of this tomorrow.

Enough chatter…now create a new folder called and located at Views\Shared\DisplayTemplates and create a file in there called Boolean.cshtml, then paste in the following code:

@model bool?

@if (Model.HasValue)
{
if (Model.Value)
{ <span class=“label label-success”>Yes</span> }
else
{ <span class=“label label-warning”>No</span> }
}
else
{ <span class=“label label-info”>Not Set</span> }

As the view that is responsible for rendering Boolean values, we must first set the model type of the view. I’ve used a nullable bool as it’s more durable and works with either the basic bool or the nullable version.

The rest of the code is fairly straightforward, just determine if there’s a value or not, then set up the label based on the value or lack thereof.

Using the Display Template

Because we named it “Boolean.cshtml”, the MVC Framework will use our template in favor of the built-in template for Booleans, which you’ll recall from Day 4 was simply a checkbox. We saw something like this:

 image

But with the new template in place, we’ll see this:

image

You can modify your Index.cshtml at this point to see this in action by adding the following line of code:

<p>Likes Music: @Html.DisplayFor(model => model.LikesMusic)</p>

And that’s it, a call to DisplayFor makes the magic happen. From now on, all Boolean values will be rendered as yes/no/not set labels throughout your site.

Next Steps

Of course, the display is interesting enough, but what about editing? What if you don’t want all checkboxes to suffer the same disappearing fate? Tomorrow we’ll look at getting the editor in place and to give the MVC Framework more direction on when to use it.

Day 6: Reusing Design Elements on Multiple Pages

This is an installment in a 30 day series on Bootstrap and the MVC Framework. To see more, check out Day 0 for an index.

While it’s important to learn the mechanics of the underlying technology we use, it’s never really much fun to have to do the same work over and over again. That’s part of why we’re here; rather than hacking out the CSS for each site or page, we use frameworks and libraries to bring a uniform look-and-feel.

Likewise, we want to make sure we’re leveraging the MVC Framework to do the heavy lifting for us when we’re trying to get our data out to the client.

Layouts and Partial Views

Back on Day x I briefly mentioned the layout page, located in your Views\Shared directory. This type of “master page” gives you the ability to create a template that can be shared on all pages where you want to wrap your content with common elements, such as side bars, menus, footers and the like, or likewise, to stuff in client-side application scripts, style sheets and other elements.

At the other end of the layout page is the concept of a partial view – a template that can be used to render a specific kind of content in different pages. You may also hear them called by the shortened name of “partials”. This allows you to define one time how a set of data will be rendered and then include the partial wherever you need to render the content.

Creating a Partial View

Let’s consider for a moment the section of labels that is rendered at the bottom of our person page that lists the skills.

image

That block of skills is really just a collection of strings that we are displaying as labels decorated with Bootstrap styling. I could imagine that would be handy to have in other places on my site as well.

Let’s look at that code again quickly and see what we have going on.

<div>
<p>
Skills:
@foreach (var skill in Model.Skills)
{
<span class=”label label-primary”>@skill</span>
}
</p>
</div>

Essentially, we’re dumping a bunch of span elements to the page inside of a p tag, all wrapped up in a div. Not too complex. There is a title to describe the list of labels, and a for..each loop that walks over the collection to dump the labels to the page.

Let’s cut that code to the clipboard and paste it into a new file in the Views\Simple folder called _StringCollection.cshtml. You can add the file by right-clicking on the Simple folder and selecting Add –> View. When prompted, make sure to tick the “Create as Partial View” so that the scaffolder doesn’t set the layout or title, and select the “empty (without model)” template. Using the underscore as a prefix is a convention to let others (and remind yourself) that the file is intended be rendered as a partial view.

Paste the code into the file and update it a little so that the entire partial matches the following code, including the model definition at the top:

@model ICollection<string>

<div>
<p>
@ViewBag.ListDescription
@foreach (var value in Model)
{
<span class=”label label-primary”>@value</span>
}
</p>
</div>

Notice that rather than just writing out “Skills” to the page ahead of our labels, we’re now using a property from the ViewBag. Now, return to your Index.cshtml and, in the place of the code that you removed, add the following lines to your view:

@{
ViewBag.ListDescription = “Skills:”;
Html.RenderPartial(“_StringCollection”, Model.Skills);
}

Run your newly updated page and see…well, you’ll see exactly what we had before, but we’re doing it a little more cleverly!

Here we’ve set the title and then asked Razor, the view engine, to process the partial view file with the contents of the string collection we’ve passed in. From now on, anywhere in our site, we can push a collection of strings into a label set with a title in two lines of code.

Next Steps

This isn’t the only way that we can render a type of data with some kind of enhanced templating. Tomorrow we’ll look at making it even more effortless to get our data all fancied up for the ball.