Giving Data to JavaScript

Thursday, August 30, 2012 by K. Scott Allen
9 comments

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
12 comments

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
6 comments

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.

ASP.NET MVC - Highlight Current Link

Monday, August 27, 2012 by K. Scott Allen
10 comments

In an ASP.NET MVC application, there are many different solutions you might use to highlight the menu item for the current location.

Highlight current item

Here's one - a custom HTML helper for building menu items. The custom helper will detect if the link is a link to the current action, and if so the helper adds an additional CSS class to the link (currentMenuItem).

public static MvcHtmlString MenuLink(
this HtmlHelper helper,
string text, string action, string controller)
{
var routeData = helper.ViewContext.RouteData.Values;
var currentController = routeData["controller"];
var currentAction = routeData["action"];

if(String.Equals(action, currentAction as string,
StringComparison.OrdinalIgnoreCase)
&&
String.Equals(controller, currentController as string,
StringComparison.OrdinalIgnoreCase))

{
return helper.ActionLink(
text,action, controller, null,
new { @class="currentMenuItem"}
);
}
return helper.ActionLink(text, action, controller);
}

Use the helper when building a menu in your Layout view.

<li>@Html.MenuLink("Contact", "Contact", "Home")</li>

And don't forget to add some styles to make the current link appear differently from the other links.

ul#menu li a {
background: none;
color: #999;
padding: 5px;
border-radius: 15px;
text-decoration: none;
}

ul#menu li a.currentMenuItem {
background-color: black;
color: white;
}

Another variant would be for the helper check the current controller name only when deciding to mark a link as current.

Levels Of Abstraction In An MVC View

Thursday, August 16, 2012 by K. Scott Allen
2 comments

Working on a dashboard I came across a view arranged like the following diagram:

bad dashboard

The scenario is simplified because there is more to do inside of one block than just @SomeOutput, but focus on the structure of the view. I needed to add some more behaviors to the dashboard using CSS and script code, but it only took a few minutes to achieve frustration. Sometimes the view would delegate to a partial view for a specific section of the dashboard, and sometimes the view would inline all the markup and code for a section. Then there was also the odd case of having one partial view responsible for two entire sections of the dashboard, which threw me off entirely. Being new to the code it took some time to figure out how the pieces worked together to produce the page. 

Before I started making my own changes, I did a little refactoring to structure the view like so ...

better dashboard

... and then development life was easier. The mental model of how to map from implementation to output was simplified, and I instantly knew where to go to make different changes.

There are a number of ways you could spin this story. You could argue how the original view violated the single responsibility principle since it was taking responsibility for providing the structure of the dashboard and rendering some of the details. I’d agree with this argument. You could also argue the original view violated the single level of abstraction principle, and I’d agree with that argument, too.

In the end I simply liked the solution better because it seemed simple and symmetrical. Not many people talk about the aesthetic qualities of balance and symmetry in code, but I think it is a sign of craftsmanship that can benefit software by making code easier to understand and maintain. I bet the dashboard changes again in 3 months, and hopefully the next person has an easier time making those changes.

A Troubleshooting Guide for Entity Framework Connections And Migrations

Wednesday, August 15, 2012 by K. Scott Allen
8 comments

The Entity Framework DbContext class uses a convention over configuration approach to development. When everything is working correctly, you can generate and populate a database just by writing a little bit of code and running “enable-migrations” and “update-database” from the Package Manager Console window in Visual Studio. No XML mapping or configuration files are required, see EF Code-Based Migrations Walkthrough for more details.

When things do not work, the conventions are frustrating because they form an impenetrable fog of mystery. Of course, having everything explicitly configured isn’t always clearer or easier to troubleshoot, but here are some common problems I’ve observed with EF 4.1 – EF 5.0, and some steps you can take to avoid the problems.

Cannot Connect to a Database

A couple popular errors you might run across include:

“System.Data.ProviderIncompatibleException: An error occurred while getting provider information from the database”

And the timeless message:

“System.Data.SqlClient.SqlException: A network-related or instance-specific error occurred while establishing a connection to SQL Server.

These messages can happen at any stage, from enable-migrations, to update-database, to running the application. The key to getting past one of these messages is figuring out which database the framework is trying to reach, and then making that database available (or pointing the framework somewhere else).

The first step I would recommend is trying to determine what connection string the framework is using, because the exception doesn’t tell you the connection string, and the connection string can be controlled by a variety of conventions, configurations, and code.

To find out the connection string, I’d add some logging to a default constructor in my DbContext derived class.

public class DepartmentDb : DbContext 
{
public DepartmentDb()
{
Debug.Write(Database.Connection.ConnectionString);
}

public DbSet<Person> People { get; set; }
}

Run the application with the debugger and watch the Visual Studio Output window. Or, set a breakpoint and observe the ConnectionString property as you go somewhere in the application that tries to make a database connection.

Chances are you’ll see something like the following:

Data Source=.\SQLEXPRESS;Initial Catalog=SomeNamespace.DepartmentDb;Integrated Security=True;

