Archive for category .net
Adding minification and obfuscation of your Javascript and CSS to your ASP.net build process using Yahoo YUI Compressor
Posted by shawson in .net, C#.net, CSS, Javascript on July 22, 2011
I’ve just finished integrating Yahoo’s YUI Compressor into the MSBuild process for a new web probject I’m working on, and I thought I would document the process as there doesn;t seem to be a start to finish guide about anywhere.
To start with, let me just explain the structure I use for new Solutions;
C:\_Dev\MyNewWebsite\ C:\_Dev\MyNewWebsite\Artwork\ C:\_Dev\MyNewWebsite\BuildTools\ C:\_Dev\MyNewWebsite\Docs\ C:\_Dev\MyNewWebsite\Source\ C:\_Dev\MyNewWebsite\Source\MyNewWebsite.sln C:\_Dev\MyNewWebsite\Source\MyNewWebsite.Web\ C:\_Dev\MyNewWebsite\Source\MyNewWebsite.Web\Controls\ C:\_Dev\MyNewWebsite\Source\MyNewWebsite.Web\Images\ C:\_Dev\MyNewWebsite\Source\MyNewWebsite.Web\Scripts\ C:\_Dev\MyNewWebsite\Source\MyNewWebsite.Web\Services\ C:\_Dev\MyNewWebsite\Source\MyNewWebsite.Web\Styles\ C:\_Dev\MyNewWebsite\Source\MyNewWebsite.Web\MyNewWebsiteWeb.csproj C:\_Dev\MyNewWebsite\Source\MyNewWebsite.Entities\ C:\_Dev\MyNewWebsite\Source\MyNewWebsite.Entities\MyNewWebsiteEntities.csproj C:\_Dev\MyNewWebsite\Source\MyNewWebsite.Interfaces\ C:\_Dev\MyNewWebsite\Source\MyNewWebsite.Interfaces\MyNewWebsiteInterfaces.csproj C:\_Dev\MyNewWebsite\ThirdParty\
Firstly, download the dot net port of the YUI compressor from codeplex. I then extracted this into a new folder in the BuildTools folder. (there should be 2 dll files and one txt licence file.)
I then created a new MSBuild file called build-minify.xml, in the MyNewWebsite.Web project folder. That file looks like this;
<?xml version="1.0" encoding="utf-8"?>
<!-- http://yuicompressor.codeplex.com/wikipage?title=Sample%20MSBuild.xml%20File&amp;amp;amp;amp;ProjectName=yuicompressor -->
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<UsingTask
TaskName="CompressorTask"
AssemblyFile="..\..\BuildTools\Yahoo.Yui.Compressor-v1.5.0.0\Yahoo.Yui.Compressor.dll" />
<ItemGroup>
<CssFiles Include="$(SourceLocation)Styles\Fonts.css"/>
<CssFiles Include="$(SourceLocation)Styles\Site.css"/>
<CssIE Include="$(SourceLocation)Styles\IE.css"/>
<CssIE6 Include="$(SourceLocation)Styles\IE6.css"/>
<JsAll Include="$(SourceLocation)Scripts\jquery-1.6.1.min.js" />
<JsAll Include="$(SourceLocation)Scripts\jquery-ui-1.8.14.custom.min.js" />
<JsAll Include="$(SourceLocation)Scripts\json2.js" />
<JsAll Include="$(SourceLocation)Scripts\jqModal-r14.js" />
<JsAll Include="$(SourceLocation)Scripts\jquery.tipsy.js" />
<JsAll Include="$(SourceLocation)Scripts\jquery.scrollTo-1.4.2.min.js" />
<JsAll Include="$(SourceLocation)Scripts\jquery.localscroll-1.2.7.min.js" />
<JsAll Include="$(SourceLocation)Scripts\chinook-alert.js" />
<JsAll Include="$(SourceLocation)Scripts\chinook-validation.js" />
<JsAll Include="$(SourceLocation)Scripts\chinook-rollovers.js" />
<JsAll Include="$(SourceLocation)Scripts\chinook-custom-accordion.js" />
<JsAll Include="$(SourceLocation)Scripts\chinook-vehicle-lookup.js" />
<JsAll Include="$(SourceLocation)Scripts\chinook-sandbox.js" />
<JsAll Include="$(SourceLocation)Scripts\chinook-finance-calculator.js" />
<JsAll Include="$(SourceLocation)Scripts\chinook-apply-now.js" />
</ItemGroup>
<Target Name="Minimize">
<CompressorTask
CssFiles="@(CssFiles)"
DeleteCssFiles="false"
CssOutputFile="Styles/Site.rel.css"
CssCompressionType="YuiStockCompression"
DisableOptimizations="Nope"
EncodingType="Default"
LineBreakPosition="-1"
LoggingType="ALittleBit"
ThreadCulture="en-gb"
IsEvalIgnored="false"
/>
<CompressorTask
CssFiles="@(CssIE)"
DeleteCssFiles="false"
CssOutputFile="Styles/IE.rel.css"
CssCompressionType="YuiStockCompression"
DisableOptimizations="Nope"
EncodingType="Default"
LineBreakPosition="-1"
LoggingType="ALittleBit"
ThreadCulture="en-gb"
IsEvalIgnored="false"
/>
<CompressorTask
CssFiles="@(CssIE6)"
DeleteCssFiles="false"
CssOutputFile="Styles/IE6.rel.css"
CssCompressionType="YuiStockCompression"
DisableOptimizations="Nope"
EncodingType="Default"
LineBreakPosition="-1"
LoggingType="ALittleBit"
ThreadCulture="en-gb"
IsEvalIgnored="false"
/>
<CompressorTask
JavaScriptFiles="@(JsAll)"
ObfuscateJavaScript="true"
PreserveAllSemicolons="true"
DisableOptimizations="false"
EncodingType="Default"
DeleteJavaScriptFiles="false"
LineBreakPosition="-1"
JavaScriptOutputFile="Scripts/chinook.rel.js"
LoggingType="ALittleBit"
ThreadCulture="en-gb"
IsEvalIgnored="false"
/>
</Target>
</Project>
You can create whatever ItemGroups you’d like- then just create a compressor task for each. For a rundown of the settings, check out the link in the comment at the top of the XML there. In the above file I had decided to compress all of my Javascript into a single file called chinook.rel.js, and my fonts and site css file rolled into one file, keeping the ie6 css separate, but still minifying it down.
The next step is to add it to the normal build. I opened the solution in Visual Studio, right clicked my web project and selected properties. Go to “Build Events” and add the following post-build event;
$(MSBuildBinPath)\msbuild.exe $(ProjectDir)build-minify.xml /target:Minimize
Now you can test it out by building your project. The new minified files are dumped out, in my case to the Scripts folder. Now that the files are there, I need a way of telling my release version of the website to use these instead of the raw, human-readable versions; but I still want to continue using the human-readable versions for development.
To achieve this I use pre-processor directives. These are most commonly seen in the c# code behind files, but can also be used in the aspx files. I added the following lines at the bottom of my master page;
<% #if (!DEBUG) %>
<script src="Scripts/chinook.rel.js" type="text/javascript"></script>
<% #else %>
<script src="Scripts/jquery-1.6.1.min.js" type="text/javascript"></script>
<script src="Scripts/jqModal-r14.js" type="text/javascript"></script>
<script src="Scripts/chinook-alert.js" type="text/javascript"></script>
<script src="Scripts/jquery-ui-1.8.14.custom.min.js" type="text/javascript"></script>
<script src="Scripts/chinook-vehicle-lookup.js" type="text/javascript"></script>
<script src="Scripts/chinook-sandbox.js" type="text/javascript"></script>
<script src="Scripts/chinook-finance-calculator.js" type="text/javascript"></script>
<script src="Scripts/jquery.scrollTo-1.4.2.min.js" type="text/javascript"></script>
<script src="Scripts/jquery.localscroll-1.2.7.min.js" type="text/javascript"></script>
<script src="Scripts/jquery.tipsy.js" type="text/javascript"></script>
<script src="Scripts/json2.js" type="text/javascript"></script>
<script src="Scripts/chinook-validation.js" type="text/javascript"></script>
<script src="Scripts/chinook-apply-now.js" type="text/javascript"></script>
<script src="Scripts/chinook-rollovers.js" type="text/javascript"></script>
<script type="text/javascript" src="Scripts/chinook-custom-accordion.js"></script>
<% #endif %>
So if the project is NOT running in debug mode, I import my full chinook.rel.js include which has everything already included, otherwise I manually include all the human readable, separate files.
And that’s pretty much it. Make sure you thoroughly retest your site with your combined java script file, as sometimes minification can cause issues with some code.
Entity Framework 4.1 Code First (With One to Many relationship) Code Example
Posted by shawson in .net, C#.net, Entity Framework, Linq on July 10, 2011
A quick piece of code demo’ing a very common/ simple usage scenario- basic one to many with some demo data being seeded into the database; I thought this might be needed as I’ve waded through a LOT of exmaples for various beta versions and different releases of EF, but had little luck actually finding something relevant. The best site I came across was tucked away on the ADO.net team’s blog- Using DbContext in EF 4.1. First– the entities and the database context
public class Category
{
[Key]
public Guid ID { get; set; }
public string Title { get; set; }
public virtual ICollection<Product> Products { get; set; }
//virtual makes this lazily loaded
public Category()
{
this.ID = Guid.NewGuid();
}
}
public class Product
{
[Key]
public Guid ID { get; set; }
public string Title { get; set; }
public string Details { get; set; }
public double Price { get; set; }
public string ImageFileName { get; set; }
public DateTime DateAdded { get; set; }
public virtual Category Category { get; set; }
//virtual makes this lazily loaded
public Product()
{
this.ID = Guid.NewGuid();
}
}
public class MyDBContext: DbContext
{
public DbSet<Product> Products { get; set; }
public DbSet<Category> Categories { get; set; }
}
Note the use of ICollection on Products in Category, and the use of DbSet in the context. I used a DbSet in lieu of ICollection on the Products entity and found it went mental if I had a Product with no category (something which I wanted to be valid) – swapping it to ICollection fixed this issue (I don’t know enough of the inner workings to explain why)
BAMM! Next for the seeding- add a class like so;
public class MyDBInitializer : DropCreateDatabaseAlways<MyDBContext>
{
protected override void Seed(Entities.ComicolleDB context)
{
Category marvel = new Category()
{
Title = "Category 1"
};
Category dc = new Category()
{
Title = "Category 2"
};
context.Categories.Add(marvel);
context.Categories.Add(dc);
context.Products.Add(new Product()
{
Title = "Test1",
ImageFileName = "image-1.gif",
Details = "This is a test",
Price = 4.99,
DateAdded = DateTime.Now,
Category = marvel
});
context.Products.Add(new Product()
{
Title = "Test2",
ImageFileName = "image-1.gif",
Details = "This is a test",
Price = 4.99,
DateAdded = DateTime.Now,
Category = dc
});
context.Products.Add(new Product() // no category
{
Title = "Test3",
ImageFileName = "image-1.gif",
Details = "This is a test",
Price = 4.99,
DateAdded = DateTime.Now
});
context.SaveChanges();
}
}
Then add the following line to the end of your Application_Start() method in global.asax;
Database.SetInitializer<MyDBContext>(new MyDBInitializer());
Voila- you can then go ahead and use your model in whatever applications you see fit- here are some example;
MyDBContext db = new MyDBContext();
// get a category, and make sure the products are loaded
Category the_category = db.Categories.Include("Products")
.Where(x => x.Title == "Category 1").SingleOrDefault();
// get all the products for that category
List<Product> some_products = the_category.Products;
// get all the categories (without loading the products)
List<Category> some_categories = db.Categories.ToList();
Netgear ReadyNAS Duo command line shut down utility
Posted by shawson in .net, C#.net, Networking on July 4, 2011
So I finished the backup app and compiled it for anyone who wants it- it’s used from the command prompt like so;
ShutdownNASBox -h <hostname> -u <username> -p <password>
eg.
ShutdownNASBox -h backup -u admin -p abc123
If you run the tool with administrator privileges, it will log to the Windows Event Log on the System tab.
You can download it here (note you will need dot net framework 4 installed)
Automatic NAS Box shutdown – How to POST the shutdown command over SSL with HTTP authentication from a dot net Console app (Part 1/2)
Posted by shawson in .net, C#.net, Networking on July 3, 2011
I recently purchased a Netgear ReadyNAS Duo RAIDed network storage box for general backup of my ‘stuff and things’, which sit’s on my desk and runs off the same power as my PC. A couple of times now I’ve booted the box up to run a backup, then forgot to shut it down, then shut down my PC, flick the switch at the wall and then realise. When I boot everything back up in a day or so, the NAS box has to do a full system check and maybe rebuild the RAID array if theres a problem etc etc – it’s a pain.
So I thought I would set about automating the NAS box shut down with my PC shut down which turned out to be pretty easy. The NAS box is controller via a web UI- my box has the host name “BACKUP” so I can get to it over the browser on http://BACKUP/. This uses basic HTTP authentication asking me to login, and also use’s https (which my browser always warns me about because it’s not from a trusts CA or whatever- so I just ignore the warnings and continue). From the web UI you can go to the system tab and select shut down and the box goes down. I figured as this is going to be a simple web call, it should be easy enough to write a simple console app which makes the same call which can be fired on Windows shutdown- so I fired up Firebug, opened the “Net” tab, which allows you to inspect all http calls made, and triggered a shut down. It’s probably worth noting at this point that the techniques used here could probably be applied to pretty much any other networked device with a web based UI (most routers, firewalls, switches, printers, media boxes etc) so this should hopefully be quite useful.
Sure enough the HTTPS POST made to a file called get_handler on the root could be seen, with the POST data string;
As we can see from firebug, the data sent is;
PAGE=System&OUTER_TAB=tab_shutdown&INNER_TAB=NONE&shutdown_option1=1&command=poweroff&OPERATION=set
So six key value pairs separated by ampersands. The code itself is pretty simple using WebClient class (System.Net namespace)- however there are a couple of complications, which as it happens are fairly common things to run into, so a good opportunity to give some example code for future reference;
-
We need to perform our Form Post over SSL
-
The SSL certificate of the server we are posting to will never be valid!
-
We must carry out our form post while supplying basic HTTP authentication credentials
I created a new Console application and added the following code;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Collections.Specialized;
namespace ShutdownNASBox
{
class Program
{
static void Main(string[] args)
{
using (WebClient client = new WebClient())
{
// add the basic http authentication username &amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp; password
client.Credentials = new NetworkCredential("admin", "abc123");
// register the face that the connection uses SSL
// (otherwise it defaults to TLS and you get an exception)
ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3;
// set it to effectivly ignore the SSL certificate
ServicePointManager.ServerCertificateValidationCallback =
delegate { return true; };
// build a NameValueCollection which holds those 6 values we saw
// being posted when we used firebug
NameValueCollection c = new NameValueCollection();
c.Add("PAGE", "System");
c.Add("OUTER_TAB", "tab_shutdown");
c.Add("INNER_TAB", "NONE");
c.Add("shutdown_option1", "1");
c.Add("command", "poweroff");
c.Add("OPERATION", "set");
try
{
// Post the data! This will return as a byte array
byte[] bytes =
client.UploadValues("https://backup/get_handler", c);
// convert the byte array into text we can read!
string result = Encoding.ASCII.GetString(bytes);
Console.Write("Shutdown Message Sent");
Console.Write(result);
}
catch (Exception e)
{
Console.Write("Shutdown Message Send Failure!");
Console.Write(e.ToString());
}
}
}
}
}
And that’s all there is to it! An obvious and easy upgrade would be to make this parametrized and maybe get it to write to the windows log on failure.
In part two I shall do a quick post on how to schedule tasks to run on shut down in Windows 7.
You can see the finished app, with the above recommended improvements already implemented, here
Entity Framework “The data reader is incompatible with the specified complex type.”
Posted by shawson in .net, C#.net, Linq, SQL Server on June 7, 2011
I recently had this problem with a site I’m working on. I’m using Entity framework to access a bunch of legacy stored procedures, originally in MySQL but ported over to MSSQL. Having added the sprocs to EF and let it auto-generate it’s magic, I was shocked to find one of my calls throwing the following exception;
System.Data.EntityCommandExecutionException: The data reader is incompatible with the specified 'ChinookModel.GetVehicleDescFromModelId_Result1'. A member of the type, 'ivaluationid1', does not have a corresponding column in the data reader with the same name. at System.Data.Query.InternalTrees.ColumnMapFactory.GetMemberOrdinalFromReader(DbDataReader storeDataReader, EdmMember member, EdmType currentType, Dictionary`2 renameList) at System.Data.Query.InternalTrees.ColumnMapFactory.GetColumnMapsForType(DbDataReader storeDataReader, EdmType edmType, Dictionary`2 renameList) at System.Data.Query.InternalTrees.ColumnMapFactory.CreateColumnMapFromReaderAndType(DbDataReader storeDataReader, EdmType edmType, EntitySet entitySet, Dictionary`2 renameList) at System.Data.Query.InternalTrees.ColumnMapFactory.CreateFunctionImportStructuralTypeColumnMap(DbDataReader storeDataReader, FunctionImportMapping mapping, EntitySet entitySet, StructuralType baseStructuralType) at System.Data.EntityClient.EntityCommandDefinition.FunctionColumnMapGenerator.System.Data.EntityClient.EntityCommandDefinition.IColumnMapGenerator.CreateColumnMap(DbDataReader reader) at System.Data.Objects.ObjectContext.CreateFunctionObjectResult[TElement](EntityCommand entityCommand, EntitySet entitySet, EdmType edmType, MergeOption mergeOption) at System.Data.Objects.ObjectContext.ExecuteFunction[TElement](String functionName, MergeOption mergeOption, ObjectParameter[] parameters) at System.Data.Objects.ObjectContext.ExecuteFunction[TElement](String functionName, ObjectParameter[] parameters) at Chinook.Model.ChinookEntities.GetVehicleDescFromModelId(Nullable`1 modelid) in C:\_Dev\Chinook\Source\Chinook.Model\Chinook.Designer.cs:line 160 at Chinook.Model.GlassGuideDataProvider.GetVehicleFromModelId(Int32 ModelId) in C:\_Dev\Chinook\Source\Chinook.Model\GlassGuideDataProvider.cs:line 104 at Chinook.Services.VehicleDataLookup.GetVehicleForRegistration(String reg) in C:\_Dev\Chinook\Source\Chinook\Services\VehicleDataLookup.asmx.cs:line 81
It seemed to be moaning that one of the columns in the complex type I set for it to use as the return type, doesn’t match to a column actually being returned, despite entity framework having auto generated that type itself! The cause was, as is generally the case, user error. Inspecting the sproc a bit closer I noticed one of the columns was being returned twice, using the same name. EF generated me a call with an iValuation and iValuation1 column, but failed to match iValuation1 because in reality both columns were simply called iValuation! So a simple, and kind of obvious fix, but worth noting to stop someone else loose a little more hair when they’re confonted with this error!
Adding Javascript Unit Testing/ Compression to your MSBuild
Posted by shawson in .net, Javascript, Test Driven Development on May 4, 2011
A couple of resources- I shall add to this post as I look into this myself. I basically want to add steps to my project file, so msbuild will run javascript tests (qUnit) and perform minification/ combines all the js source files.
- http://yuicompressor.codeplex.com/
- http://blogs.msdn.com/b/francischeung/archive/2010/02/13/integrating-javascript-unit-tests-with-continuous-integration.aspx
- http://www.testinggeek.com/index.php/testing-tools/test-execution/189-qunit-selenium-continuous-integration
- http://dotnet.geir-sorensen.net/2010/04/10/msbuild-custom-targets/
- http://www.simple-talk.com/dotnet/.net-tools/extending-msbuild/
Quickly Find/ Open a file in Visual Studio
Posted by shawson in .net, Visual Studio on April 14, 2011
I’m working on some massive solutions containing loads of projects at my new place and frequently have to shoot between different source files scattered all over- A colleague recently showed me a really quick way to find and open files- from the Find bar in the top ‘standard’ menu bar, you can type ‘>of’ followed by the name of the file you are after and it will bring up an auto complete menu letting you select and open the file.

