Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / XML

Embed only when you need

4.42/5 (5 votes)
17 Jul 2013CPOL2 min read 12.1K  
Create an embedded-resource-only DLL.

While continuing to play around, and merging the best of ASP.NET controls and jQuery based UI, I came across the decision to create an embedded-resource-only DLL.

This DLL should contain all my JavaScript files as embedded resource with proper mechanism to load them from everywhere in the whole application (including dependencies and duplicates).

It became obvious that with the amount of JavaScript I put into the DLL, those must be minified when deploying.

Easy... I added the 'GoogleClosureCompiler' Custom Tool to every file and voilĂ ! I had it!

So now I have in the same project both the plain and the minified version of the code, so I add some conditions into it to load the right one...

Something like this:

C#
using System;
using System.Web;
using System.Web.UI;

#if DEBUG
[assembly: WebResource( "jquery.js", "text/javascript" )]
[assembly: WebResource( "kendo.core.js", "text/javascript" )]
#else
[assembly: WebResource( "jquery.min.js", "text/javascript" )]
[assembly: WebResource( "kendo.core.min.js", "text/javascript" )]
#endif

namespace Utils
{
 public class JavaScript
 {
  private static int _IncludeID = 0;
  private static int _ScriptPath = 1;

  private static string _Script = 
    "<script javascript="javascript" src="\" text="text" type="\"></script>";

#if DEBUG
  private static string[ ] _jQuery = { "jQueryScriptInclude", "jquery.js" };
  private static string[ ] _Core = { "CoreScriptInclude", "kendo.core.js" };
#else
  private static string[ ] _jQuery = { "jQueryScriptInclude", "jquery.min.js" };
  private static string[ ] _Core = { "CoreScriptInclude", "kendo.core.min.js" };
#endif
  public static void Add ( Page Page, Type Type, string ID, string Name )
  {
   if ( !Page.ClientScript.IsStartupScriptRegistered( Type, ID ) )
   {
    Page.ClientScript.RegisterStartupScript( 
     Type, 
     ID, 
     string.Format( 
      _Script, 
      HttpUtility.HtmlEncode( Page.ClientScript.GetWebResourceUrl( Type, Name ) ) 
     ), 
     false 
    );
   }
  }
 }
}

Look good, isn't it? Event better! It works! Loads the right JavaScript file.

So what's wrong?

Both the plain and the minified files were embedded into both the debug and the release version of the DLL!

In fact, when I started to think about it, found that that was expected. Nobody told the compiler that those files should be included according to some condition... After some search I found that  - apparently - there is no way to tell that!

There is. Not nice, not comfortable, not UI, but there is.

You have to edit the project file. Move files to different ItemGroup and add the proper condition.

Originally, Visual Studio creates the ItemGroup like this:

XML
<itemgroup>
 <embeddedresource include="js\jquery.js">
  <generator>GoogleClosureCompiler</generator>
  <lastgenoutput>jquery.min.js</lastgenoutput>
 </embeddedresource>
 <embeddedresource include="js\jquery.min.js">
  <autogen>True</autogen>
  <designtime>True</designtime>
  <dependentupon>jquery.js</dependentupon>
 </embeddedresource>
 <embeddedresource include="js\kendo.core.js">
  <generator>GoogleClosureCompiler</generator>
  <lastgenoutput>kendo.core.min.js</lastgenoutput>
 </embeddedresource>
 <embeddedresource include="js\kendo.core.min.js">
  <autogen>True</autogen>
  <designtime>True</designtime>
  <dependentupon>kendo.core.js</dependentupon>
 </embeddedresource>
</itemgroup>

All you have to do is separate the plain and the minified files into different ItemGroups, than add some condition, and done...

XML
<itemgroup condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
 <embeddedresource include="js\jquery.js">
  <generator>GoogleClosureCompiler</generator>
  <lastgenoutput>jquery.min.js</lastgenoutput>
 </embeddedresource>
 <embeddedresource include="js\kendo.core.js">
  <generator>GoogleClosureCompiler</generator>
  <lastgenoutput>kendo.core.min.js</lastgenoutput>
 </embeddedresource>
</itemgroup>
<itemgroup condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
 <embeddedresource include="js\jquery.min.js">
  <autogen>True</autogen>
  <designtime>True</designtime>
  <dependentupon>jquery.js</dependentupon>
 </embeddedresource>
 <embeddedresource include="js\kendo.core.min.js">
  <autogen>True</autogen>
  <designtime>True</designtime>
  <dependentupon>kendo.core.js</dependentupon>
 </embeddedresource>
</itemgroup>

For sure it's not too elegant to do it by hand, but there are good things too.

Visual Studio will keep the ItemGroup definitions you created, as long you don't remove the original file. And by the amount of extension we have, for sure someone already working (done?) to add one, that handles this little thing...

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)