When there is no other configuration or code in place, the Entity Framework will try to connect to the local SQL Server Express database (.\SQLEXPRESS). Visual Studio 2010 will install SQL Server Express by default, so if you are not establishing a connection you might have customized the installation, shut down SQL Server Express, or did one of a thousand other things you might possibly do to make the database unavailable (like change the network protocols). One way to see what SQL services are available on your machine is to go to the Package Manager Console in Visual Studio and execute the following command (also showing the output below):

PM> Get-Service | Where-Object {$_.Name -like '*SQL*'}

Status   Name               DisplayName                          
------   ----               -----------                          
Stopped  MSSQLFDLauncher    SQL Full-text Filter Daemon Launche...
Stopped  MSSQLSERVER        SQL Server (MSSQLSERVER)             
Stopped  SQLBrowser         SQL Server Browser                   
Stopped  SQLSERVERAGENT     SQL Server Agent (MSSQLSERVER)       
Running  SQLWriter          SQL Server VSS Writer                

In the above output you can see I do not have a default SQLEXPRESS instance available (it would list itself as MSSQL$SQLEXPRESS), but I do have a default SQL Server instance installed (MSSQLSERVER – but it is not running). I’d have to start the service and give the Entity Framework an explicit connection string for this scenario to work (see Controlling Connections below).

EF 5 and Visual Studio 2012

Visual Studio 2012 installs SQL Server LocalDb by default. LocalDb is the new SQL Express with some notable differences from SQL Express 2008. A LocalDb instance runs as a user process, requires a different connection string, and stores the system databases under your hidden AppData directory.

Since LocalDb is a user process and not a service, you won’t see it listed in the output of the Get-Service command above. You can, however, run SqlLocalDb.exe from the package manager console (or the command line) to see if LocalDb is installed.

PM> SqlLocalDb info
v11.0

If the executable isn’t found, chances are you do not have LocalDb installed. In the above output, I can see I have LocalDb v11.0 installed. EF 5 will use LocalDb if it doesn’t detect SQL Express running, so when you look at the Database.Connection.ConnectionString property in the constructor, like we did earlier, you might  see the following instead:

Data Source=(localdb)\v11.0;Initial Catalog=SomeNamespace.DepartmentDb;Integrated Security=True;

(localdb)\v11.0 is the LocalDb connection string, and if you are not connecting to LocalDb then you might need to reinstall (here is a link that will eventually take you to the MSI file).

Connection Factories

How does the framework know to use LocalDb instead of Express? It’s done through configuration. If you open your application’s config file, you should see the following inside:

<entityFramework>
<defaultConnectionFactory
type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory,
EntityFramework"
>
<parameters>
<parameter value="v11.0" />
</parameters>
</defaultConnectionFactory>
</entityFramework>

Using the LocalDbConnectionFactory means you’ll no longer try to connect to SQL Express by default. There is also a connection factory for SQL Compact. You’ll find this factory in your config file if you install the EF SQL Compact NuGet package.

Insufficient Permissions

Another common problem I’ve seen popping up when using Code First migrations is typically realized with one of the following exceptions:

System.Data.SqlClient.SqlException: Login failed for user ‘[Your account here]'.

... and ...

System.Data.SqlClient.SqlException (0x80131904): CREATE DATABASE permission denied in database 'master'.

These permission issues can be hard to fix. The first thing I’d do is add some debugging code to verify the connection string being used by the Entity Framework (the debugging code demonstrated earlier). Once you know the server the Entity Framework is trying to reach you should try to login to the server with a management tool (like SQL Management Studio, which also works with LocalDb), if you can. The problem is you might not be able to login with your account.

Even if you are an administrator on your local machine you might find yourself with limited privileges in your own, local SQL Server. One scenario where this can happen is when SQL Server or SQL Server Express is installed onto your machine by a different user, or you installed the software using a different account, or perhaps your machine was built from a cloned image file. As of SQL 2008, just being an administrator in Windows doesn’t make you a sysadmin in SQL Server.

To fix the permission issues you can try to login to the server using the sa account, but of course you must know the password and the sa account must be enabled. You can also try to login to your machine using the Windows account used for the software installation. Once logged in with high privileges you’ll need to add your Windows login to the list of SQL Server logins and (ideally) put yourself in the sysadmin server role

When all else fails, you can try to regain control of SQL Server by starting the server in single user mode (see Connect to SQL Server When System Administrators Are Locked Out). The SQL Express blog also published a script to automate this process (see How to take ownership of your local SQL Server), which should also work with SQL 2012. The nuclear option, if you don’t care about any of the local databases, is to uninstall and reinstall SQL Server.

Cannot Attach to Deleted MDF File

If you are using SQL LocalDb, don’t ever delete the physical .mdf and .log files for your database without going through the SQL Server Object Explorer in Visual Studio or in SQL Server Management Studio. If you delete the files only, you end up with an error like the following in a web application:

Cannot attach the file ‘…\App_Data\DepartmentDb.mdf' as database 'DepartmentDb'.

Or the following error in a desktop app:

SqlException: Cannot open database "DepartmentDb" requested by the login. The login failed.

