How to: Minify and bundle scripts and css in Umbraco

0 Kommentarer

How to: Unobtrusive Validation and minification using MVC in Umbraco

Last night I was updating my boys PS Vita it took a couple of hours and I was up alone so I decided to resolve an issue that I had in Umbraco, well it is not Umbraco related but a few things came up during the solution which is specific for Umbraco.

So I decided to write this "How to" to help anyone else wanting to implement unobtrusive validation with jquery and minification using mvc in Umbraco.


The goal here is to add unobtrusive validation to an MVC controller (SurfaceController in Umbraco) using jQuery, jQuery validation, MVC and bundled scripts in Umbraco

The setup

  • A clean installation of Umbraco 7.0.1
  • The Surface controller from Umbraco docs
  • jQuery 1.10.2
  • Umbraco built in Client Dependency
  • CDN for jQuery, jQuery validation, MVC unobtrusive validation etc...

Let's get to work

First let's prepare the ground by adding all the necessary dependencies, if you are a using Visual Studio or WebMatrix you can use the NuGet package manager otherwise you'll have to download the files manually and include them in your site.

jQuery + validation

PM> Install-Package jQuery
PM> Install-Package jQuery.Validation
PM> Install-Package Microsoft.jQuery.Unobtrusive.Ajax -Pre
PM> Install-Package Microsoft.jQuery.Unobtrusive.Validation -Pre

Getting the scripts together

Ensure if you are not using a CDN that the following files are in your /Script/ directory:

  • jquery-1.10.2.min.js (if you are using jquery version 2.0.3 also
  • jquery.unobtrusive-ajax.min.js
  • jquery.validate.min.js
  • jquery.validate.unobtrusive.min.js

Referencing & minification


There are a few things you have to do as you can see:

  • Add: @using ClientDependency.Core.Mvc
  • Add: @Html.Raw(@Html.RenderCssHere())
  • Add: @Html.Raw(@Html.RenderJsHere())

I have added them to my template where I want them.

@inherits Umbraco.Web.Mvc.UmbracoTemplatePage
@using ClientDependency.Core.Mvc;
 Layout = null;
<!DOCTYPE html>
 <!--[if lt IE 9]><script src=""></script><![endif]-->


In this template I have derived from the Master.cshtml layout view and I have added the following in this page:

  • @using ClientDependency.Core.Mvc
  • Html.RequiresJs("~/Scripts/jquery-1.10.2.min.js") (for JavaScript)
  • Html.RequiresCss("~/css/Page.css") (for StyleSheet)

If you want to order the including then just add another parameter like this:

  • Html.RequiresJs("~/Scripts/jquery-1.10.2.min.js", 1) (this will load first, it is a good idea to check this or just make it habit)

There is no need to call RenderJsHere or RenderCssHere it is done in the Master.cshtml file.

@inherits Umbraco.Web.Mvc.UmbracoTemplatePage
@using ClientDependency.Core.Mvc;
 Layout = "Master.cshtml";


Changes to ClientDependency.config in the ~/Config/ folder

I have included my whole ClientDependency.config file then you can use a tool like WinMerge to see the difference from yours!

A few important pointers

  • The minification and bundling will only happen if you set the web.config compilation debug attribute to false if set to true it will not minify or bundle and this is particular good when developing a website
  • The ClientDependency version has to be bumped up by 1 each time you change a css file or javascript file, so when you finish debugging remember to bump the version by 1!


<?xml version="1.0" encoding="utf-8"?>

For full details of the client dependency framework, visit
It manages CSS and JS file dependencies per control without having to worry about duplicates.
It also manages the combination, compression and minification of all JS & CSS files.

* Compression/Combination/Minification is not enabled unless debug="false" is specified on the 'compiliation' element in the web.config
* A new version will invalidate both client and server cache and create new persisted files
<clientDependency version="4" fileDependencyExtensions=".js,.css" loggerType="Umbraco.Web.UI.CdfLogger, umbraco">

 This section is used for Web Forms only, the enableCompositeFiles="true" is optional and by default is set to true.
 The LoaderControlProvider is set to default, the javascriptPlaceHolderId, cssPlaceHolderId attributes are optional and default to what is listed below. If using
 this provider, then you must specify both PlaceHolder controls on your page in order to render the JS/CSS.
 <fileRegistration defaultProvider="PlaceHolderProvider">
 <add name="PageHeaderProvider" type="ClientDependency.Core.FileRegistration.Providers.PageHeaderProvider, ClientDependency.Core" enableCompositeFiles="true" />
 <add name="LazyLoadProvider" type="ClientDependency.Core.FileRegistration.Providers.LazyLoadProvider, ClientDependency.Core" enableCompositeFiles="true" />
 <add name="LoaderControlProvider" type="ClientDependency.Core.FileRegistration.Providers.LoaderControlProvider, ClientDependency.Core" enableCompositeFiles="true" />
 <add name="PlaceHolderProvider" type="ClientDependency.Core.FileRegistration.Providers.PlaceHolderProvider, ClientDependency.Core" javascriptPlaceHolderId="JavaScriptPlaceHolder" cssPlaceHolderId="CssPlaceHolder" enableCompositeFiles="true" />

 <!-- This section is used for MVC only -->
 <mvc defaultRenderer="StandardRenderer">
 <add name="StandardRenderer" type="ClientDependency.Core.FileRegistration.Providers.StandardRenderer, ClientDependency.Core" enableCompositeFiles="true" />
 <add name="LazyLoadRenderer" type="ClientDependency.Core.FileRegistration.Providers.LazyLoadRenderer, ClientDependency.Core" enableCompositeFiles="true" />

 The composite file section configures the compression/combination/minification of files.
 You can enable/disable minification of either JS/CSS files and you can enable/disable the 
 persistence of composite files. By default, minification and persistence is enabled. Persisting files
 means that the system is going to save the output of the compressed/combined/minified files
 to disk so that on any subsequent request (when output cache expires) that these files don't have
 to be recreated again and will be based on the persisted file on disk. This saves on processing time.
 <compositeFiles defaultProvider="CompositeFileProcessor" compositeFileHandlerPath="~/DependencyHandler.axd">
 <add name="CompositeFileProcessor" type="ClientDependency.Core.CompositeFiles.Providers.CompositeFileProcessingProvider, ClientDependency.Core" enableCssMinify="true" enableJsMinify="true" persistFiles="true" compositeFilePath="~/App_Data/TEMP/ClientDependency" bundleDomains="localhost:123456" urlType="Base64QueryStrings" pathUrlFormat="{dependencyId}/{version}/{type}" />

 <!-- A file map provider stores references to dependency files by an id to be used in the handler URL when using the MappedId Url type -->
 <add name="XmlFileMap" type="ClientDependency.Core.CompositeFiles.Providers.XmlFileMapper, ClientDependency.Core" mapPath="~/App_Data/TEMP/ClientDependency" />
 <add type="application/json" path="^.*?/Services/.*"/>

 <add path="*" compressJs="true" compressCss="true" jsExt=".js,asmx/js" cssExt=".css">
 <add path="^.*test.aspx.*"/>


Changes in web.config

Enable client validation by adding two keys in the appSettings:

 <add key="ClientValidationEnabled" value="true" />
 <add key="UnobtrusiveJavaScriptEnabled" value="true" />

The view (we are almost there)

@model CommentViewModel

@using(Html.BeginUmbracoForm("CreateComment", "BlogPostSurface"))
@Html.EditorFor(x => Model)
<input type="submit"/>

We are done - happy coding!

Some description

0 Kommentarer