@Shazwazza

Shannon Deminick's blog all about web development

Introducing ‘Smidge’ – an ASP.NET 5 runtime JS/CSS pre-processor

December 11, 2014 23:19

During the past month I decided to dive deep into learning ASP.NET 5, and what better way to learn than to start a new OSS project :)

I chose to make a new new simple and extensible Javascript/CSS runtime pre-processor for ASP.NET 5. It does file minification, combination and compression, has a nice file caching layer and it’s all done in async operations. I ported over a few ideas and code snippets from CDF (client dependency framework) but with a more modern approach. I’ve called it ‘Smidge’ = something really small.

The project is on GitHub, it’s still a work in progress but its functional and there’s even some documentation! In the next few weeks I’ll get more of the code and docs updated and hopefully have a beta release out. In the meantime, you can clone the source, browse the code, build it and of course use it if you like.

Project details

It’s currently only targeting aspnet50 and not the Core CLR… I didn’t start with Core CLR because there was some legacy code I had to port over and I wanted to get something up and working relatively quickly. It shouldn’t be too much work to convert to Core CLR and Mono, hopefully I’ll find time to do that soon. It’s referencing all of the beta-* libraries from the ASP.NET 5 nightly myget feeds since there’s some code I’m using that isn’t available in the current beta1 release (like Microsoft.AspNet.WebUtilities.UriHelper). The target KRE version is currently KRE-CLR-amd64 1.0.0-beta2-10760.

Installation

I’ve put up an Alpha 1 release on Nuget, so you can install it from there:

PM> Install-Package Smidge -Pre

There’s some installation instructions here, you’ll need to add the smidge.json file yourself for now, can’t figure out how to get VS 2015 (kpm pack) to package that up … more learning required!

 

There’s certainly a lot of detective work involved in learning ASP.NET 5 but with the code being open source and browse-able/searchable on GitHub, it makes finding what you need fairly easy.

ClientDependency 1.8 released

July 7, 2014 08:02

It’s taken me forever to get this release out purely due to not having enough time, but here it finally is. This update now multi-targets framework versions:

  • Core project now targets both .Net 4 and 4.5
  • MVC project is now targets both .Net 4 and 4.5 for MVC 4 and .Net 4.5 for MVC 5

There are also a couple of minor bug fixes:

The update to the CDF .Less project is the update to use the latest .Less 1.4.0.0 version.

To install the CDF core:

PM> Install-Package ClientDependency

To install CDF for MVC (less than v5):

PM> Install-Package ClientDependency-MVC

If you are using MVC 5 then you’ll need to use the MVC 5 specific version:

PM> Install-Package ClientDependency-MVC5

To install the .Less update:

PM> Install-Package ClientDependency-Less

Remember CDF also supports TypeScript, CoffeeScript and SASS!

PM> Install-Package ClientDependency-TypeScript

PM> Install-Package ClientDependency-CoffeeScript

PM> Install-Package ClientDependency-SASS

Multi targeting a single .Net project to build for different framework versions

May 2, 2014 04:18

Consider this scenario:

  • I have a project that relies on ASP.Net MVC and currently this project is built against the .Net framework 4.0 and MVC 4
  • I want to support MVC 5 for this project
  • To support MVC 5, I’d need to upgrade the project to use .Net framework 4.5
  • This would mean that developers still running .Net framework 4.0 would no longer be able to use my updated project

I also don’t want to have to create different projects and assemblies that target specific MVC versions (in this case you’d end up with assembly names like MyProject.MVC4.dll and MyProject.MVC5.dll). I have seen this done with other solutions and it works but I feel it is not necessary unless your project is using specific functionality from a particular MVC version.

In my case my project will compile perfectly against MVC 4 and 5 without any codebase changes so I’m not actually targeting against a specific MVC version ( >= 4 ). If your project uses specific functionality from the different MVC versions I think you will have to output different assemblies like MyProject.MVC5.dll. In that case this post will probably help: http://blogs.korzh.com/2013/12/nuget-package-different-mvc-versions.html

The goal

