Category Archives: Web Development

Using The Google Analytics API With Asp.Net MVC

I’m a big fan of wordpress and really like the Google Analyticator plugin. It provides a dashboard widget that summarizes your analytics stats. I was working on a project that had a relatively sparse admin dashboard and figured I would provide a similar view of analytics stats. The main difference is that the project I was working on was an asp.net mvc3 project.

I searched for some analytics api examples for asp.net and didn’t really find much. So hopefully this will help someone who is looking to consume gdata apis from .net. All of the code is available on github for your viewing pleasure.

What does it look like?

Authenticating with Google Data Api

Authenticating with Google is pretty simple.  Google supports a variety of authentication methods including OAuth2.  I’m not entirely sure why, but I chose to go with their AuthSub method of authentication.  Basically, you redirect the user to a specific Google url, they authorize your application and are returned to your application with a token.  You can then use that token for one-time operation or convert the token to a long lasting token that can be used repeatedly.

The code I use to authenticate looks like:

I store the long lasting token in an embedded instance of RavenDb. It’s a quick & super easy way to store things like that.

Querying Analytics

Now that you have a token from the user, you can query analytics to get data for any site that the user has access to.  Google sites have a unique id associated with them, that Google calls TableId.  You need to specify this value with any analytic data query.  In order to get a list of available sites, you’ll need to query the account feed:

With that snippet, I organize the sites based on their associated account.

After choosing a specific site to work with, you can query information like total page views, average amount of time spent on the site, etc.  The data feed explorer is quite handy in exploring the type of data that Analytics will return.  For example, the following query will get a number of general stats across all pages:

Similarly, you can add dimensions to your query.  Dimensions allow you to group the metrics data, similar to sql group by.  The following query will get a list of pages sorted by most page views:

The UI side of things

The graph is generated using the jquery sparkline plugin. While not as sexy as the official analytics graphs, it works for a quick view. Everything else on the page is styled with twitter bootstrap, with a few minor tweaks.

Conclusion

That’s about it.  Have a look at the complete project to get a full understanding of how I used the analytics api to build an asp.net mvc widget that summarizes website analytics.

Hello Rails

This year, I began to explore worlds outside of .net, as more than a lurker, and I want to continue to share my steps along the way. This is one of those steps…

Background

The DMB Stream community has grown more than I had ever envisioned when I first created the site. To help celebrate that and give back to the community, I wanted to run a Facebook contest. I read long ago that Heroku and Facebook have a partnership where you can host your Facebook app on Heroku for free. This means no server configuration and it just works 🙂  I have been meaning to make a site with rails, but always fell back into my comfort zone of .net.  Not this time…

Getting Started

I fired up a virtual image of mac osx (I will get a dedicated box as I become more comfortable with non windows environments) and started down the path of installing my development environment.  I used the Rails Ultimate Install Guide and other answers from this StackOverflow post to get the majority of my development tools setup.  Outside of that, I had my trusty Agile Web Development With Rails book next to me to hold my hand throughout this journey.

I should make a side note: I chose to use Heroku’s MongoHQ for persisting data.  They offer free data storage with Mongo, up to 16MB.  I don’t feel I need a relational database and MongoHQ seemed like the easiest route to take for saving contest submissions.

Riding Rails

Since this is my first rails app, it took a bit longer than I expected to get up and running.  That and I made a point to get comfortable with vim which took time as well.  I supplemented the rails book with the getting started guide on the rails wiki.  It compliments my rails book with basic things like hooking up the root route.

After a day or so of using vim, I decided to check out Textmate to see how that compares.  Coming from Visual Studio, I can definitely say that I am more at home using Textmate over vim.  I’m happy I learned vim and have basic usage down.  I know I could continue to improve my efficiency with vim, but I really like the project like view that Textmate offers.  Being able to quickly select any file in the rails tree is a major deciding factor for me.