Random Band Generator!
Posted by shawson in .net, C#.net, Javascript, jQuery on February 12, 2011
Just a quick post to mention that I’ve uploaded the Random Band Generator- just a bit of fun I boshed together built for a mate… check it out here.
Finally, proper browser support for WebGL thanks to Google Chrome!
Posted by shawson in WebGL, XNA Game Development on February 10, 2011
Google released Google Chrome v9 a few days ago with native WebGL support- no more having to hack around hidden browser settings, WebGL will now work, out of the box, on one of the “main stream” browsers.
In light of this I’m doing a round up a bunch of WebGL 3d engines available at the moment (which I shall put up here when I’m done) to help me select which engine to use as the base for my next 8weekgame competition entry. I think I shall stick with the re-make of Desert Strike, but will be moving away from the original XNA I started out with, to make it totally web based (No flash plugins!) like my previous submission, Manic Spaceman
Microsoft Creators Club – Premium Account Cancellation- Microsofts best kept secret!
Posted by shawson in XNA Game Development on February 6, 2011
So I signed up for an Microsoft creators club account a while back and it just auto-renewed. I’ve not used it for a while so figured I would cancel it from robbing me of any more money! I hopped over to their site at https://windowsphone.create.msdn.com/support and after an hour of hunting through EVERY part of that site, and various forums posts with other people complaining of the same thing which pointed me to a bunch of “Account Cancellation” links which all ended in “Oops, this page has been moved!”. I was even directed to billing.microsoft.com which acknowledged the fact that I had this £30 payment going out every 4 months; I clicked on the row and then clicked to disable the service, which brings up a bunch of links to various websites, but nothing about the creators club!? So, the site basically told me what I already knew, and did nothing to help solve the problem.
I eventually came across a forum post which pointed me in the direction of a contact form: https://windowsphone.create.msdn.com/support?redirectToUrl=%2FApp. Upon completing the forum I was redirected to the app creator home page- no “thank you, we will get back to you” page, so now I can only wait and hope that someone actually picks up my mail!

