Page 4 of 5

Manually setting the navigator.geolocation

Firefox is probably my most favorite browser. Mostly because of all the great extensions.
Every web developer should know Firebug. It really makes my life so much easier. I use it a lot for:

  • Examining and manipulating dom elements
  • Run JavaScript
  • Inspect ajax calls (request and response)
  • Resource manager (see what’s being loaded, cached, etc)

But this post is not about Firebug.
Another great extension is Geolocator.
This tool allows you to change your geolocation. Let me first explain what the geolocation is.
The geolocation is your current position provided by your browser.
It can be requested via JavaScript. This is one of the new features described in the HTML5 standard.

navigator.geolocation

The geolocation object has three methods:

  • getCurrentPosition
  • watchPosition
  • clearWatch

getCurrentPosition gives you the current position, this method accepts two arguments, the first argument is the method called when the position is successfully retrieved. The second argument is the method called when the position could not be retrieved. This could also be because the user has denied location sharing.


function onSuccess(position)
{
    var lat = position.coords.latitude;
    var long = position.coords.longitude;
}

function onError()
{
    // handle failed retrieving of location.
}

navigator.geolocation.getCurrentPosition(onSuccess, onError);

The watchPosition method also returns the current position, but continues to return updated positions.
The clearWatch method stops the watchPosition method.

Not all browsers support html5, so not all browsers support geolocation. You first need to check if geolocation is available.


if (navigator.geolocation) {
    // do location based stuff here
}

I was working on a location based application and wanted to test the applications with different positions, and that’s when I came across the Geolocator extension.
I created several locations and when I reloaded the page, Firefox showed a dropdownlist with my locations so I could easily switch my position.

Locations can be added by going to the Add-ons menu and select the Geolocator options. Search for your location, leave the search screen (tweak settings a bit if you’d like) and click the save button.

Mobile devices, detection and views in .Net MVC

Mobile is hot, and will probably only get hotter. Sites need to be viewable on any kind of devices, so mobile detection is a hot issue.

Headers

But how do we detect mobile devices?

Every http request send to a page or website contains headers. These headers give us information about the sender. A nice tool to intercept a request and check the headers is fiddler. I have been using this tool for some years now, and I gained a lot of knowledge about requests and responses.


GET http://vicreative.nl/ HTTP/1.1
Host: vicreative.nl
Connection: keep-alive
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
User-Agent: Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1547.66 Safari/537.36
Accept-Encoding: gzip,deflate,sdch
Accept-Language: nl-NL,nl;q=0.8,en-US;q=0.6,en;q=0.4

This is an example of a request to my website. This request is sent by Chrome.

The header we are looking for is the User-Agent. This header gives us information about the indentity of the browser who send the request. In above example, you can see that the request is send with a Chrome browser. This header will also tell us when the request is send by a mobile browser. I used a mobile device emulator to fake a mobile request:

GET http://www.vicreative.nl/ HTTP/1.1
User-Agent: Opera/9.80 (Android 2.3.7; Linux; Opera Mobi/46154) Presto/2.11.355 Version/12.10
Host: www.vicreative.nl
Accept: text/html, application/xml;q=0.9, application/xhtml+xml, multipart/mixed, image/png, image/webp, image/jpeg, image/gif, image/x-xbitmap, */*;q=0.1
Accept-Language: en-US,en;q=0.9
Accept-Encoding: gzip, deflate
Connection: Keep-Alive
Device-Stock-UA: Opera Mobile Emulator (no stock UA available)

Another header to keep in mind is the following:


X-Requested-With: XMLHttpRequest

This header information tells us that this is an ajax request. This is also used to determine the IsAjaxRequest property in a MVC controller.

So many devices

Now that we know that every device and browser sends its own User-agent header, you will probably think that it’s impossible to know all devices and browsers and operation systems. Well, you’re right.

I think that’s why the mobile device detection of Microsoft does not work so great. They just can’t update it enough to make it work for all devices.

So do not use HttpCapabilitiesBase.IsMobileDevice. It will only work if you override it and set the correct value.

There is a NuGet package which contains many devices and is updated regularly: 51 degrees.mobi

It also comes with a config, which allows you to set actions for mobile devices, like redirects.

Setting Mobile context

Whether a browser is mobile, can be manually overridden:

HttpContext.SetOverriddenBrowser(this.Request.Browser.IsMobileDevice
                                        ? BrowserOverride.Mobile
                                        : BrowserOverride.Desktop);

The 51 degrees framework will automatically do that, so you don’t really have to do this, but it can come in handy when you want to force it for some reason.

The Browser object has a lot more useful properties for determining which view to display, for instance the property Platform.

Creating Display Modes

As described above, the Browser object has a lot of information about the requested device.
At application start, we can create specific display modes for device types. For instance for Andriod devices:

DisplayModes.Modes.Insert(0, new DefaultDisplayMode("android")
{
    ContextCondition = Context => Context.Request.Browser.Platform == "Android"
});

Keep it clean and create a (static) class in the App_start folder called DisplayModes which contains a method RegisterDisplayModes which registers all display Modes:

public class DisplayModes
{
    public static void RegisterDisplayModes(DisplayModeProvider displayModeProvider)
    {
        displayModeProvider.Modes.Insert(0, new DefaultDisplayMode("android")
        {
            ContextCondition = Context => Context.Request.Browser.Platform == "Android"
        });
        .....
    }
}

Now call this method from the App_Start in the Global.asax file:

protected void Application_Start()
{
    AreaRegistration.RegisterAllAreas();

    DisplayModes.RegisterDisplayModes(DisplayModeProvider.Instance);
    .....
}

Now that we have registered a display mode for android, we can create android specific views.

Know that the first matching DisplayMode will be used. So the order of registration is very important! The mobile display mode is already registered.

Mobile views

Let’s make some mobile views now.

Creating views for devices is really simple, just add the name of the view before the extension of the file and the ViewEngine will automatically pick up the view for the correct device.

mobile-views

This example has a default Index view (index.cshtml) a mobile view for all mobile devices (Index.mobile.cshtml) and a android specific view (Index.android.cshtml).

This works for all views, including layouts, partial views, shared views, strongly typed views etc.

Because we registered the android DisplayMode at position 0 (first), all android devices will be provided with this view.  When the device is not an android device, but is a mobile device, the mobile view will be presented. For all other devices, the normal index view will be displayed.

Testing

It’s kinda difficult to test this from your developer laptop/pc, but there are many tools who simulate mobile devices. I like the mobile emulator from Opera. It has a lot of presets for mobile devices.

But there are many other emulators, even microsoft has its own.

Caching issues MVC 4

Now that you have created and published your mobile friendly application, you deploy it to your server and quickly check it on your mobile to see if it really works. And it works! Hooray!

Soon people start complaining about seeing strange views. It looks like a mixture of mobile and default views.

This is because of a bug in MVC4. The MVC team has released a patch for it, available here on NuGet.

Sitecore Multisite – Generating out of context links

Linking to items in other sites gives a lot of problems and strange urls.
Sitecore creates links by using the context of the current site.
There is an easy solution for creating out of context links, just switch the context!

First we need to find the site context of the item. The Sitecore.Configuration.Factory gives us access to all available sites.

var sites = Sitecore.Configuration.Factory.GetSiteInfoList();

Now we need to find the corresponding site.

SiteContext siteContext  = null;
foreach (var site in sites)
{
    var fullPath = string.Concat(site.RootPath + site.StartItem);
    if (item.Paths.FullPath.StartsWith(fullPath))
    {
        siteContext = new SiteContext(site);
        break;
    }
}

Now that we’ve got the site context, we can generate the correct url.

var urlOptions = LinkManager.GetDefaultUrlOptions();
urlOptions.Site = siteContext;
var url = LinkManager.GetItemUrl(item, urlOptions);

Automatic Bundling and Minification in .Net

One of the cool new features of .Net 4.5 is the bundling and minification feature. This can save so many requests to your server and saves you many kbs without creating a debug hell. The amount of data is getting more and more important, because of the mobile devices. People pay lots of money on data bundles for their mobile device, we better not waste it. It also decreases loading time!! Reasons enough to start using bundling and minification!

First thing you need to do is download and install the Microsoft ASP.NET Web  Optimization Framework nuget package.

The bundles are registered at application startup. This event is handled in the Application_Start method in the Global.asax. I always try to keep my Global.asax as clean as possible and split all registrations to seperate files in the App_Start folder. So I created a static BundleConfig class in the App_Start folder. This class contains one method, Register with the current Bundles as argument.

BundleConfig.RegisterBundles(BundleTable.Bundles);

BundleConfig

The BundleConfig class registers all JavaScript and Stylesheet bundles, Both Bundles can be added to the same BundleCollection, but both bundles have their own classes. JavaScript bundles are created by using the ScriptBundle class and Stylesheet Bundles are created by using the StyleBundle class.

bundles.Add(new ScriptBundle("~/bundles/jquery").Include("~/Scripts/jquery-{version}.js"));

This creates a JavaScript bundle named “~/bundles/jquery”  and includes one file, “~/Scripts/jquery-{version}.js”.  {version} is automatically resolved to the version of the jquery file in the scripts folder.

bundles.Add(new StyleBundle("~/Content/css").Include("~/Content/site.css"));

This creates a Stylesheet bundle names “~/content/css”” and contains one file “~/Content/site.css”. Adding more files is easy, just add more files to the include and separate them by a comma.

Adding bundles to a view

The only thing left to do, is adding the bundles to a view.

MVC (Razor)

@Scripts.Render("~/bundles/jquery")

WebForms

<%: Scripts.Render("~/bundles/jquery") %>

The above code renders the JavaScript bundle.

MVC (Razor)

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

WebForms

<%: Styles.Render("~/Content/css") %>

The above code renders the Stylesheet bundle.

All the requests to the bundles have a querystring parameter (v=CkVTG71m7lHB5jSCpyOSxbeCVJLIPag7u7NL4ykFenk1). This is to make sure that no old versions of this file are cached and retrieved.

Config files

Bundles can also be configured in config files. This allows you to make changes to your bundle without having to rebuild the project. It also allows frontend developers to easily include, remove or change files in a bundle without having to use visual studio.

An example of a bundle.config file

<?xml version="1.0" encoding="utf-8" ?>
<bundles version="1.0">
  <styleBundle path="~/Content/css">
    <include path="~/Content/Site.css" />
  </styleBundle>
</bundles>

Debugging

One of the biggest problems of minified files is debugging. It’s almost impossible to debug those files.

That’s when the best feature of this minification framework comes in place. When compilation is set to debug (in web.config), the files will not be minified, which makes it a lot easier to debug.

<system.web>
    <compilation debug="true" />
    <!-- Lines removed for clarity. -->
</system.web>

Creating custom bundle transforms

Custom transforms can be created by implementing the IBundleTransform interface.,

using System.Web.Optimization;

public class MyByndleTransform : IBundleTransform
{
   public void Process(BundleContext context, BundleResponse response)
   {
       // Process bundle tranform here
   }
}

The custom transform can now be added to the transform of a bundle

var myBundle = new Bundle("~/My/Files/To/Include");
lessBundle.Transforms.Add(new MyBundleTransform());

This bundle can now be added to the bundles collection in the BundleConfig file.

Why creating custom bundle transforms? Just think of less or coffeescript, or whatever bundle you want.

Simple CKEditor MVC EditorTemplate

I like using wysiwyg editors in my projects. It gives the user a lot of freedom in creating content.

There are a lot of wysiwyg editors, like TinyMCE, CKEditor, etc. I prefer CKEditor (formerly known as FCKEditor), because it is flexible, extendible, has a lot of plugins and creates clean (and customizable) html.

Most of my projects are MVC projects and I created a simple solution for using the CKEditor for content properties of my model.

First I mark the Properties in my model as html Properties by using the UIHint attribute.

public class Page
{
    public string Title { get; set; }

    public string SubTitle { get; set; }

    [UIHint("html")]
    public string Content { get; set; }
}

The UIHint attribute is part of the System.ComponentModel.DataAnotations namespace and can be combined with any other (MVC) attribute.

Now we need to create a view for this model:

@model MvcApplication1.Models.Page

<h2>Create new Page</h2>

<div>
    @Html.EditorForModel()
</div>

This will render an input for every property in the model. In this case, three inputs of type texy are rendered, because the type of the three properties in the Page model are strings and the application does not know how to handle the “html” value in the UIHint attribute of the Content Property.

By calling Html.EditorForModel all properties in the provided model are rendered. The attributes influence the rendering of the properties. The UIHint attribute lets you change which template is used for rendering this property. MVC searches for templates in the EditorTemplates folder. It searches in the controller folder for an EditorTemplates folder. When this folder is not found, it searches in the Shared folder for an EditorTemplates folder. When no folder is found, it will use the default template for the type of this property. When an EditorTempaltes folder is found, it will look for an html.csharp file. This is because of the value in the UIHint attribute. I want to use the html editor for every controller, so I place the html.csharp file in the Shared/EditorTemplates folder. It is also possible to override any default template, so you can make your own template for strings by creating a string.cshtml file and place it in the EditorTemplates.

When calling Html.DisplayForModel (or Html.DisplayFor), it searches in the DisplayTemplates folder. This has the same fallback scenario as described above for EditorTemplates.

My html.csharp file contains the following code:


@model String

@Html.TextArea("", Model, new { @class = "htmleditor" })

<script type="text/javascript">
    $(document).ready(function () {
        var id = "@ViewData.TemplateInfo.HtmlFieldPrefix";
        var instance = CKEDITOR.instances[id];
        if (instance) {
            delete CKEDITOR.instances[id];
        }
        $("#" + id).ckeditor();
    });
</script>

This creates a new instance of the CKEditor and deletes the old instance if exists.

Sitecore’s sublayout datasource, brilliant! Or maybe not?

One of the strengths of Sitecore is the DMS (Digital Marketing System). DMS collects user information and allows you to personalize the website based on the user’s profile.

One of the possible personalizations is changing the content of a sublayout by changing its datasource.

This sounds great, but sitecore made one big design flaw!

The items in the datasource are not stored by ID, but by the selected items path! This means that changing one of the item names in the tree of the selected item (or the selected item name itself) will break the datasource. Moving the item will also break the datasoure. Beware of that!!!

Sitecore announced to fix this in a future version.

I’m also not very happy about the way you have to retrieve the datasource item:

Item item;
string datasource = ((Sitecore.Web.UI.WebControls.Sublayout)this.Parent).DataSource;
if (!string.IsNullOrEmpty(datasource) {
    item = Sitecore.Context.Database.SelectSingleItem(datasource);
}

Reading Excel files in .Net using C#

Customers and project managers seem to have one thing in common, they both like working with Excel. Though Excel isn’t really my favorite application, there is one thing very nice about it. It is very easy to read an Excel file in .Net.

In this post, I will try to describe how you can read and parse an Excel file.

This post is based on a computer which has Office 2010 installed. If you try to read excel files on a computer or server without office installed, you first need to install this.

Interfaces

Nobody seems to care about interfaces anymore, that’s why I’m telling you that I do think it is important. It makes your application loosely coupled and unit testable! It also makes you think about generic solutions for problems.

Program to an interface, not an implementation!!

The interface I created for my reader file:


public interface IFileReader<T>
{
     T Read(string filename);
}

I created the following class which implements the IFileReader interface


public class ExcelReader : IFileReader<DataTable>
{
     public DataTable Read(string filename)
     {
      ....
     }
}

The connection string

The Excel file can be read as a database, using an OleDb  (Object Linking and Embedding, Database) connection. This is a connection designed by Microsoft for accessing a variety of sources.

I use two different connection strings for reading Excel files, one for the good old xls files and one for the xlsx files.

I check on file extension for detecting the right connection string (I know this is dirty!!!)


 string connectionString;
 var filename = filePath.Trim().ToLower();
 if (filename.EndsWith(".xlsx"))
 {
    connectionString = string.Format("Provider=Microsoft.ACE.OLEDB.12.0;Data Source={0};Extended Properties=\"Excel 12.0 Xml;HDR=YES;IMEX=1\";", filePath);
 }
 else if (filename.EndsWith(".xls"))
 {
    connectionString = string.Format("Provider=Microsoft.Jet.OLEDB.4.0;Data Source={0};Extended Properties=\"Excel 8.0;HDR=Yes;IMEX=1\";", filePath);
 }

Please put these connection strings in the connectionstrings section of your app.config or web.config!!

Reading sheets

Now that we have a connection string, we can create a connection.


OleDbConnection connection = new OleDbConnection(connectionString);
connection.Open();

Make sure you use try/catches for the connection.
Now that the connection is open, the next step is reading the tables. The tables in Excel are the available sheets.


DataTable tableSheets = connection.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null);

Every row in the tableSheets is a sheet


string dataTableName = tableSheets.Rows[0]["TABLE_NAME"].ToString(); 

The above code will give you the name of the first sheet. The sheet name can be used to retrieve the data of this sheet. You can also use a foreach or for loop to retrieve all sheet names if you need to collect data of all sheets.

Reading data


OleDbCommand command = new OleDbCommand(string.Format("SELECT * FROM [{0}]", dataTableName), connection);
command.CommandType = CommandType.Text;

This Command reads the data of the first sheet.
I like to use a DataTable to store the retrieved data. A DataTable is a representation of one table and contains both Columns and Rows.
The first row in a excel sheet are read as columns. The data in the Rows can be retrieved by using the name of the column as index key (like a dictionary).

So we need to fill the DataTable with the result of the Command:


var dataTable = new DataTable();
OleDbDataAdapter dataAdapter = new OleDbDataAdapter(command);
dataAdapter.Fill(dataTable);

The OleDbDataAdapter executes the command and fills the DataTable with the resultset.

The datatable is filled and ready to use. Make sure you handle exceptions properly!

Clean up!

The only thing left to do is clean up! Close the connection and dispose all disposable objects! Why? Because you don’t want memory leaks or other strange behavior in your application! Always dispose disposable objects!  

if (connection.State == ConnectionState.Open)
connection.Close();
connection.Dispose();
command.Dispose();
dataAdapter.Dispose();

I recommend using usings instead of calling dispose!

Setting readonly variables

A lot of people don’t seem to realize that setting readonly variables is indeed possible, it can only be done from inside the constructor:

public class SomeClass
{
   private readonly ISomeService _someService;
   private readonly ISomeOtherService _someOtherService;

   public SomeClass(ISomeService someService, ISomeOtherService someOtherService)
   {
      _someService = someService;
      _someOtherService = someOtherService;
   }
}

This is perfectly fine working code and I strongly recommend it. I use this a lot with dependency injection (DI). This makes sure that the injected instances cannot be overridden, because they can only be set in the constructor.
That’s why I really don’t like the requirement of a parameterless constructor in UserControls in WebForms. There is no possibility for injection, only resolving is possible.

Opening VS 2012 Web projects in VS 2010

Have you ever met a front end developer who doesn’t mind working in Visual Studio? Well, I’m one of the lucky ones who have!
He doesn’t even own an iPhone and still his work is pretty awesome! (no, he did not pay me to write this!)

We work together on several projects. He works uses a basic version of visual studio 2010, while I work with visual studio 2012.
I created some .net 4 web projects for him to work in, and asked him to get the latest version from TFS.

He asked me if he should install WebMatrix and I answered with a simple no. This caused the projects to not being able to load.
I started checking the project references, nothing shocking. The project properties were also pretty basic, using custom webserver.

I discovered that the problem was IIS Express. This is not installed in VS 2010. Probably didn’t exists at the time of release.

So I checked the web server settings to see if IIS Express is enabled, but the project settings were set to custom webserver and the already disabled IIS Express checkbox was not checked.

I finally checked the project file, by using edit project file. This will unload the project and allows you to edit the project file, which is basically just an xml file. You should definetly check this out if you have never done that before.

And that’s where I saw the problem:

<UseIISExpress>true</UseIISExpress>

Setting this to false and reloading and committing the project file solved the problem!

Sitecore user serialization

A colleague gave me an excel file with usernames, password and profile information and asked me if I could import them in Sitecore.
After writing an import tool (read about reading excel files here), I thought to be clever and used Sitecore serialization to import all users to the test environment.
Serialization works quite well. It creates a user file for every user (in the data\serialization\security folder) and even the roles can be serialized.
I copied these files to the test environment and started the deserialization process. All sitecore users were visible in sitecore, but none of the users where able to login.
That’s when I found out that passwords are not serialized!
So remember! Serialization of users looks nice, but you do need to create new passwords!