Wednesday, 3 August 2011

Adding MVC 3 to an asp.net web site

OK, I've been off the blog for a while with things being very busy at work (some interesting changes coming up on public.presalesadvisor.com), but I'm back (for now at least).

I've been starting to tool up on MVC, and while I won't cover that right now as there's no shortage of coverage on that, I wanted to cover one bit that seems slightly lacking in coverage, which is specifically adding MVC 3 to ASP.Net Websites (not web projects).

The most excellent Mr Hanselman has already done the vast majority of the work for anyone wanting to add mvc to asp.net (and in fact pretty much all of it if you're using a web application) with his AddMvc3ToWebForms Nuget Package

There are however a couple more steps needed to get it working with a web site rather than web project

1) Install the nuget package as normal, either by selecting AddMvc3ToWebForms from the online gallery in Visual Studio's "Add Library Package Reference" option (Tools > Library Package Manager > Add Library Package Reference), or by typing the command Install-Package AddMvc3ToWebForms in the Package Manager Console (Tools > Library Package Manager > Package Manager Console)

When I ran this I got an error at the end but as far as I can tell, this isn't actually a problem, but caused by it not having a csproj file to work with:

 PM> Install-Package AddMvc3ToWebForms
'WebActivator (≥ 1.3)' not installed. Attempting to retrieve dependency from source...
Done.
Successfully installed 'WebActivator 1.3.2'.
Successfully installed 'AddMvc3ToWebForms 0.9.1'.
Successfully added 'WebActivator 1.3.2' to extranet.
Successfully added 'AddMvc3ToWebForms 0.9.1' to extranet.
Install-Package : Method invocation failed because [System.__ComObject] doesn't contain a method named 'Add'.
At line:1 char:16
+ Install-Package <<<<  AddMvc3ToWebForms
    + CategoryInfo          : NotSpecified: (:) [Install-Package], RuntimeException
    + FullyQualifiedErrorId : NuGetCmdletUnhandledException,NuGet.PowerShell.Commands.InstallPackageCommand


If you try and compile now it will fail, complaing of not being able to find MvcApplication1. This is because the view (cshtml) files it creates reference a standard namespace (MvcApplication1) that doesn't correspond to the ASP namespace in the created model/controller files. There is also the additional issue that in a web site the 'M&C' files should live under App_Code not in the rool directory.

2a) If you aren't interested in the initial files created by the package then you could simply create Models and Controllers directories under App_Code, delete the ones in the site root, and empty out the Views directory, then get on with your own coding

2b) If you do want to keep the Account/Home/Shared files that have been created then move the Models and Controllers files to App_Code

3) To resolve the namespace issue open up ChangePassword.cshtml, LogOn.cshtml, Register.cshtml in Views\Account and remove the 'MvcApplication1.' from the @model reference at the top

You should now be ready to roll - Enjoy

Friday, 11 March 2011

Breaking down 'google' sitemaps

Just a quick follow up on my previous post on 'google' xml sitemaps :

Once you start databinding your sitemaps, especially if you have as much data as we do on presalesadvisor is to break the sitemap down, using a master index map. These look a lot like the normal sitemaps, but uses a sitemapindex top level element in place of the urlset, and sitemap in place of url. Each location (sitemapindex - sitemap - loc) should then point to individual sitemap files which google, etc will then drill down in to.

A good example of where this would be useful is on presalesadvisor, where there is a huge quantity of data being generated in multiple regional sets. When generated all in one big sitemap file the load time is huge, and risking timeout. Instead we set up our objectdatasources with a querystring parameter of the region code (e.g. en-GB, en-US) and then link to these subsets from the main sitemapindex. With this simple change load times and server load are greatly reduced (which is more important these days from the SEO angle with google taking load times in to account in their ranking algorithms), and we have an all round win.

The sitemaps themselves remain exactly the same as before, and the new sitemapindex looks like this:

<?xml version="1.0" encoding="UTF-8" ?>
<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
 <sitemap>
   <loc>http://public.presalesadvisor.com/Sitemap/XmlSiteMap.aspx?regionID=en-US</loc>
  </sitemap>
 <sitemap>
   <loc>http://public.presalesadvisor.com/Sitemap/XmlSiteMap.aspx?regionID=en-GB</loc>
  </sitemap>
</sitemapindex>

In terms of function all you do differently when logged into your google site admin is add the new SiteMapIndex url as your sitemap rather than any of the actual individual sitemaps

Thursday, 20 January 2011

Step by step guide to installing the Surface SDK on 64 bit windows

With the recent announcements and demos for the new Microsoft Surface I've noticed a few people talking about the version 1 sdk, and the fact they can't install it on their x64 Windows 7 boxes, so I thought I'd give a quick bulletpoint guide to how to acheive this.
To get up and running you will need the following:

XNA 2 Redist
http://www.microsoft.com/downloads/en/details.aspx?FamilyID=15fb9169-4a25-4dca-bf40-9c497568f102&displaylang=en

Windows SDK
http://msdn.microsoft.com/en-us/windows/bb980924