The end result is that I want a single project file that has 4 build configurations:

  • Debug / Release
    • These will build against .Net 4.0
    • This will reference MVC 4
  • Debug-Net45 / Release-Net45
    • This will build against .Net 4.5
    • This will reference MVC 5

Each of these build configurations exports the same assembly name: MyProject.dll

I then want a single NuGet package which will install the correct DLL based on the .Net version that the user has installed.

How it’s done

Build configuration setup

To start with you’ll have a project that targets .Net framework 4.0 and references MVC 4 and 2 standard build configurations: Debug, Release.

First we need to create 2 new build configurations: Debug-Net45 and Release-Net45 and have these configurations output the DLLs to a custom folder. To do this we launch the Configuration Manager:

2014-04-30_2014

Create a new build configuration:

2014-04-30_2016

Enter the name of the new configuration and copy the configuration from it’s associated existing one. So Debug-Net45 would copy from Debug and Release-Net45 copies from Release.

2014-04-30_2021

Do this for both configurations – Debug-Net45 and Release-Net45.

Project setup

The next step requires manually editing your .csproj file since Visual Studio doesn’t want to normally allow you to do this. This is how you can configure each build type to target a different framework version. You’ll first need to find these 2 entries:

<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">

Inside each of these elements you need to explicitly tell these build configurations to use .Net framework 4.0 by adding this element:

<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>

Next you’ll want to copy/paste both of these property groups and:

  • Change the Condition to check for the new build configurations and to target .Net framework 4.5
  • Change the OutputPath to have a specific .Net 4.5 folder
  • Change the TargetFrameworkVersion to be .Net 4.5

You should end up with 2 new elements that look something like:

<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug-Net45|AnyCPU'">
    <DebugSymbols>true</DebugSymbols>
    <OutputPath>bin\Debug-Net45\</OutputPath>
    <DefineConstants>DEBUG;TRACE</DefineConstants>
    <DebugType>full</DebugType>
    <PlatformTarget>AnyCPU</PlatformTarget>
    <ErrorReport>prompt</ErrorReport>
    <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
    <PlatformTarget>AnyCPU</PlatformTarget>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release-Net45|AnyCPU'">
    <DebugType>pdbonly</DebugType>
    <Optimize>true</Optimize>
    <OutputPath>bin\Release-Net45\</OutputPath>
    <DefineConstants>TRACE</DefineConstants>
    <ErrorReport>prompt</ErrorReport>
    <WarningLevel>4</WarningLevel>
    <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
    <PlatformTarget>AnyCPU</PlatformTarget>
</PropertyGroup>

Next we need to do this for the MVC references or any framework specific references you need to target. In this example it is just the MVC references and you’ll need to wrap them with an ItemGroup element, you’ll end up with something like this to target the MVC 4 libs:

<ItemGroup Condition=" '$(Configuration)'=='Debug' Or '$(Configuration)'=='Release'">
    <Reference Include="System.Web.Helpers, Version=2.0.0.0, .....">
      <Private>True</Private>
      <HintPath>
        ..\packages\Microsoft.AspNet.WebPages.2.0.30506.0\lib\net40\System.Web.Helpers.dll
      </HintPath>
    </Reference>
    <Reference Include="System.Web.Mvc, Version=4.0.0.0, .....">
      <Private>True</Private>
      <HintPath>
        ..\packages\Microsoft.AspNet.Mvc.4.0.30506.0\lib\net40\System.Web.Mvc.dll
      </HintPath>
    </Reference>
    <Reference Include="System.Web.Razor, Version=2.0.0.0, .....">
      <Private>True</Private>
      <HintPath>
        ..\packages\Microsoft.AspNet.Razor.2.0.30506.0\lib\net40\System.Web.Razor.dll
      </HintPath>
    </Reference>
    <Reference Include="System.Web.WebPages, Version=2.0.0.0, .....">
      <Private>True</Private>
      <HintPath>
        ..\packages\Microsoft.AspNet.WebPages.2.0.30506.0\lib\net40\System.Web.WebPages.dll
      </HintPath>
    </Reference>
    <Reference Include="System.Web.WebPages.Deployment, Version=2.0.0.0, .....">
      <Private>True</Private>
      <HintPath>
        ..\packages\Microsoft.AspNet.WebPages.2.0.30506.0\lib\net40\System.Web.WebPages.Deployment.dll
      </HintPath>
    </Reference>
    <Reference Include="System.Web.WebPages.Razor, Version=2.0.0.0, .....">
      <Private>True</Private>
      <HintPath>
        ..\packages\Microsoft.AspNet.WebPages.2.0.30506.0\lib\net40\System.Web.WebPages.Razor.dll
      </HintPath>
    </Reference>