As far as rails itself goes, I have really enjoyed working with that framework.  Rails feels between one and two major releases ahead of asp.net mvc.  All of the built in helpers, asset pipeline, etc are all time savers and magically work with no configuration/custom code.  The only thing that feels less mature than asp.net mvc is validation.  Rails has model validation, but I have yet to find something along the lines of the unobtrusive jquery validation that asp.net mvc provides.  That doesn’t mean it isn’t out there…

That’s one of the downfalls that I have found regarding Rails.  Finding up to date information for the current version of rails isn’t the easiest thing in the world.  There’s a lot of blog posts and examples out there for rails and a good chunk of those are for older rails versions.  Sometimes the examples work, sometimes the latest version of rails looks nothing like what’s in the example.

Heroku, GitHub, and Mongo

What can I say about Heroku? It’s amazing and such a pleasure to use; I don’t see myself using another rails host at this point.  They continue to innovate and offer solutions with the same vigor that Amazon does with their web services.  Heroku pricing is extremely attractive as well.  Host any number of small sites for free and they’ll scale on demand, when that time comes.  Deploying to heroku is so simple and easy… MS could learn a lot from them (that is, if there are any passionate people left on that stack).  Yes, I understand that there is AppHarbor, but deployment options for .net are outdated, limited, and overall complete shit.

Not much to say about GitHub either… it’s what everyone uses these days for source control.  I used both the command line git client and GitHub’s mac client with my project.  Both have benefits and the gui client is so simple and elegant… I still really enjoy Kiln for my .net projects, but I’ll be in git land for everything else.

I chose to go with MongoHQ for data persistence.   MongoHQ and Heroku have a partnership that provides the free 16MB plan to each heroku app.  If your app requires more storage than that, MongoHQ price levels won’t break your bank.  There are no license fees or worries about infrastructure.  MongoHQ has multiple libraries available for non rails environments as well (including .net and java).  They even have a similar partnership with AppHarbor.  Rails by default is setup to use ActiveRecord and a relational database.  Have no fear, it’s easy to override those defaults and MongoMapper wraps mongo in a way that makes working with it feel very similar to a traditional database.

Conclusion

While I was building this application, I found myself thinking that I should be doing busy work type things, but there really isn’t a lot of that to do with the rails stack.  For small/medium sized sites, it’s geared to help you realize your ideas rather than getting lost in architecture and useless technical rants.  To get started, that’s all I need… If the site ever gets too big or cost prohibitive for rails, it should monetize itself enough at that point to facilitate alternatives.

At this point, I’m planning out my next project and will be using the same frameworks to make it a reality.  It’s more complicated than a simple facebook app, so it should be a nice next step for my rails experience.

I feel that innovation and excitement have long moved away from the Microsoft stack and the trend seems to continue among developers.  There are many other things going on out there and in general, it feels like .net is treading water and playing catch up.

As slanted as this post may seem, I haven’t given up on .net.  I still have a fondness for it, but I would be stupid to ignore the rest of the web.

ProfileAttribute for MvcMiniProfiler

I’ve been using the MvcMiniProfiler quite a bit lately.  I put it in production with Acturent and I’ve contributed a bit to the project.  With Acturent, I came up with a simple ActionFilterAttribute that I’m using to auto inject the profiler to all actions in the application.  Rather than going through and specifically adding @MvcMiniProfiler.MiniProfiler.RenderIncludes() to each view, I just slap the following attribute on my base controller class:

public class ProfileAttribute : ActionFilterAttribute{
  public override void OnResultExecuted(ResultExecutedContext filterContext) {
    base.OnResultExecuted(filterContext);
    if (filterContext.RequestContext.HttpContext.Request.IsAjaxRequest()) return;
    var session = ObjectFactory.Container.GetInstance<IUserSession>();
    if (session != null) {
      var user = session.GetCurrentUser();
      if (user == null || !user.IsAdmin) return;

      var includes = MiniProfiler.RenderIncludes().ToString();
      using (var writer = new StreamWriter(filterContext.HttpContext.Response.OutputStream)) {
        writer.Write(includes);
      }
    }
  }
}