In this case the database is still registered in LocalDb, so you’ll need to go in the Object Explorer and also delete the database here before SQL Server will recreate the files. 

SQL Server Object Explorer in VS2012

Controlling Connections

Explicitly controlling the connection string for the Entity Framework is easy. You can pass a connection string to the DbContext constructor, or you can pass the name of a connection string that resides in the application’s configuration file. For example, the following code will make sure the Entity Framework connects to the local SQL Server default instance and use a database named departments.

public class DepartmentDb : DbContext 
{
public DepartmentDb()
: base(@"data source=.;
initial catalog=departments;
integrated security=true"
)
{
}

public DbSet<Person> People { get; set; }
}

While the following would tell the framework to look for a connection string named departments in the config file:

public class DepartmentDb : DbContext 
{
public DepartmentDb() : base("departments")
{
}

public DbSet<Person> People { get; set; }
}

If the Entity Framework does not find a connection string named “departments” in you config file, it will assume you want a database named departments on the local SQL Express or LocalDb instances (depending on which connection factory is in place).

Finally, if you do not pass any hints to the DbContext constructor, it will also look for a connection string with the same name as your class (DepartmentDb) in the config file.

As you can see, there are lots of options the Entity Framework tries when establishing a connection. The goal of all this work is to make it easy for you to use databases, but when software is misconfigured or not installed correctly, all these options can also make troubleshooting a bit difficult.

Where Are We?

When troubleshooting connection problems with the Entity Framework the first step is to always figure out what server and database the framework is trying to use. If the problems are permission related, the next step is to find a way to make yourself a sysadmin on the server (or at least get yourself in the dbcreator role). If the problem is making a connection to a server instance that doesn’t exist, you can always explicitly configure a connection string for an existing instance of SQL Server.

If all else fails, use SQL Server Compact, as nearly anything you can do with Code-First Entity Framework will work the compact edition of SQL Server.

Configuration Tips For ASP.NET MVC 4 on a Windows Azure Website

Tuesday, August 7, 2012 by K. Scott Allen
12 comments

The new Windows Azure Website feature is easy to use. You can deploy an application by publishing from  Visual Studio or by pushing code with git. There are a few extra configuration steps I’ve found useful.

Using HTTP PUT and DELETE with the ASP.NET WebAPI

Using PUT and DELETE with Azure (or IIS, or IIS Express for that matter) requires some extra configuration before the server will allow messages with these methods into the processing pipeline. By default, IIS will only allow GET, HEAD, POST, and DEBUG. The following configuration section goes inside of <system.webserver>, and will tell IIS to process PUT and DELETE, too.

Note: the final release version of ASP.NET MVC 4 will include this configuration in web.config by default when you create a new project*, but it is still handy for upgrades and to generally know why it exists.

<handlers>
<remove name="ExtensionlessUrl-Integrated-4.0" />
<add name="ExtensionlessUrl-Integrated-4.0"
path="*."
verb="GET,HEAD,POST,DEBUG,DELETE,PUT"
type="System.Web.Handlers.TransferRequestHandler"
preCondition="integratedMode,runtimeVersionv4.0" />
</handlers>

The Usual HTML 5 Media Types

Before IIS will serve a static file it needs to know the media type associated with the file. Video and SVG files were refusing to work until I added the following (also in the <system.webserver> section of web.config):

<staticContent>
<remove fileExtension=".mp4"/>
<remove fileExtension=".ogv"/>
<remove fileExtension=".webm"/>
<remove fileExtension=".svg"/>
<mimeMap fileExtension=".mp4" mimeType="video/mp4" />
<mimeMap fileExtension=".ogv" mimeType="video/ogg" />
<mimeMap fileExtension=".webm" mimeType="video/webm" />
<mimeMap fileExtension=".svg" mimeType="image/svg+xml"/>
</staticContent>

The <remove> entries will allow the configuration to work even on local servers that already have the media types configured (you’ll have a runtime error if you add a duplicate entry, but there is no error if you remove an entry that doesn’t exist).

Automatic Migrations

Finally, if you are using Code First Entity Framework migrations you can have them execute automatically after a release push by adding  to the Web.Release.config file. Web.config transformations even work with git deployments to Azure.

<entityFramework>
<contexts xdt:Transform="Insert">
<context type="EmployeeApp.EmployeeDb, MvcApplication10">
<databaseInitializer
type="System.Data.Entity.MigrateDatabaseToLatestVersion`2[
[EmployeeApp.EmployeeDb,MvcApplication10],
[MvcApplication10.Migrations.Configuration, MvcApplication10]
], EntityFramework"
/>
</context>
</contexts>
</entityFramework>

Of course you’ll need to substitute your own DbContext and Configuration types as the generic type parameters to MigrateDatabaseToLatestVersion. See EF 4.3 Configuration File Settings for more details (yes, it works with EF 5.0, too).

* MVC 4 will also configure ExtensionlessUrlHandler-ISAPI-4.0_32bit and ExtensionlessUrlHandler-ISAPI-4.0_64bit.

by K. Scott Allen K.Scott Allen
My Pluralsight Courses
The Podcast!