</ItemGroup>

Then we need to go ahead and copy/paste this block but target the different build configurations and then swap out these MVC 4 version references with the MVC 5 version references.

Nuget package restore

For this tutorial I’m assuming you are using Nuget to reference your MVC libs and an easy way to get Nuget to play reasonably with this setup is to enable Nuget package restore for your solution – right click on your solution and click the button:

2014-05-01_1625

Then in your packages.config file you can manually add the MVC 5 references:

<?xml version="1.0" encoding="utf-8"?>
<packages>
  <package id="Microsoft.AspNet.Mvc" 
           version="4.0.30506.0" targetFramework="net40" />
  <package id="Microsoft.AspNet.Razor" 
           version="2.0.30506.0" targetFramework="net40" />
  <package id="Microsoft.AspNet.WebPages" 
           version="2.0.30506.0" targetFramework="net40" />
  <package id="Microsoft.Web.Infrastructure" 
           version="1.0.0.0" targetFramework="net40" />
  
  <package id="Microsoft.AspNet.Mvc" 
           version="5.0.0" targetFramework="net45" />
  <package id="Microsoft.AspNet.Razor" 
           version="3.0.0" targetFramework="net45" />
  <package id="Microsoft.AspNet.WebPages" 
           version="3.0.0" targetFramework="net45" />
</packages>

Now when you build your solution under the different build configurations Nuget will automatically go and get the correct MVC versions based on the current .Net Framework version.

Thats it!

With all of this in place it should ‘just work’ :) You will notice some odd looking icons in your references list in Visual Studio but it’s nothing to worry about, Visual Studio is just confused because it isn’t familiar with how you’ve tricked it!

2014-05-01_1709

So now when you build using your different build configurations, it will output the correct DLLs to the correct build folders:

  • Both Debug & Release will output to /bin/Debug & bin/Release with MVC 4 libraries and the MyProject.dll will be compiled against .Net Framework 4.0
  • Both Debug-Net45 & Release-Net45 will be output to /bin/Debug-Net45 & /bin/Release-Net45 with MVC 5 libraries and the MyProject.dll will be compiled against .Net Framework 4.5

And here’s some proof:

2014-05-01_1714

2014-05-01_1715

If you are using some automated build processes with MSBuild you can then just target the build configuration names you’d like to export.

The Nuget setup is pretty simple since you can target your dependencies by framework:

<group targetFramework="net40">
<!--between 4 and less than version 5-->
<dependency id="Microsoft.AspNet.Mvc" version="(4.0.20710,5)" />
</group>