Obviously it will need a bit of tweaking if you implement it in your app.  Specifically, the user validation code should be swapped out with whatever logic you want to use to determine who sees the profile information.

Using pjax with ASP.Net MVC3

I was recently introduced to the pjax project and wondered how hard it would be to use it with asp.net.  It turns out that it takes next to no effort to have a basic asp.net mvc3 razor application support pjax.

Overview

pjax uses ajax to reload a portion of your page.  This is nothing new, but the “p” part of pjax stands for pushState.  PushState is a new feature of Html5 that allows you to modify browser history, without messing around with hash values.  So pushState gives you the speed boost of using ajax to update just part of your page, while offering a traditional experience for browsers like IE.  According to caniuse.com, Firefox 4+, Safari 5+, Chrome 8+, iOS 4+, and Android 2.2+ all support pushState.

Demo

The github home for the jQuery plugin for pjax has an overview of available options and usage.  The project also has a demo hosted on heroku that will give you an idea of how pjax works and some ideas for how you can use it in your application(s).

My version using Asp.Net MVC3

While my version may not be as sexy as the Ruby example, it’s simple and allows you to still use content sections for things like javascript.  I just check for the X-PJAX header in the _ViewStart.cshtml, where my layout is specified for the views.  If the X-PJAX header is specified, then the views should use a “chrome-less” layout.  Otherwise, they should use the normal layout.

The _ViewStart.cshtml file looks like:

@{
  if (Request.Headers["X-PJAX"] != null) {
    Layout = "~/Views/Shared/_PjaxLayout.cshtml";
  } else {
    Layout = "~/Views/Shared/_Layout.cshtml";
  }
}

My _PjaxLayout.cshtml layout file is very basic and just contains a tag for the page title and the content body section:

<title>@ViewBag.Title</title>
@RenderBody()

Additional thoughts

If you have javascript that needs to run on the page, you could easily add @RenderSection(“Script”, false) after @RenderBody().  Just keep in mind that the pjax plugin only updates one container on the page.  So if you have multiple html content sections that need updating, you would need to wrap them in a container that could be updated in one call.

Download

If you’re interested, feel free to take a look at the asp.net mvc3 pjax demo project I created.

HtmlHelper DropDownList for Enumerations

I’ve really been enjoying the html helpers baked into the ASP.Net MVC framework. To compliment the SelectList extensions that I use, I often use this extension as well.  It displays a drop down of enum values for the specified property.  It will attempt to get the name via the DisplayAttribute.  If the attribute is not present, then it will just get the name from the enum value.

I created an extension method to get the Name of an enum value (as described above):

private static readonly Dictionary<Enum, string> NameCache = new Dictionary<Enum, string>();
public static string GetName(this Enum type)
{
  if (NameCache.ContainsKey(type))
    return NameCache[type];

  var enumType = type.GetType();
  var info = enumType.GetField(type.ToString());
  if (info == null)
    return string.Empty;

  var displayAttribute = info.GetCustomAttributes(false).OfType<DisplayAttribute>().FirstOrDefault();
  var value = string.Empty;
  if (displayAttribute != null)
    value = displayAttribute.GetName() ?? string.Empty;

  NameCache.Add(type, value);

  return value;
}

I then make use of that extension with the enum dropdown helper:

public static MvcHtmlString DropDownListForEnum<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression)
{
  return htmlHelper.DropDownListForEnum(expression, null, null);
}
public static MvcHtmlString DropDownListForEnum<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, object htmlAttributes)
{
  return htmlHelper.DropDownListForEnum(expression, new RouteValueDictionary(htmlAttributes));
}
public static MvcHtmlString DropDownListForEnum<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, IDictionary<string, object> htmlAttributes)
{
  return htmlHelper.DropDownListForEnum(expression, null, htmlAttributes);
}
public static MvcHtmlString DropDownListForEnum<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, string optionLabel)
{
  return htmlHelper.DropDownListForEnum(expression, optionLabel, null);
}
public static MvcHtmlString DropDownListForEnum<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, string optionLabel, object htmlAttributes)
{
  return htmlHelper.DropDownListForEnum(expression, optionLabel, null);
}
public static MvcHtmlString DropDownListForEnum<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, string optionLabel, IDictionary<string, object> htmlAttributes)
{
  if (expression == null)
    throw new ArgumentNullException("expression");

  var member = expression.Body as MemberExpression;
  if (member == null)
    throw new ArgumentNullException("expression");

  var selectedValue = string.Empty;
  var metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
  if (metadata.Model != null)
  {
    selectedValue = metadata.Model.ToString();
  }
  var enumType = Nullable.GetUnderlyingType(member.Type) ?? member.Type;

  var listItems = new List<SelectListItem>();
  foreach (var name in Enum.GetNames(enumType))
  {
    var type = Enum.Parse(enumType, name) as Enum;
    listItems.Add(new SelectListItem
    {
      Text = type.GetName(),
      Value = name,
      Selected = name == selectedValue
    });
  }

  return htmlHelper.DropDownListFor(expression, listItems, optionLabel, htmlAttributes);
}

The beauty of this extension method is that it uses the DropDownListFor(…) helper baked into the framework already. So validation, etc is wired up for me. Also worth noting, this extension works with nullable and non-nullable properties. Hope this helps someone save some time…

Asp.Net MVC: SelectList extension methods

I wanted to share some extensions I use for dealing with the Asp.Net MVC select lists (DropDownList/ListBox) helpers.  Why the mvc helper apis are not more friendly in this area, I do not know…

Now some examples of how to use these extensions:

A single dropdown:

@Html.DropDownListFor(x => x.PropertyId, Model.AllProperties.ToSelectListItems(x => x.Name, x => x.Id.ToString(), x => x.Id == Model.PropertyId))

A multiselect dropdown:

@Html.ListBoxFor(x => x.PropertyIds, Model.AllProperties.ToMultiSelectListItems(x => x.Name, x => x.Id.ToString(), x => Model.PropertyIds.Contains(x.Id)))

 

Announcing FluentScheduler

Overview

Over the Thanksgiving Holiday, I created an open source project called FluentSchedulerFluentScheduler is a .NET 4 based task scheduler.  It allows you to run tasks/cron jobs from your application.  A fluent api is used to configure schedules for when to run each task.

Why?

In .NET land, I had previously used an xml based task scheduler that only allowed interval based task runtimes.  I wanted more of a .NET 4 way of doing things… With FluentScheduler, not only can you can use a class to represent a task, you can also define your task using a lambda expression.  I really wanted things to be flexible and not try to limit people with how they define their tasks.  Additionally, you can schedule your tasks to run at specific times as well as intervals.

There were many firsts for me with this project:

  • I enjoy using fluent apis, but I have never written one myself.  I figured this project would give me a nice opportunity to dive into creating a fluent interface for a product.  Getting fluent apis right is not easy… I hope you find the api I created to be logical and easy to use.
  • While I have worked on open source projects in the past, it has been a while.  I wanted to explore a different host than Sourceforge, so I chose CodePlex.  There are a lot of other .NET based projects hosted on CodePlex and the site gives project owners options for which source control system you would like to use.  These days, I prefer using Mercurial, which CodePlex offers as an available source control system.  So far, my experience with CodePlex has been excellent.  The tool is easy to use and quick to setup.
  • This is my first official NuGet library.  I have private NuGet packages, but FluentScheduler is part of the official Microsoft feed and available to everyone.

Examples

Detailed usage instructions are available here.  But to give you a taste of how easy this library is to use 🙂

