:::: MENU ::::

Friday, May 22, 2009

I’ve had several people ask me lately about encrypting data in .NET.  I’m not sure why the question has come up a lot recently, but it’s definitely something good to know if you have any sensitive data that needs to be stored.  .NET provides two main encryption roads that you can travel down including symmetric encryption and asymmetric encryption.  Symmetric encryption relies upon a private key to encrypt and decrypt while asymmetric encryption relies upon a public key to encrypt and a private key to decrypt.  Symmetric encryption provides the best performance while asymmetric encryption provides the best security in situations where keys need to be exchanged between different parties.  If you need to encrypt and decrypt data directly within an application symmetric encryption works fine as long as other prying eyes can’t get their hands on the private key (or your source code). 

I have a fairly straightforward encryption/decryption class named Encryptor that I use when I need to perform symmetric encryption in my web applications.  The class relies upon a symmetric algorithm called Rijndael that can be used to encrypt and decrypt data. 

While I’m not going to provide a detailed discussion of what the class does I’m happy to post it here for anyone who needs that type of functionality.  Keep in mind that you’ll need to update the password and salt values to whatever you need to use in your applications and should consider dynamically grabbing the password from a secured data store as opposed to hard-coding it in the source code (especially if you’ll be shipping the assembly…people can disassemble it using tools like Reflector).  The salt acts as a type of junk data that is used in constructing the password and can also be used to pad encrypted data with bogus bytes so that hackers don’t know which part of the data is valid and which part is junk.

using System;

using System.IO;

using System.Security.Cryptography;

 

namespace YourApp.Model.Helpers {

   

    internal class Encryptor

    {

        internal static string Decrypt(string cipherText)

        {

            byte[] cipherBytes = Convert.FromBase64String(cipherText);

            Rfc2898DeriveBytes pdb = new Rfc2898DeriveBytes(_Pwd, _Salt);

            byte[] decryptedData = Decrypt(cipherBytes, pdb.GetBytes(32), pdb.GetBytes(16));

            return System.Text.Encoding.Unicode.GetString(decryptedData);

        }

 

        private static byte[] Decrypt(byte[] cipherData, byte[] Key, byte[] IV) {

            MemoryStream ms = new MemoryStream();

            CryptoStream cs = null;

            try {

                Rijndael alg = Rijndael.Create();

                alg.Key = Key;

                alg.IV = IV;

                cs = new CryptoStream(ms, alg.CreateDecryptor(), CryptoStreamMode.Write);

                cs.Write(cipherData, 0, cipherData.Length);

                cs.FlushFinalBlock();

                return ms.ToArray();

            }

            catch {

                return null;

            }

            finally {

                cs.Close();

            }

        }

 

        public static string Encrypt(string clearText)

        {

            byte[] clearBytes = System.Text.Encoding.Unicode.GetBytes(clearText);

            Rfc2898DeriveBytes pdb = new Rfc2898DeriveBytes(_Pwd, _Salt);

            byte[] encryptedData = Encrypt(clearBytes, pdb.GetBytes(32), pdb.GetBytes(16));

            return Convert.ToBase64String(encryptedData);

        }

 

 

        private static byte[] Encrypt(byte[] clearData, byte[] Key, byte[] IV)

        {

            MemoryStream ms = new MemoryStream();

            CryptoStream cs = null;

            try

            {

                Rijndael alg = Rijndael.Create();

                alg.Key = Key;

                alg.IV = IV;

                cs = new CryptoStream(ms, alg.CreateEncryptor(), CryptoStreamMode.Write);

                cs.Write(clearData, 0, clearData.Length);

                cs.FlushFinalBlock();

                return ms.ToArray();

            }

            catch

            {

                return null;

            }

            finally

            {

                cs.Close();

            }

        }

 

        static string _Pwd = "Your_Password_Goes_Here"; //Be careful storing this in code unless it’s secured and not distributed

        static byte[] _Salt = new byte[] {0x45, 0xF1, 0x61, 0x6e, 0x20, 0x00,  0x65, 0x64, 0x76, 0x65, 0x64, 0x03, 0x76};

    }

}

 

To use the class to encrypt data (and get back a Base64 encoded string) the following code can be written:

string creditCardNumber = Encryptor.Encrypt(cust.CreditCardNumber);

 

Wednesday, May 20, 2009

.Net Framework 4.0 provides us with a new class called Lazy<T>. As documentation sais then Lazy<T> provides support for several common patterns of lazy initialization, including the ability to initialize value types and to use null values. So it is construct that helps us implement lazy loading.

I wrote a little code example on Visual Studio 2010 that illustrates how to use Lazy<T>.


static void Main(string[] args)
{
    var lazyString = new Lazy<string>(
        () =>
        {
            // Here you can do some complex processing
            // and then return a value.
    
Console.Write("Inside lazy loader");
            return "Lazy loading!";
        });
    Console.Write("Is value created: ");
    Console.WriteLine(lazyString.IsValueCreated);
 
    Console.Write("Value: ");
    Console.WriteLine(lazyString.Value);

   
Console.Write("Value again: ");
    Console.WriteLine(lazyString.Value);

   
Console.Write("Is value created: ");
    Console.WriteLine(lazyString.IsValueCreated);
 
    Console.WriteLine("Press any key to continue ...");
    Console.ReadLine();
}

When we run this code we will get the following output.

    Is value created: False
    Inside lazy loader
    Value: Lazy loading!
    Value again: Lazy loading!
    Is value created: True
    Press any key to continue …

The value of our Lazy<string> will be initialized when we first ask it and then it will be stored for subsequent calls. Notice that there is one Console.WriteLine inside lazy initialization function and if you look at output you can see that this function is run only once. So only thing you have to do is to write initialization function and Lazy<T> makes all the work automatically.

I found also one example that may give you better explanations about internals of Lazy<T>: Lazy Computation in C#.

 

Tuesday, May 19, 2009

Unit Testing ASP.NET? ASP.NET unit testing has never been this easy.

Typemock is launching a new product for ASP.NET developers – the ASP.NET Bundle - and for the launch will be giving out FREE licenses to bloggers and their readers.

The ASP.NET Bundle is the ultimate ASP.NET unit testing solution, and offers both Typemock Isolator, a unit test tool and Ivonna, the Isolator add-on for ASP.NET unit testing, for a bargain price.

