OdeToCode IC Logo

ELMAH and MiniProfiler In ASP.NET MVC 4

Tuesday, September 11, 2012 by K. Scott Allen

If you are new to ASP.NET MVC you might not know about ELMAH and MiniProfiler. These are two distinct OSS projects that you can easily install with NuGet, and both provide valuable debugging and diagnostic services. Scott Hanselman has blogged about both projects in the past (see NuGet Package of the Week #7, and #9), but this post will highlight some of the updates since Scott's post and still provide a general overview of the  features for each project.

ELMAH

ELMAH gives you "application-wide error logging that is completely pluggable". In other words, you can easily log and view all the errors your application experiences without making any changes to your code. All you need to get started is to "install-package elmah" from the Package Manager Console in Visual Studio and ELMAH will be fully configured and available. Navigate to /elmah.axd in your application, and you'll see all the errors (this will only work for local requests, by default).

ELMAH Error Log

ELMAH will keep all the errors in memory, so an application restart will clear the log. If you want the error information to stick around longer, you can configure ELMAH to store information in a more permanent location, like inside of a database. The elmah.sqlservercompact package will add all the configuration you need to store the error log in a SQL Compact database file inside the App_Data directory of the app. There are also packages to log errors to SQL Server (elmah.sqlserver), Mongo (elmah.mongodb) and more. Most of these packages require you to go into the web.config file to configure simple connection string settings, and possibly setup a schema (see the files dropped into App_Readme for more details).

ELMAH and HandleErrorAttribute

For ASP.NET MVC projects you might want to start by installing the elmah.mvc package. The elmah.mvc package will install an ElmahController so you can view the error log by visiting the /elmah URL. More importantly, elmah.mvc will install an action filter to log errors even when the MVC HandleErrorAttribute (the one that most applications use as a global action filter) marks an exception as "handled". The HandleErrorAttribute marks exceptions as handled and renders a friendly error view when custom errors are enabled in web.config, which will usually be true when an app runs in production. These handled exceptions are invisible to ELMAH, but not when elmah.mvc is in place.

MiniProfiler

MiniProfiler is a "simple but effective" profiler you can use to help find performance problems and bottlenecks. The project has come a long way over the last year. To get started with MiniProfiler, you can install the MiniProfiler.MVC3 package (which also works in ASP.NET MVC 4). After installation, add a single line of code to your _Layout view(s) before the closing </body> tag:

@StackExchange.Profiling.MiniProfiler.RenderIncludes() 

Update:

You'll also need to add a handler so MiniProfiler can retrieve the scripts it needs:

<system.webServer>
...
<handlers>
<add name="MiniProfiler" path="mini-profiler-resources/*" verb="*" type="System.Web.Routing.UrlRoutingModule" resourceType="Unspecified" preCondition="integratedMode" />
</handlers>
</system.webServer>


Once everything is ready, you'll start to see the MiniProfiler results appear in the top left of the browser window (for local request only, by default). Click on the time measurement to see more details:

MiniProfiler results

MiniProfiler can tell you how long it takes for actions to execute and views to render, and provides an API if you need to instrument specific pieces of code. The MiniProfiler install will also add a MiniProfiler.cs file in your App_Start directory. This file is where most of the MiniProfiler configuration takes place. From here you can enable authorization and database profiling.

Two great projects to check out, if you haven't seen them before.

Seeding an Entity Framework Database From File Data

Monday, September 10, 2012 by K. Scott Allen

The migrations feature of the Entity Framework includes a Seed method where you can populate the database with the initial static data an application needs. For example, a list of countries.

 

protected override void Seed(Movies.Infrastructure.MovieData context)
{
context.Countries.AddOrUpdate(c => c.Name,
new Country {Name = "India"},
new Country {Name = "Japan"},
// ..
);
}

You'll find the Seed method in the migration configuration class when you "enable-migrations" in a project. Since the migrations framework will call the Seed method with every database update you make, you have to be sure you don't create duplicated records in the database. The AddOrUpdate method will help to prevent duplicate data. With the first parameter to the method you specify a property the framework can use to identify each entity. The identifier could be the primary key value of the entity, but if your database is generating the value, as it would with identity columns, you won't know the value. To manage a list of countries, we just want to make sure we don't duplicate a country, so identifying a record using the name of the country will suffice.
 
Behind the scenes, AddOrUpdate will ultimately need to first query the database to see if the record exists and if so, update the record. If the record doesn't exist migrations will insert a new record. AddOrUpdate is not something you'd want to use for millions of records, but it works well for reasonable sized data sets.  However, sometimes you already have the data you need in a CSV or XML file and don't want to translate the data into a mountain of C# code. Or, perhaps you already have initialization scripts written in SQL and just need to execute the scripts during the Seed method.
 
It's relatively easy to parse data from an XML file, or read a SQL file and execute a command. What can be tricky with the Seed method is knowing your execution context. Seed might be called as part of running "update-database" in the Visual Studio Package Manager Console window. But the Seed method might also be called when a web application launches in an IIS worker process and migrations are turned on by configuration. These are two entirely different execution contexts that complicate the otherwise mundane chore of locating and opening a file.

Putting It Somewhere Safe

One solution is to embed the data files you need into the assembly with the migration code. Add the files into the project, open the properties window, and set the Build Action property to "Embedded Resource".
 
Embedding Resources
 
Now you can open the file via GetManifestResourceStream. The Seed method might look like:
 
protected override void Seed(CitationData context)
{

var resourceName = "Citations.App_Data.Countries.xml";
var assembly = Assembly.GetExecutingAssembly();
var stream = assembly.GetManifestResourceStream(resourceName);
var xml = XDocument.Load(stream);
var countries = xml.Element("Countries")
.Elements("Country")
.Select(x => new Country
{
Name = (string)x.Element("Name"),
}).ToArray();
context.Countries.AddOrUpdate(c=>c.Name, countries);
}

 

Notes

The name of the resource is derived from the location of the resource ({ddefault_namespace}.{folder}.{subfolder}.{filename}). In the example above, countries.xml lives in the App_Data folder of the project, and the project's default namespace is "Citations". If you don't like the name, you can change it.
 
For .sql scripts you can use context.Database.ExecuteSqlCommand, but you'll need to break the file into separate commands if there are delimiters inside (like "GO").
 
Finally, if the data is truly static you might consider executing the data load during the Up method of a migration.

Seeding Membership &amp; Roles in ASP.NET MVC 4

Wednesday, September 5, 2012 by K. Scott Allen

Jon Galloway has an overview of the new membership features in ASP.NET MVC 4. The Internet project template moves away from the core membership providers of ASP.NET and into the world of SimpleMembershipProvider and OAuth.

There is quite a bit I could write about the new features and the code generated by the Internet project template, but for this post I just want to cover a scenario I've demonstrated in the past - seeding the roles and membership tables. If you are using Entity Framework code-first migrations it's relatively easy to add some code to the Seed method of the migrations configuration to populate the membership tables with some initial roles and users. Just remember every update-database command will call the Seed method, so you have to write the code to make sure you don't try to create duplicate data.

First, the new project template creates an MVC 4 Internet application without any provider configuration, but for the membership features to work properly during a migration, it appears you need at least some configuration. The following code makes sure the SimpleMembershipProvider and SimpleRolesProvider are in place.

<roleManager enabled="true" defaultProvider="simple">
<providers>
<clear/>
<add name="simple" type="WebMatrix.WebData.SimpleRoleProvider,
WebMatrix.WebData"
/>
</providers>
</roleManager>
<membership defaultProvider="simple">
<providers>
<clear/>
<add name="simple" type="WebMatrix.WebData.SimpleMembershipProvider,
WebMatrix.WebData"
/>
</providers>
</membership>

Then inside the Seed method of the DbMigrationsConfiguration<T> derived class, you can have:

protected override void Seed(MovieDb context)
{
//context.Movies.AddOrUpdate(...);

// ...

SeedMembership();
}

private void SeedMembership()
{
WebSecurity.InitializeDatabaseConnection("DefaultConnection",
"UserProfile", "UserId", "UserName", autoCreateTables: true);

var roles = (SimpleRoleProvider) Roles.Provider;
var membership = (SimpleMembershipProvider) Membership.Provider;

if (!roles.RoleExists("Admin"))
{
roles.CreateRole("Admin");
}
if (membership.GetUser("sallen",false) == null)
{
membership.CreateUserAndAccount("sallen", "imalittleteapot");
}
if (!roles.GetRolesForUser("sallen").Contains("Admin"))
{
roles.AddUsersToRoles(new[] {"sallen"}, new[] {"admin"});
}
}

Working with Enums and Templates In ASP.NET MVC

Tuesday, September 4, 2012 by K. Scott Allen

Imagine you have the following types defined.

public class Movie
{
public int Id { get; set; }
public string Title { get; set; }
public MovieGenre Genre { get; set; }
}

public enum MovieGenre
{
Action,
Drama,
Adventure,
Fantasy,
Boring
}

If you want to display MovieGenre, the DisplayFor helpers generally give you what you expect (i.e. @Html.DisplayFor(m=> m.Genre) displays "Adventure"), but EditorFor will only give you a text input because the framework treats an enum the same as a string.

Default EditorFor with enum

If the user knows your enum values they can type in a value and model binding works correctly, but we certainly don't want users to guess the valid values. A better approach would use a drop down list, or a set of radio buttons, to constrain and guide the user's input. There are a few articles on the web showing how to build a drop down list from enums (Stuart Leeks has a good one - Creating a DropDownList helper for enums). I wanted to try a slightly different approach using templates and supporting localization. If you are familiar with templates in ASP.NET MVC, see Brad Wilson's series on templates and metadata).

Template Selection

The first challenge is getting the MVC framework to select a custom template when it sees @Html.EditorFor(m => m.Genre). If you create a view named MovieGenre.cshtml and place it in the ~/Views/Shared/EditorTemplates folder, the MVC runtime will use the template and you can place inside the template any custom markup you want for editing a Genre. However, trying to have a single generic template (Enum.cshtml) for all enums won't work. The MVC framework sees the enum value as a simple primitive and uses the default string template. One solution to change the default framework behavior is to write a custom model metadata provider and implement GetMetadataForProperty to use a template with the name of "Enum" for such models.

public override ModelMetadata GetMetadataForProperty(
Func<object> modelAccessor, Type containerType, string propertyName)
{
var result = _inner.GetMetadataForProperty(modelAccessor, containerType, propertyName);
if (result.TemplateHint == null &&
typeof(Enum).IsAssignableFrom(result.ModelType))
{
result.TemplateHint = "Enum";
}
return result;
}

The "_inner" field represents the default metadata provider. Depending on how you want to setup the runtime, _inner could also be a call to the base class if you derive from CachedDataAnnotationsModelMetadataProvider. Regardless of the approach, the above code will rely on another provider to do the hard work. The code only throws in "Enum" as the template name to use if there is no template name specified and the model type derives from Enum.

The Template

With a custom metadata provider in place the runtime will locate and use an Enum template when a view uses EditorFor against a MovieGenre property.

Editor templates in place and ready!

The implementation of the template is straightforward. Regardless of the type of UI you want, you'll need to use Enum.GetValues to get all the possible values of the enumeration. You can then use the values to build a drop down list, radio buttons, anything you can image. The following code would render a simple drop down list.

@model Enum

@{

var values = Enum.GetValues(ViewData.ModelMetadata.ModelType).Cast<object>()
.Select(v => new SelectListItem
{
Selected = v.Equals(Model),
Text = v.ToString(),
Value = v.ToString()
});
}

@Html.DropDownList("", values)

Localization and Display Name Customization

Things get a little more complicated in the view if you want to customize the text display of an enum value, or if you want to localize the text using resource files. The Display attribute does most of the work, but as far as I can tell the code has to dig out the attribute on its own (there is no help from the MVC metadata provider). For example, take the following definition for MovieGenre.

public enum MovieGenre
{
[Display(ResourceType = typeof(Resources.Translations), Name = "Action")]
Action,

[Display(Name="Drama!")]
Drama,

Adventure,

Fantasy,

Boring
}

The following template code will display the proper text value, even localized, to the user.

@using System.ComponentModel.DataAnnotations
@model Enum

@{

Func<object, string> GetDisplayName = o =>
{
var result = null as string;
var display = o.GetType()
.GetMember(o.ToString()).First()
.GetCustomAttributes(false)
.OfType<DisplayAttribute>()
.LastOrDefault();
if (display != null)
{
result = display.GetName();
}

return result ?? o.ToString();
};

var values = Enum.GetValues(ViewData.ModelMetadata.ModelType).Cast<object>()
.Select(v => new SelectListItem
{
Selected = v.Equals(Model),
Text = GetDisplayName(v),
Value = v.ToString()
});
}

@Html.DropDownList("", values)

I'd want to measure the performance of the template if it is heavily used in a busy application, but the idea here is to use this approach if you want to create some fancy markup in the template. If all you want to do is ultimately call Html.DropDownList, a custom HTML helper approach is simpler.

Giving Data to JavaScript

Thursday, August 30, 2012 by K. Scott Allen

One set of common questions in the world of ASP.NET MVC & JavaScript revolve around getting data from the server into JavaScript. This isn't about pulling data with SignalR or the WebAPI, but questions along the lines of:

- How do I generate an ActionLink in JavaScript and not hard code a URL?

- How do I get the URL for a WebApi?

- How do I get the ID value of something when the user clicks an item in a list?

If your JavaScript lives inside of your view, you can always use a Razor code expression to inject a value directly into the script. However, this doesn't solve all the scenarios listed above, and if your JavaScript is in an external .js file you don't have the ability to use code expressions. Here are a few techniques I've used to pass computed data from the server to the client.

Using <link>

Generating a <link> tag from a view is simple, and the value can represent an action link, a WebAPI endpoint, or a resource like a template. In the case of the WebAPI, for example, you could emit a link tag from a view using Url.RouteUrl (which requires an httproute member in route values to work properly).

<link id="cartApiUrl" 
href ="@Url.RouteUrl("DefaultApi",
new { httproute = "
", controller = "Cart"})"
rel="api"/>

With jQuery it is easy to find the value of the link, and use the value to call the web service.

var cartApiUrl = $("#cartApiUrl").attr("href");
$.post(cartApiUrl + "/" + itemId).then(updateCart);

Data Attributes

Data- (data dash) attributes are popular because you can embed nearly anything inside, and they are easy to consume from jQuery. Let's take the question of "What item did the user click on?".  If the view renders a data- attribute with an identifier inside, the task is trivial. The view code would look something like the following.

<div>                
<img src="@item.ImageUrl" data-itemid="@item.Id" />
</div>

The JavaScript to retrieve the Id of the clicked item can use jQuery.data.

$("img[data-itemid]").click(function () {
var itemId = $(this).data("itemid");
// ...
});

You can even embed JSON data into a data- attribute, and if jQuery detects JSON data (the value starts with { or [), it will try to parse the value inside and give you an object back. This is useful in cases when you need to build options for a widget, like jQuery UI autocomplete, and include a server generated value (like the URL of the action for autocomplete to use as a data source). The view would look like:

<input type="search" name="q" 
data-quicksearch ='{"source":"@Url.Action("Search")",
"minLength":4, "delay":250}'
/>

Then a few lines of JavaScript could wire up autocomplete throughout an application:

$("input[data-quicksearch]").each(function() {
var input = $(this);
var options = input.data("quicksearch");

// You can now use:
// options.source
// options.minLength
// options.delay

input.autocomplete(options);
});

Dumping Data

Yet another option is to dump a data structure into a view for script to consume. One framework to help with this approach is NGon (inspired by Gon in the Rails world). The NGon implementation takes information you put into a NGon property of the ViewBag and serializes the property into JSON. In a controller action you can throw anything into NGon.

public ActionResult Index()
{
ViewBag.NGon.Count = 3;
ViewBag.NGon.Name = "Home";
ViewBag.NGon.OtherStuff = new[]{2, 4, 6};
ViewBag.NGon.Thing = new Thing
{
Id = 5,
Name = "Home"
};

return View();
}

Then place the serialized data into your view using an HTML helper provided by NGon:

@Html.IncludeNGon()

And on the client, all the values are available to your script code.

var count = ngon.Count;
var thingName = ngon.Thing.Name;

NGon doesn't have a NuGet package and still uses the .NET JavaScriptSerializer (instead of Json.NET). Perhaps there is a pull request in Alex's future.

My Favorite Visual Studio 2012 Features

Wednesday, August 29, 2012 by K. Scott Allen

I've grown fond of the following features in Visual Studio 2012.

Round Tripping Projects

Because Visual Studio 2012 doesn't convert solution and project files, you can use 2012 even when the rest of the team uses VS2010.

Finally!

Quick Launch

Even when you know where the option or menu item lives, it's often quicker to hit Ctrl+Q and type a few letters to find a command or option.

Visual Studio Quick Launch

SQL Server Object Explorer

It's the real object explorer from SQL Server Management Studio - now available in VS. Go to View -> SQL Server Object Explorer, or use a Ctrl+\, Ctrl+S shortcut. You can manage server logins, drop databases, and open a new, un-crippled query window.

SQL Server Object Explorer

 

Search Solution Explorer

Click in the search box underneath the toolbar, or use Ctrl+; to go there and keep your fingers on the keyboard. It's a great way to find, for example, all CSS files in a project. The search parameter stays in effect until you clear the box, and you get to see the files in the their solution hierarchy. It doesn't search just files, though, you can also find members by name.

Search in Solution Explorer

Open Files Filter

When working with a bunch of open files, trying to find a specific file in the horizontal tabs of the editor can be a pain. The Open Files Filter button in the Solution Explorer toolbar can show only the open files in Solution Explorer, being both vertical and hierarchical, can make open files easier to find.

Open Files Filter

Async in Entity Framework 6.0

Tuesday, August 28, 2012 by K. Scott Allen

If you pull the latest Entity Framework source from CodePlex, you can take a look at some of the features being added for the next version of EF. These features include an async API for DbContext (SaveChangesAsync and ExecuteSqlCommandAsync), as well as async operations on IQueryable<T> through some new extension methods.

Here is how the async version of SaveChanges looks in an ASP.NET MVC controller action:

[HttpPost]
public async Task<ActionResult> Edit(Thing thing)
{
if(ModelState.IsValid)
{
_db.Entry(thing).State = EntityState.Modified;
await _db.SaveChangesAsync();
return RedirectToAction("Index");
}

return View(thing);
}

The new IQueryable operators are async versions of operators that materialize a concrete result. For example, finding a single entity:

[HttpGet]
public async Task<ActionResult> Edit(int id)
{
var model = await _db.Things.FindAsync(id);
// or
var model = await _db.Things.SingleAsync(t => t.Id == id);

return View(model);
}

Also forcing execution with ToList:

public async Task<ActionResult> Index()
{
var model = new HomeIndexViewModel();
model.Things = await _db.Things.ToListAsync();

return View(model);
}

Getting an application up and running with EF 6 (including migrations) is slightly challenging, but I've found the easiest approach is to msbuild the Nuget.proj file in the NuGet directory, then adding the NuGet\bin\debug directory as a custom local NuGet repository and adding references to EF 6 via NuGet. I also had to register all the EF assemblies for verification skipping with sn -Vr.