// Schedule a complex task to run immediately and on a monthly interval
Schedule(() =>
	{
		Console.WriteLine("Complex Action Task Starts: " + DateTime.Now);
		Thread.Sleep(1000);
		Console.WriteLine("Complex Action Task Ends: " + DateTime.Now);
	}).ToRunNow().AndEvery(1).Months().OnTheFirst(DayOfWeek.Monday).At(3, 0);

How can I use it?

You can begin using FluentScheduler today by either adding it as a NuGet library package reference or by grabbing the assembly from the project release page.  Once you reference the assembly, please take a look at the documentation for how to configure things.

More Information…

If you’re interested in learning more about the project, check out the project’s homepage.  If you’re interested in contributing, please fork the project and start submitting pull requests 🙂

Creating NuGet packages with TeamCity

I wanted to create NuGet packages for some internal libraries that I use.  I came across this post that describes how to create a NuGet package with MSBuild, which got me the majority of the way.  I did have to make a few modifications to make it fit in nicely with my TeamCity CI server.

To begin, I installed the MSBuild Community Tasks to my build server.

After that, I grabbed the NuGet.MSBuild assembly from their CI server and copied it to the C:Program Files (x86)MSBuildNuGet folder.

Following Mark’s instructions, I created a NuGet folder for my project.  In that folder, I’m able to put my nuspec file and any transforms.  With current versions of NuGet, you need to make sure that you have proper namespaces added to the package and metadata elements:

<package xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
	<metadata xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">

I then added the following MSBuild file to my project:

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
	<Import Project="$(MSBuildExtensionsPath)MSBuildCommunityTasksMSBuild.Community.Tasks.Targets"/>
	<UsingTask AssemblyFile="$(MSBuildExtensionsPath)NuGetNuGet.MSBuild.dll" TaskName="NuGet.MSBuild.NuGet" />

	<PropertyGroup>
		<AssemblyName>BiaCreations</AssemblyName>
		<PackagePath>C:Packages</PackagePath>
		<BuildConfiguration Condition="'$(teamcity_version)' == ''">Debug</BuildConfiguration>
		<BuildConfiguration Condition="'$(teamcity_version)' != ''">Release</BuildConfiguration>
		<build_number Condition="'$(teamcity_version)' == ''">1.0.0.0</build_number>
	</PropertyGroup>

	<Target Name="CreatePackage">
		<PropertyGroup>
			<PackageBuildPath Condition="'$(teamcity_version)' == ''">buildNuGet</PackageBuildPath>
			<PackageBuildPath Condition="'$(teamcity_version)' != ''">$(teamcity_build_tempDir)buildNuGet</PackageBuildPath>
			<PackageSourcePath>NuGet</PackageSourcePath>
		</PropertyGroup>

		<ItemGroup>
			<PackageSourceFiles Include="$(PackageSourcePath)**" />
			<PackageLibFiles Include="bin$(BuildConfiguration)$(AssemblyName).dll;bin$(BuildConfiguration)$(AssemblyName).pdb" />
			<OldDestinationFiles Include="$(PackagePath)$(AssemblyName).1.*.nupkg" Exclude="$(PackagePath)$(AssemblyName).$(build_number).nupkg" />
		</ItemGroup>

		<RemoveDir Directories="$(PackageBuildPath)" ContinueOnError="true" />
		<Message Text="Setting up the $(PackageBuildPath) directory will all the necessary files to create our package"/>
		<Copy SourceFiles="@(PackageSourceFiles)"  DestinationFiles="@(PackageSourceFiles->'$(PackageBuildPath)%(RecursiveDir)%(Filename)%(Extension)')" />
		<Copy SourceFiles="@(PackageLibFiles)"  DestinationFiles="@(PackageLibFiles->'$(PackageBuildPath)lib%(RecursiveDir)%(Filename)%(Extension)')" />

		<FileUpdate Files="$(PackageBuildPath)package.nuspec" Regex="version&gt;([^&quot;&lt;]*)&lt;/version" ReplacementText="version&gt;$(build_number)&lt;/version" />

		<Message Text="Creating the package"/>

		<NuGet PackageDir="$(PackagePath)" SpecFile="$(PackageBuildPath)package.nuspec" />
		<Message Text="Deleting previous package"/>
		<Delete Files="@(OldDestinationFiles->'$(PackagePath)%(Filename)%(Extension)')" ContinueOnError="true" />
	</Target>