Typemock Isolator is a leading .NET unit testing tool (C# and VB.NET) for many ‘hard to test’ technologies such as SharePoint, ASP.NET, MVC, WCF, WPF, Silverlight and more. Note that for unit testing Silverlight there is an open source Isolator add-on called SilverUnit.

The first 60 bloggers who will blog this text in their blog and tell us about it, will get a Free Isolator ASP.NET Bundle license (Typemock Isolator + Ivonna). If you post this in an ASP.NET dedicated blog, you'll get a license automatically (even if more than 60 submit) during the first week of this announcement.

Also 8 bloggers will get an additional 2 licenses (each) to give away to their readers / friends.

Go ahead, click the following link for more information on how to get your free license.

Unit Testing ASP.NET? ASP.NET unit testing has never been this easy.

Typemock is launching a new product for ASP.NET developers – the ASP.NET Bundle - and for the launch will be giving out FREE licenses to bloggers and their readers.

The ASP.NET Bundle is the ultimate ASP.NET unit testing solution, and offers both Typemock Isolator, a unit test tool and Ivonna, the Isolator add-on for ASP.NET unit testing, for a bargain price.

Typemock Isolator is a leading .NET unit testing tool (C# and VB.NET) for many ‘hard to test’ technologies such as SharePoint, ASP.NET, MVC, WCF, WPF, Silverlight and more. Note that for unit testing Silverlight there is an open source Isolator add-on called SilverUnit.

The first 60 bloggers who will blog this text in their blog and tell us about it, will get a Free Isolator ASP.NET Bundle license (Typemock Isolator + Ivonna). If you post this in an ASP.NET dedicated blog, you'll get a license automatically (even if more than 60 submit) during the first week of this announcement.

Also 8 bloggers will get an additional 2 licenses (each) to give away to their readers / friends.

Go ahead, click the following link for more information on how to get your free license.

Friday, May 8, 2009

Sometimes you have to load jQuery, but you don’t know if it has already been referenced somewhere else in the website. 

This tends to happen if you have a custom web control, delivered in an assembly, that relies on jQuery.

This code has been ripped out of my application, and may have a typo or three, but it gives you the general idea.

 

var jQueryScriptOutputted = false;

function initJQuery() {

   

    //if the jQuery object isn't available

    if (typeof(jQuery) == 'undefined') {

   

   

        if (! jQueryScriptOutputted) {

            //only output the script once..

            jQueryScriptOutputted = true;

           

            //output the script (load it from google api)

            document.write("<scr" + "ipt type=\"text/javascript\" src=\"http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js\"></scr" + "ipt>");

        }

        setTimeout("initJQuery()", 50);

    } else {

                        

        $(function() { 

            //do anything that needs to be done on document.ready

        });

    }

           

}

initJQuery();

 

Friday, May 1, 2009

I'm editing in a link to Adam Machanic's blog on this. In the comments on this topic here you will see there are imperfections found in my methods. Reading Adam's blog shows this in more detail.
http://sqlblog.com/blogs/adam_machanic/archive/2009/04/26/faster-more-scalable-sqlclr-string-splitting.aspx

Thanks Adam!

I wrote this short CLR split function awhile back based on a few other articles I read when 2005 was released. I decided to play with it today and see if I could put it with the SQL split solutions.

Let's get the basics out of the way on SQL CLR. SQL CLR is only good once it's in memory. The CLR function split basically won over the T-SQL split functions after it was cached. This is a critical variable to consider when thinking CLR vs. T-SQL options on coding. If you are doing heavy manipulation of data and heavy math, CLR will typically help you, but you should be very careful with CLR and memory management. You can run your server resources out and literally stop functionality. I highly recommend reading MrDenny's blog on CLR here. Denny touches on important topics on when to use CLR and why you shouldn't. After that, look into how SQL Server 32bit, 32bit with AWE and 64bit versions handle memory. Each handles memory differently. AWE enalbed instances will probably be the one that will cause you more headaches then the rest. I had severe memory issues a few months ago on a production database server that forced restarts nightly until I fixed the problem. I analyzed the problem and it came to be several factors that caused it and SQL CLR memory was one of those factors. Here is my chance to thank mrdenny and ptheriault again for the assisatnce on that strange problem.

I went out and google'd "fast split function t-sql". Found a few and tested them against the CLR split method. I found a dozen or so split functions that looked good. I still went with a numbers table one after testing them out next to each other. Here is one of the functions I used. If you have a better one, post it in the comments and I can edit the post.

tsqlLine number On/Off | Show/Hide | Select all

  1. ALTER FUNCTION [dbo].[Split] (
  2. @List VARCHAR(7998), --The delimited list
  3. @Del CHAR(1) = ',' --The delimiter
  4. )
  5. RETURNS @T TABLE (Item VARCHAR(7998))
  6. AS
  7. BEGIN
  8. DECLARE @WrappedList VARCHAR(8000), @MaxItems INT
  9. SELECT @WrappedList = @Del + @List + @Del, @MaxItems = LEN(@List)
  10.  
  11. INSERT INTO @T (Item)
  12. SELECT SUBSTRING(@WrappedList, Number + 1, CHARINDEX(@Del, @WrappedList, Number + 1) - Number - 1)
  13. FROM dbo.Numbers n
  14. WHERE n.Number <= LEN(@WrappedList) - 1
  15. AND SUBSTRING(@WrappedList, n.Number, 1) = @Del
  16.  
  17. RETURN
  18. END

Code is hidden, SHOW

Here is my CLR split

csharpLine number On/Off | Show/Hide | Select all

  1. using System;
  2. using System.Data;
  3. using System.Collections;
  4. using System.Data.SqlClient;
  5. using System.Data.SqlTypes;
  6. using Microsoft.SqlServer.Server;
  7.  
  8. public partial class UserDefinedFunctions
  9. {
  10.     [SqlFunction(Name = "CLR_Split",
  11.     FillRowMethodName = "FillRow",
  12.     TableDefinition = "id nvarchar(10)")]
  13.  
  14.     public static IEnumerable SqlArray(SqlString str, SqlChars delimiter)
  15.     {
  16.         if (delimiter.Length == 0)
  17.             return new string[1] { str.Value };
  18.         return str.Value.Split(delimiter[0]);
  19.     }
  20.  
  21.     public static void FillRow(object row, out SqlString str)
  22.     {
  23.         str = new SqlString((string)row);
  24.     }
  25. };

Code is hidden, SHOW

I loaded a text file with a huge amount of delimited data to really get a gauge on time this would take. The string is basically, "data%data%data%data%data" and on. Around 600 indexes. I restarted my local instance of SQL Server 2005 that I did these on to ensure you can see CLR before cache and after.

More

Wednesday, April 29, 2009

Just thought of sharing a some useful IIS App pool functions I wrote long back in C#.  Requirement was to play around with IIS v5.0/6.0 and do all settings dynamically -

Note : You must have administrator priveledge to perform all IIS actions.

Namespace Required

using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.DirectoryServices;
using System.DirectoryServices.ActiveDirectory;
using System.IO;
using System.Diagnostics;
using IISOle; // IISOle requires a reference to the Active Directory Services.
using System.Reflection;
using System.Configuration;
using System.Text.RegularExpressions;

Functions

public static bool RecycleAppPool(string serverName, string adminUsername, string adminPassword, string appPoolName)
        {
            DirectoryEntry appPools = new DirectoryEntry("IIS://" + serverName + "/w3svc/apppools", adminUsername, adminPassword);
            bool status = false;
            foreach (DirectoryEntry AppPool in appPools.Children)
            {
                if (appPoolName.Equals(AppPool.Name, StringComparison.OrdinalIgnoreCase))
                {
                    AppPool.Invoke("Recycle", null);
                    status = true;
                    break;
                }
            }
            appPools = null;
            return status;
        }

 

/// <summary>
        /// Creates AppPool
        /// </summary>
        /// <param name="metabasePath"></param>
        /// <param name="appPoolName"></param>
        public static bool CreateAppPool(string metabasePath, string appPoolName)
        {
            //  metabasePath is of the form "IIS://<servername>/W3SVC/AppPools"
            //    for example "IIS://localhost/W3SVC/AppPools"
            //  appPoolName is of the form "<name>", for example, "MyAppPool"
            DirectoryEntry newpool, apppools;
            try
            {
                if (metabasePath.EndsWith("/W3SVC/AppPools"))
                {
                    apppools = new DirectoryEntry(metabasePath);
                    newpool = apppools.Children.Add(appPoolName, "IIsApplicationPool");
                    newpool.CommitChanges();
                    newpool = null;
                    apppools = null;
                    return true;
                }
                else
                    throw new Exception(" Failed in CreateAppPool; application pools can only be created in the */W3SVC/AppPools node.");               
            }
            catch (Exception ex)
            {
                throw new Exception(string.Format("Failed in CreateAppPool with the following exception: \n{0}", ex.Message));
            }
            finally
            {
                newpool = null;
                apppools = null;
            }
        }

        /// <summary>
        /// Assigns AppPool to Virtual Directory
        /// </summary>
        /// <param name="metabasePath"></param>
        /// <param name="appPoolName"></param>
        public static bool AssignVDirToAppPool(string metabasePath, string appPoolName)
        {
            //  metabasePath is of the form "IIS://<servername>/W3SVC/<siteID>/Root[/<vDir>]"
            //    for example "IIS://localhost/W3SVC/1/Root/MyVDir"
            //  appPoolName is of the form "<name>", for example, "MyAppPool"
            //Console.WriteLine("\nAssigning application {0} to the application pool named {1}:", metabasePath, appPoolName);

            DirectoryEntry vDir = new DirectoryEntry(metabasePath);
            string className = vDir.SchemaClassName.ToString();
            if (className.EndsWith("VirtualDir"))
            {
                object[] param = { 0, appPoolName, true };
                vDir.Invoke("AppCreate3", param);
                vDir.Properties["AppIsolated"][0] = "2";
                vDir = null;
                return true;
            }
            else
                throw new Exception(" Failed in AssignVDirToAppPool; only virtual directories can be assigned to application pools");
        }

 

  /// <summary>
        /// Delete AppPool
        /// </summary>
        /// <param name="metabasePath"></param>
        /// <param name="appPoolName"></param>
        public static bool DeleteAppPool(string serverName, string adminUsername, string adminPassword, string appPoolName)
        {
            //  metabasePath is of the form "IIS://<servername>/W3SVC/AppPools"
            //  for example "IIS://localhost/W3SVC/AppPools"
            //  appPoolName is of the form "<name>", for example, "MyAppPool"

            DirectoryEntry appPools = new DirectoryEntry("IIS://" + serverName + "/w3svc/apppools", adminUsername, adminPassword);
            bool status = false;
            foreach (DirectoryEntry AppPool in appPools.Children)
            {
                if (appPoolName.Equals(AppPool.Name, StringComparison.OrdinalIgnoreCase))
                {
                    AppPool.DeleteTree();
                    status = true;
                    break;
                }
            }
            appPools = null;
            return status;
        }

Hope you folks find it useful. If you need any other help related to IIS, just post me your requirement.

        public static void AddHostHeader(string serverName, string adminUsername, string adminPassword, string websiteName, string hostHeader)

        {

            string siteID = GetSiteID(serverName, adminUsername, adminPassword, websiteName);

            DirectoryEntry root = new DirectoryEntry("IIS://" + serverName + "/W3SVC/" + siteID, adminUsername, adminPassword);

            PropertyValueCollection serverBindings = root.Properties["ServerBindings"];

            //Add the new binding        

            serverBindings.Add(hostHeader);

            //Create an object array and copy the content to this array     

            Object[] newList = new Object[serverBindings.Count];

            serverBindings.CopyTo(newList, 0);

            //Write to metabase

            root.Properties["ServerBindings"].Value = newList;

            root.CommitChanges();

            root.Close();

            root.Dispose();

        }

 

        public static string GetSiteID(string serverName, string adminUsername, string adminPassword, string websiteName)

        {

            DirectoryEntry root = new DirectoryEntry("IIS://" + serverName + "/W3SVC", adminUsername, adminPassword);

            string siteID = "0";

            foreach (DirectoryEntry e in root.Children)

            {

                if ((e.SchemaClassName == "IIsWebServer") && (e.Properties["ServerComment"][0].ToString() == websiteName))

                {

                    siteID = e.Name;

                }

            }

            root.Close();

            root.Dispose();

            return siteID;

        }

When deploying ASP.NET applications to a production environment, you will most likely want to set the compilation debug attribute in web.config to false, as having debug set to true has some downsides:

  • Compilation takes longer as batch optimizations are disabled
  • Scripts and images from WebResources.axd will not be cached on the client
  • Larger memory footprint
  • Code will execute slower because of enabled debug paths

To force debug = false in all ASP.NET applications on the server, you can change the retail switch in machine.config:

<configuration>

    <system.web>

        <deployment retail="true"/>

    </system.web>

</configuration>

 

Tuesday, April 21, 2009

The ExpressionBuilder is still unknown to a lot of developers that haven’t experienced the sadistic pleasure of localizing a web application. It was introduce in ASP .NET 2.0 and allows you to bind values to control properties using declarative expressions.

I learnt about the ExpressionBuilder when I was doing some research on localization best practices in .NET. The recommendation is to use the specialized ResourceExpressionBuilder that creates code to retrieve resource values when the page is executed.

The ResourceExpressionBuilder is great for localization but what if we want to bind a control’s property to something else? Maybe a value in the Web.config’s AppSetting section. You may have tried something like this: 

<asp:TextBox
id="foo"
runat="server"
text="<%=ConfigurationManager.AppSettings["FooText"] %>"/>

Don’t be embarrassed. We’ve all done it at least once, and we’ve all been greeted with:

Parser Error Message: Server tags cannot contain <% ... %> constructs.

Thankfully there is an ExpressionBuilder that can help. the AppSettingsExpressionBuilder provides access to values in the AppSettings section of the Web.config and we use it as follows:

<asp:TextBox
id="foo"
runat="server"
text="<%$ AppSettings: FooText %>"/>

The ResourceExpressionBuilder and the AppSettingsExpressionBuilder are both derived from the ExpressionBuilder base class. That means we can create our own but I'll leave that topic for another day.

Keep in mind that the ExpressionBuilder only works when it is assigned to the property of a control. So you won’t be able to use it, for example, to pass values to a JavaScript constructor.