Surface SDK 1.0 SP1
http://www.microsoft.com/downloads/en/details.aspx?FamilyID=3db8987b-47c8-46ca-aafb-9c3b36f43bcc&displaylang=en

1) Once you have the above, install the XNA 2 Framework and the Windows SDK

2) Go into the windows sdk bin directory (probably C:\Program Files\Microsoft SDKs\Windows\v7.0A\Bin or similar) and run Orca.msi

3) Run Orca and open the file SurfaceSDKWE.msi
- Locate LaunchConditions in the tables list on the left
- Delete the rows 'Installed OR NOT VersionNT64'and 'Installed OR VISTASKU<>"Starter"'

Also, if you are using Visual Studio 2010 and do not have any installation of Visual Studio 2008 then you will want to also delete the following:
-'Installed OR        (VS2008SPLEVEL AND VS2008SPLEVEL >= "#0") OR        (VCSEXP2008SPLEVEL AND VCSEXP2008SPLEVEL >= "#0")'
-'Installed OR (VS2008SPLEVEL AND VS2008CSPROJSUPPORT) OR VCSEXP2008SPLEVEL'
Save the file and close orca

4) In a command prompt extract the msi file either using 'msiexec /a SurfaceSDKWE.msi /qb TARGETDIR=C:\Temp\SurfaceSDKWEExtract'

5) Open the msi in the extract directory using orca and remove the launch conditions again

5.5 - optional) If for whatever reason you are not using the visual studio command prompy set your machine's PATH environment variable to include the windows sdk bin directory, or alternatively prefix the corflags commands below with the full path

6) Run an administrator level command prompt and navigate to the directory you extracted the msi to, then in to \Microsoft Surface\v1.0\ and run
 'corflags setupcustomaction.exe /32bit+ /force'

7) Run the installer you have just modified

8) Using the command prompt navigate through the install directory and its children and run the corflags command against each of the executables

You should now be able to run the demos etc, but if you want to build and run the code samples yourself you will need to ensure that the project settings are targetting x86 CPUs explicitly

9) HAVE FUN

Tuesday, 18 January 2011

It takes all sorts

Just to show that there are all sorts in the industry I just thought I'd share one link I came across the other day (and no, I was not searching for it) - http://www.ibm-m4.com/

It really does take all sorts

Sunday, 5 December 2010

Twitter

Just to let you know, for updates on the blog, and useful links to development tips and tricks as I find them I am on twitter as delradie - http://twitter.com/#!/Delradie

Using Linq to remove duplicate data from a DataTable


In response to a question on experts exchange I just wanted to do a quick post on data cleanup using Linq

Linq has a lot of very useful operations that can be used to reduce the complexity of array (or dataset) operation.

In this instance the operator .Distinct() can be used to remove duplicates in a datatable, with a small priviso:

If you call the method on the datatable (using the call .AsEnumerable() to get it in to a form you can work with in linq) with no parameters you will find that it returns all rows - this is because by default it does an object comparison, and of course all the records have their own memory address, and therefore are considered to be different. The trick is to tell it to use the default DataRowComparer which will get it to do a column by column value check.

One final point to watch out for is in getting the data back in to datatable - remember that datasets/tables/rows are reference types, so clearing down the tabe will actually cause problems, so the trick is to take a copy of the datatable, clear the original, operate on the copy, then reimport the rows to the cleared down table.

All put together,  the following function will handle this for you:

/// <summary>/// Removes duplicate rows from the target table/// </summary>/// <param name="sourceDataSet">Dataset containing the table to operate on</param>/// <param name="targetTableName">Name of the table to operate on</param>
{
public void GetUniqueRows(DataSet sourceDataSet, String targetTableName)  //Check there is data to operate on

   //Take a copy of the table so clearing does not affect the operation
   //Run the distinct operation
   //Clear all data from the target table  sourceDataSet.Tables[targetTableName].Clear();

  //Re-import the distinct rows to the 'live' table
  {
    sourceDataSet.Tables[targetTableName].ImportRow(DistinctRow);
  }
}
  foreach (DataRow DistinctRow in OutputRows)
  DataRow[] OutputRows = (from rows in OperatingData.AsEnumerable() select rows).Distinct(System.Data.DataRowComparer.Default).ToArray() as DataRow[];
  DataTable OperatingData = sourceDataSet.Tables[targetTableName].Copy();
  if (sourceDataSet.Tables[targetTableName].Rows.Count == 0)    return;

Friday, 3 December 2010

If you've found any of this information useful

I know that everyone is pretty much charitied out, but if you've found any of the information presented here useful, or just have a good heart, please support a cause that is very dear to me:

Happy Staffie Rescue (http://www.happystaffierescue.org.uk/), based in the west midlands, are a breed rescue for Staffordshire Bull Terriers - a much maligned but very loving breed (we have 3 of our own).

If you can spare even a small amount this would help make a big difference for some wonderful dogs that really do deserve much better than the hands that life has dealt them.

You can donate online via http://www.happystaffierescue.org.uk/id123.html

Merry Christmas