</Project>

There are some conditions added to some of the properties so that I can run the build file locally (for testing) and so that it works as I want when TeamCity runs it.  Additionally, I am only copying the project assemblies from the bin folder, rather than all files, since I handle any dependencies via the nuspec file.

Next, I upgraded my Team City installation to version 6 so that I could take advantage of the multiple build runner feature.  I use the Visual Studio build runner to build my solution and just created a MSBuild runner that will create the NuGet package:

This pretty much sums up the changes I needed to make to have TeamCity produce a NuGet package every time it builds my library.  I’m fairly happy with this solution and so far it seems to be working well.  I want to thank Mark for his post on building NuGet files via MSBuild.  I hope this post helps those of you who want to incorporate this process with TeamCity.

Have JQuery Autocomplete behave like Google Suggest

For the current project I’m working on, I have a search box at the top of the site.  I wanted to add ajax suggestions (like Google Suggest) to it and thought it was a good exercise for the new JQuery UI 1.8 Autocomplete widget.  The autocomplete widget seems to be more suited for quickly searching pre-populated lists, but it offers nice extension points that allow you to easily customize its behavior.  Rather than having the control fetch a list of suggestions to just complete the word in the search box, I wanted the drop down to display a list of selections that when clicked, would navigate directly to the intended URL.

According to the documentation, you can pass in  three types of sources:

  1. A string representing a url that will return JSON data
  2. An array of strings (or objects)
  3. A callback that lets you define your own data

I’ll show you how to accomplish it using an array, but you can easily use one of the other methods as well.  If you want to use a different data source method, just make sure the result has the same object array signature as below.

1. Format the data source correctly

The autocomplete widget expects the source to be formatted as an array of strings or as an array of objects with specific properties.  Since we want to be able to assign a URL to each suggested item, we need to create an array of label/value pairs that represent each item:

var source = [{ label: 'My First Item', value: '/items/1' }, { label: 'My Second Item', value: '/items/2'}];

Now, when I pass that as the source to the autocomplete, we get items returned as a drop down menu.

2. Display the correct text for items

Unfortunately, when you hover over an item, it will replace the text in the search box with the value of the item:

To fix that behavior, the autocomplete widget allows you to hook into the focus event, that fires when an item in the drop down menu is hovered over/navigated to.  So we want to alter the behavior to use the label instead of value:

focus: function (event, ui) {
  $(event.target).val(ui.item.label);
  return false;
}

Now we get the label showing up in the textbox when we hover over an item:

3. Have the browser navigate to a URL when an item is selected

We’re almost there.  The last step that is needed is to wire up the item so that we navigate to the appropriate url when an item is selected:

select: function (event, ui) {
  $(event.target).val(ui.item.label);
  window.location = ui.item.value;
  return false;
}

A couple notes about what is happening in the select function. We set the value of the search box to the label value. This allows the control to auto complete in case the user gets anxious and wants to click Search before the browser redirects. After that, we instruct the browser to redirect to the selected item’s url.  Finally, we cancel the select event to make sure the default autocomplete behavior does not put the item value in the search box.

Putting it all together

We have the following:

$("#Query").autocomplete({
	source: [{ label: 'My First Item', value: '/items/1' }, { label: 'My Second Item', value: '/items/2'}]
	,focus: function (event, ui) {
		$(event.target).val(ui.item.label);
		return false;
	}
	,select: function (event, ui) {
		$(event.target).val(ui.item.label);
		window.location = ui.item.value;
		return false;
	}
});