Embedding files(resources) into a web control

I've written a number of web controls for ASP.net over the years, and one of the issues I had working with ASP.net 1.0 was how to sufficiently handle static files that ships with my controls (javascript, CSS, images etc).

When ASP.net 2.0 came along, it introduced the capability of embedding these static files into your controls' assembly, and allow you to reference them inside your control, inturn serving resources as axd files to the browser. (functionality extensively being ab... uhm used by Ajax.net)

In my demo we're going to write a very simple control that collapses content on a page, we've got two images and a piece of javascript that we're going to embed.

First off you will need to make sure that your static files are set as embedded resources in its build action property, like demonstrated in the image below.

Web Resources


One would think that thats all you'd need to do (with regards to embedding), but you still need to go to your AssemblyInfo.cs file and do some manual additions to it (perhaps someone can tell us, why this couldnt have been added automatically).

Your reference to the resources will look something like this:
 
[assembly: WebResource("DemoControl.images.down.jpg", "image/jpg")]
[assembly: WebResource("DemoControl.images.up.jpg", "image/jpg")]
[assembly: WebResource("DemoControl.javascripts.collapse.js", "text/javascript", PerformSubstitution = true)]
 

Notice the PerformSubstitution bool (if you scroll to the right) in our javascript mime type, this informs our compiler, that we've referenced some webresources inside our javascript file (like the script below), and it needs to resolve those entities for us.

 
function toggle(sender, e)
{
    var content = document.getElementById(e);
    switch(content.style.display)
    {
        case "none":	content.style.display = "block";
                        sender.src = '<%= WebResource("DemoControl.images.up.jpg")%>';
                        break;
        case "block":	content.style.display = "none";
                        sender.src = '<%= WebResource("DemoControl.images.down.jpg")%>';
                        break;							
    }
}
 

Using our embedded resources inside the server side code, we make use of the instantiated ClientScriptManager class in the Page property of the control. I wrote a small little method to retrieve resources similarly to what you see in the javascript code.
 
private string WebResource(string resourceName)
{
    return Page.ClientScript.GetWebResourceUrl(this.GetType(), resourceName);
}
 

You can download the source code to this demo here

Post/View comments
 

Encrypting your web.config

Ever wanted to protect certain sections of your web.config?

In .net 2.0 we're provided with a few standard protection providers, and the ability to write our own.
RSAProtectedConfigurationProvider : Default provider that uses RSA public key encryption to encrypt/decrypt sections.

DPAPIProtectedConfigurationProvider : Provider that uses the Windows Data Protection API (DPAPI) to encrypt/decrypt sections.

These providers can be invoked using a command-line tool, called aspnet_regiis (if you've got full access to your webserver). You will notice two commands, the first one calling the -pa attribute, this is your asp.net application identity, it gives your web application rights to the configuration store.

If you're unsure about which account you're application is using, you can always output the WindowsIdentity.GetCurrent().Name property somewhere, or simply check it out in IIS.

The second command using the -pe attribute does the actual encryption.

 
aspnet_regiis -pa "NetFrameworkConfigurationKey" "NT Authority\Network Service"
aspnet_regiis -pe "connectionStrings" -app "/WebApplication"
 

Or this can be done by writing a few simple lines of code (usually needed in a shared hosting environment, where you've got certain restrictions)

In the code sample you'll find below you simply need to pass the name of the section you wish to encrypt/decrypt, eg appSettings, connectionStrings

Note that not all sections can be encrypted in this manner, some examples are
 
<processModel>, <runtime>, <mscorlib>, <startup>, <system.runtime.remoting>,
                    <protectedData>, <satelliteassemblies>, <cryptographySettings>,
                    <cryptoNameMapping>, and <cryptoClasses>
 


Generally you would want to encrypt as little of the sections as possible (only ones containing sensitive settings), since there is some performance overhead (.net decrypts keys automatically in memory when needed, so that you dont need to decrypt a section whenever you need to use it in your application).

C#

 
// Namespaces you'll need
using System.Configuration;
using System.Web.Configuration;
 
private void EncryptSection(string sectionName)
{
    Configuration Config = WebConfigurationManager.OpenWebConfiguration(Request.ApplicationPath);
    SectionInformation Section = Config.GetSection(sectionName).SectionInformation;
 
    if (!Section.IsProtected)
    {
        Section.ProtectSection("RsaProtectedConfigurationProvider");
        Section.ForceSave = true;
        Config.Save(ConfigurationSaveMode.Modified);
    }
}
 
private void DecryptSection(string sectionName)
{
    Configuration Config = WebConfigurationManager.OpenWebConfiguration(Request.ApplicationPath);        
    SectionInformation Section = Config.GetSection(sectionName).SectionInformation;
 
    if (Section.IsProtected)
    {
        Section.UnprotectSection();
        Section.ForceSave = true;
        Config.Save(ConfigurationSaveMode.Modified);
    }
}
 

VB.net

 
'Namespaces you'll need
Imports System.Web.Configuration
 
Private Sub EncryptSection(ByVal sectionName As String)
    Dim Config As Configuration = WebConfigurationManager.OpenWebConfiguration(Request.ApplicationPath)
    Dim Section As SectionInformation = Config.GetSection(sectionName).SectionInformation
    If Not Section.IsProtected Then
        Section.ProtectSection("RsaProtectedConfigurationProvider")
        Section.ForceSave = True
        Config.Save(ConfigurationSaveMode.Modified)
    End If
End Sub
 
Private Sub DecryptSection(ByVal sectionName As String)
    Dim Config As Configuration = WebConfigurationManager.OpenWebConfiguration(Request.ApplicationPath)
    Dim Section As SectionInformation = Config.GetSection(sectionName).SectionInformation
    If Section.IsProtected Then
        Section.UnprotectSection()
        Section.ForceSave = True
        Config.Save(ConfigurationSaveMode.Modified)
    End If
End Sub
 


If everything worked out as planned, you'll end up with something similar to this in your web.config.

 
<appSettings configProtectionProvider="RsaProtectedConfigurationProvider">
    <EncryptedData Type="http://www.w3.org/2001/04/xmlenc#Element"
        xmlns="http://www.w3.org/2001/04/xmlenc#">
        <EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#tripledes-cbc" />
        <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
            <EncryptedKey xmlns="http://www.w3.org/2001/04/xmlenc#">
                <EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-1_5" />
                <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
                    <KeyName>Rsa Key</KeyName>
                </KeyInfo>
                <CipherData>
                    <CipherValue>GCe06wmlf/snuz4o7cyNpTJ+z8gBXSv89De8GkcWlNSiFzRFryxM83gUzJJzs/ADotejMnnp0IukSdXKiFzelsBmShm7mi/E8RhSZa4Pb3NXFhqHxHnP3tASMeV98dJfKTSwC3Ct1/zRYqUBN3XR3ndnYLYvcbqtBPdM+Kl/0yY=</CipherValue>
                </CipherData>
            </EncryptedKey>
        </KeyInfo>
        <CipherData>
            <CipherValue>nl7/3WpzEN/wHZgJwW35IQsWJjdvrkzvdO94MoPn/HK8LA94zV8yyYjJevvC+x6t5U4YOAqmSfc0pGA/FqPlbpYiuqjQ/HYMT3lRNAaHOk0=</CipherValue>
        </CipherData>
    </EncryptedData>
</appSettings>
 

Things can get a little bit more complicated once you find yourself in a webfarm for example, where you'd need to export your RSA keys (since the actual key used for decrypting the ciphers gets stored on the server) and deploy it to your farms etc - or perhaps rather simply do it programatically, using code similar to which is provided in this blog.

Post/View comments
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27