<group targetFramework="net45">
<!--between 4 and less than version 6 (who knows what'll happen then)-->
<dependency id="Microsoft.AspNet.Mvc" version="(4.0.20710,6)" />
</group>

Then for each of your lib files in Nuget you ensure that you output them to the framework specific /lib folders such as:

target="lib\net40"
target="lib\net45"

This process has been implemented for the Client Dependency Framework version 1.8.0 to support MVC 4 and 5 without having to change the assembly name.

VirtualPathUtility Fixed in .Net 4

August 30, 2010 22:13

If you are not already aware there’s an issue with the VirtualPathUtility object in the .Net framework. If you are trying to use the IsAbsolute or ToAbsolute methods with a path that contains a query string, you’ll get an exception thrown. A quick Google search on this issue will show you a ton of posts and ‘work arounds’ for this problem and I’ve implemented a custom work around for this in the ClientDependency framework as well. In fact, I only noticed this problem when testing the ClientDependency framework with .Net 3.5 and trying to register embedded resources through it (as see in this blog post here). Since I’d been developing the latest builds of ClientDependency in .Net 4, i had no problems at all but as soon as I changed the build to .Net 3.5, the exceptions began to show since web resource URLs have query strings.

So it the good new is that it appears as though Microsoft have finally fixed this bug in .Net 4! The bad news is that you’ll still have to use your ‘work arounds’ if you are targeting framework versions below 4.

Adding embedded resource with ClientDependency

August 3, 2010 22:32
This post was imported from FARMCode.org which has been discontinued. These posts now exist here as an archive. They may contain broken links and images.
The uComponents project for Umbraco is coming along rather nicely! So far there are 13 new data types created and a few extensions, hopefully soon we’ll have a package ready to go. In the meantime, I thought I’d share a nice little code snippet that we’re using this throughout uComponents that allows you to add embedded resources to ClientDependency. It’s pretty easy and works perfectly with Umbraco 4.5 or any other site you have running ClientDependency. This will ensure that embedded resources (JavaScript or CSS) are added to the ClientDependency combined scripts/styles and also compressed and cached.

First, I’ll show you how to register your embedded resources using our extension method class (for a Control object):

this.AddResourceToClientDependency(
    "DataTypesForUmbraco.Controls.Shared.Resources.PrevalueEditor.css", 
    ClientDependency.Core.ClientDependencyType.Css);

The above code assumes:

  • The class that you are consuming the code inherits from System.Web.UI.Control
  • That your embedded resource’s path is: DataTypesForUmbraco.Controls.Shared.Resources.PrevalueEditor.css
  • That your embedded resource is a CSS type

Pretty easy right!! Well, the only thing missing is that you’ll need to add our extension method class to your project which looks like this:

/// 
/// Extension methods for embedded resources
/// 
public static class ResourceExtensions
{

    /// 
    /// Adds an embedded resource to the ClientDependency output by name
    /// 
    /// 
    /// 
    /// 
    public static void AddResourceToClientDependency(this Control ctl, string resourceName, ClientDependencyType type)
    {
        //get the urls for the embedded resources           
        var resourceUrl = ctl.Page.ClientScript.GetWebResourceUrl(ctl.GetType(), resourceName);

        //add the resources to client dependency
        ClientDependencyLoader.Instance.RegisterDependency(resourceUrl, type);
    }

    /// 
    /// Adds an embedded resource to the ClientDependency output by name and priority
    /// 
    /// 
    /// 
    /// 
    public static void AddResourceToClientDependency(this Control ctl, string resourceName, ClientDependencyType type, int priority)
    {
        //get the urls for the embedded resources           
        var resourceUrl = ctl.Page.ClientScript.GetWebResourceUrl(ctl.GetType(), resourceName);

        //add the resources to client dependency
        ClientDependencyLoader.Instance.RegisterDependency(priority, resourceUrl, type);
    }

}

So basically, if you have a Control, you can register your embedded resources in ClientDependency with one line of code… sweeeeet.

Umbraco 4.1 Benchmarks Part 1 (Do Over)

April 20, 2010 10:06
This post was imported from FARMCode.org which has been discontinued. These posts now exist here as an archive. They may contain broken links and images.
Doh! Turns out that my first Umbraco 4.1 benchmarks was done on a build of 4.1 that had a couple of bugs in it :( BUT, this turns out to be even better for 4.1 that I previously thought! (plus there’s bugs fixed now :) If you didn’t read the last post, i recommend that you do as it has some insight as to how these stats came to be.

So, without further adieu, here’s the (true) new results:

Test Stats 4.0.3 4.0.3
client cached
4.1 4.1
client cached
Content app Completed Requests 68 7 45 5
Response (KB) 687.05 72.48 382.42 11.61
Edit content
home page
Completed Requests 50 2 34 1
Response (KB) 385.10 47.28 335.02 11.94
Expand all
content nodes
Completed Requests 17 17 16 16
Response (KB) 18.47 18.47 13.96 7.54
TOTALS Completed Requests 135 26 95 22
Response (KB) 1063.62 138.23 731.40 31.09

So to recap, here’s the total average savings in 4.1

  • Without client cache (First run)
    • Number of completed requests: 30% Less
    • Response bandwidth: 31% Less
  • With client cache
    • Number of completed requests: 6% Less
    • Response bandwidth: 78% Less

Umbraco 4.1 Benchmarks Part 1

April 16, 2010 11:42
This post was imported from FARMCode.org which has been discontinued. These posts now exist here as an archive. They may contain broken links and images.
This is the first installment of what will hopefully be many Umbraco benchmark reports created by various members of the core team in the lead up to the launch of Umbraco 4.1. This benchmark report is about the request/response performance of the Umbraco back-office. This compares 4 different configurations: 4.0.3 with browser cache disabled (first run), 4.0.3 with browser cached files, 4.1 with browser cache disabled and 4.1 with browser cached files. These comparisons have been done by using newly installed Umbraco instances with ONLY the CWS package installed. The benchmark results were prepared by using Charles Proxy.
Test Stats 4.0.3 4.0.3
client cached
4.1 4.1
client cached
Content app Completed Requests 68 7 46 6
Response (KB) 687.05 72.48 431.41 32.54
Edit content
home page
Completed Requests 50 2 34 1
Response (KB) 385.10 47.28 343.36 12.07
Expand all
content nodes
Completed Requests 17 17 16 16
Response (KB) 18.47 18.47 13.96 10.85
TOTALS Completed Requests 135 26 96 23
Response (KB) 1063.62 138.23 788.73 55.46

Note: the above is based on <compilation debug=”false”> being set in the web.config. If it is set to true, the compression, combination and minification for both the ClientDependency framework and ScriptManager is not enabled. Also, this is not based on having IIS 7’s dynamic/static compression turned on, these benchmarks are based on Umbraco performing ‘as is ‘ out of the box which will be the same for IIS 6.

Though there’s only 3 tests listed above, these results will be consistent throughout all applications in the Umbraco back office in version 4.1.

The 4.1 difference:

  • In 4.0.3, all ScriptResource calls generated by ScriptManager were not being compressed or minified. This was due to a browser compatibility flag that was set in the base page (this was probably very old code from pre v3!).
  • Script managers in the back-office have the ScriptMode=”release” explicitly set (for minification of ScriptResource.axd)
  • The ClientDependency framework is shipped with 4.1 and all of the back office registers it’s JavaScript and CSS files with this framework. This allows for:
    • Combination, compression, minification of dependencies
    • Rogue script/style detection (for those scripts/styles that weren’t registered with the framework will still get compressed/minified)
    • Compression/minification of specified Mime types, in this case all JSON requests in the back office (namely the tree)
    • Compression/minification of all JavaScript web service proxy classes (‘asmx/js’ requests that are made by registering web services with the ScriptManager
  • Much of the back office client scripting in 4.1 has been completely refactored. Most of the JavaScript has been rewritten and a ton of file cleanup has been done.

Compared to 4.0.3, this is a HUGE difference with some serious performance benefits!

ClientDependency now supporting MVC

April 7, 2010 11:38
This post was imported from FARMCode.org which has been discontinued. These posts now exist here as an archive. They may contain broken links and images.
I’m please to announce that the ClientDependency framework now supports MVC! It’s very easy to implement using HtmlHelper extension methods. Here’s some quick examples:

Make a view dependent on a CSS file based on a path defined as “Styles”

<% Html.RequiresCss("Content.css", "Styles"); %>

Make a view dependent on jQuery using a full path declaration:

<% Html.RequiresJs("/Js/jquery-1.3.2.min.js"); %>

Rendering the Style blocks and defining a global style path:

<%= Html.RenderCssHere(new BasicPath("Styles", "/Css")) %>

Rendering the Script block (no global script path defined):

<%= Html.RenderJsHere() %>

There’s still a provider model for MVC but it uses a slightly different implementation from Web Forms. The same compositeFiles provider model is used but instead of the fileRegistration provider model that is used in Web Forms, a new mvc renderers provider model is used. A renderer provider is similar to the Web Forms fileRegistration providers but instead of registering the markup in the page using the page life cycle, a renderer provider is used to render out the html block necessary to embed in the page.

All of the functionality that existed in Web Forms exists in MVC. You can make as many views that you want dependent on as many of the same or different client files that you want and the system will still sort by position and priority and remove all duplicate registrations. Rogue scripts & styles still get processed by the composite file provider in MVC. Currently however, if you place user or composite controls on your views that have Client Dependencies tagged with either the control or attribute method used in Web Forms, these will not be registered with the view and output with the renderer. 

MVC pages have been added to the demo project as examples so have a look! You can download the source HERE

For full details and documentation go HERE

ASP.Net Client Dependency Framework RC1 Released!

March 19, 2010 09:13
This post was imported from FARMCode.org which has been discontinued. These posts now exist here as an archive. They may contain broken links and images.
With the community feedback, bug reports, patches, etc… I’ve managed to find time to upgrade this library to a release candidate status. We do use this framework in many production websites but it was great to hear from other in regards to specific bugs that were found relating to particular environments. These bugs have all been fixed up and this library is looking very stable.

You can download the binaries here.

Better yet, I’ve put together a near complete documentation library on CodePlex here !!

I still think the best way to learn about this project is to download the source code from CodePlex here and have a look at the demo web application included.

Moving forward, the next phase for this library is to add MVC support and another file registration provider called PlaceholderProvider which will give you even more granular control over where dependencies can be rendered in your markup. MVC support should be fairly straight forward and we’ll include a demo project for this as well.

Well definitely be releasing a final version soon after the next Umbraco 4.1 release candidate is released (which will hopefully be fairly soon!)

Happy day! Any and all feedback, bug reports and patches are definitely appreciated!

Client Dependency Framework Beta Released

September 30, 2009 00:06
This post was imported from FARMCode.org which has been discontinued. These posts now exist here as an archive. They may contain broken links and images.
I’ve posted a new Beta release on CodePlex, you can get it here: http://clientdependency.codeplex.com/Release/ProjectReleases.aspx. On the releases tab includes a sample web site that has most of the functionality that you can do so please download it for a documentation reference.

Newest changes & additions

  • Namespace and codebase changes/steamlining
  • Proper versioning added
    • Versioning is done on a global basis in the config
    • Old versions are retained and can still be accessed from the Client Dependency URL that was previously used (if necessary)
    • Versioned composite files names are prefixed with the version number (i.e. version 2 files will be prefixed with '2_') so it's easy to figure out which files are old
    • The composite file map also reflects which composite file sets are under a specific version
  • Provider model extended to support 2 types of providers:
    • File Registration Providers
      • Still comes with 2 providers: page header provider and a lazy loading JavaScript client based provider
    • Composite File Providers:
      • Comes with the standard provider: CompositeFileProcessor
      • You can implement your own provider to customize the way that files are combined, compressed, minified, etc... if the standard provider isn't exactly what you are after
  • Forced providers! You can now force a dependency to use a particular provider. This can be useful if you want to ensure that a particular script or stylesheet is rendered on to the page differently. For example, you may want to ensure that a script is lazy loaded (using the lazy load provider) but the rest are rendered in the page header.
  • Utility methods added to the ClientDependencyLoader for more dynamic implementations
  • A test website is included in the release which doubles as documentation, it includes:
    • Standard page header provider example
    • Forced providers example
    • Lazy load provider example
    • Dynamically registering dependencies in your code behind
    • Registering dependencies with attributes and via aspx controls

Things //TODO:

I’ve finished off versioning so at least i can cross that off from the previous list. But there’s still more to do:

  • Implement functionality for jQuery CDN
    • This will be a new control/attribute to easily include jQuery in your project
    • You will have the option to select which CDN you want to use (Microsoft or Google), or you can supply an address (like your own CDN/web server)
    • Though this framework will be included in Umbraco 4.1, we’ll be leaving this functionality out of the Umbraco build as we realize that there are quite a few installs that operate behind a firewall that won’t have access to the CDN.
  • Implement skeleton for Microsoft AJAX 4 CDN
    • Again, this will be another new control/attribute to easily include Microsoft’s new brand of AJAX with their CDN solution
  • Add support for MVC
  • Support for JS/CSS Minification with options to disable per dependency
    • The reason this hasn’t been implemented yet is that I’ve found a lot of scripts/stylesheets break with minification so we need to be able to turn this on/off on a per file basis
  • Some more documentation/examples in the example web application