Apr 13, 2007

Recursive Find Control Code

  1 public T FindControl<T>(string id) where T : Control
2 {
3 return FindControl<T>(Page, id);
4 }
5
6 public static T FindControl<T>(Control startingControl, string id) where T : Control
7 {
8 // this is null by default
9 T found = default(T);
10
11 int controlCount = startingControl.Controls.Count;
12
13 if (controlCount > 0)
14 {
15 for (int i = 0; i < controlCount; i++)
16 {
17 Control activeControl = startingControl.Controls[i];
18 if (activeControl is T)
19 {
20 found = startingControl.Controls[i] as T;
21 if (string.Compare(id, found.ID, true) == 0) break;
22 else found = null;
23 }
24 else
25 {
26 found = FindControl<T>(activeControl, id);
27 if (found != null) break;
28 }
29 }
30 }
31 return found;
32 }

kick it on DotNetKicks.com

Apr 12, 2007

Enterprise Library 3.0

This release of Enterprise Library includes: Caching Application Block, Cryptography Application Block, Data Access Application Block, Exception Handling Application Block, Logging Application Block, Policy Injection Application Block, Security Application Block and Validation Application Block.

kick it on DotNetKicks.com

Apr 7, 2007

dynamically hookup (hard code in global.asax) HTTP Modules

one issue that has come up a few times is that the root site defines an HTTP module. The child virtual (an off the root virtual directory) when created by default inherits that module entry in web.config and usually fails because the module isn't available. Now it's easy to use a remove entry in your virtuals:

add the following to your web.config file
remove name="TopLevelModule"

and that can usually take care of it. However, if you have many sub-virtuals you need to touch this can get tedious.
So rather than fixing the Web.config in each subapplication I've removed the module definition in web.config and instead load the module via code. HttpModules hook up to the HttpApplication object of an ASP.NET application which is represented by your global.asax file in a Web project. HttpModules hook up to the events of this HttpApplication object, and since all a module really does is attach to the appropriate event handler in its Init() method there's no reason that you can't do this in code as well.
There's one little gotcha though: It has to be done at just the right time in the HttpApplication life cycle which is when the HttpApplication object initializes (multiple times, once for each instance of HttpApplication). The only method where this works correct is HttpApplication Init().
To hook up a module via code you can run code like the following instead of the HttpModule definition in web.config:

public class Global : System.Web.HttpApplication
{
public static xrnsToashxMappingModule Module = new xrnsToashxMappingModule();

public override void Init()
{
base.Init();
Module.Init(this);
}
}

All you do is override the HttpApplication's Init() method and then access the static instance's Init method. Init() of the module hooks up the event and off you go.
Note the use of HttpApplication Init; you might be tempted to use Application_Start, but that event is more like a static constructor that fires only once per Web application. Init() fires everytime a new application instance is initialized. Remember there are multiple HttpApplication instances executing side by side to handle simultaneous requests and each instance initializes separately.
Using web.config is the preferred way of hooking up handles usually though for sure. But there are situations where you might not want to allow the module hookup to be dynamic. For example, if you have an application where the module is crucial to operation, performs some security feature, or version check, you might not want to allow removal of the module - this way it's a lot more difficult to disconnect the module. If you have a packaged application it can also be nice to have the set up hard coded in this fashion - one less thing to screw up during installation or when users start poking around in configuration files

kick it on DotNetKicks.com

Mar 22, 2007

Encrypt/Decrypt connection strings in web.config

const string PROVIDER = "DataProtectionConfigurationProvider";
const string PROVIDER = "RSAProtectedConfigurationProvider";

Configuration ObjConfiguration =

WebConfigurationManager.OpenWebConfiguration(Request.ApplicationPath);

ConnectionStringsSection cnStrSettings = ObjConfiguration.ConnectionStrings;

//Encrypt the Connection Strings Section
cnStrSettings.SectionInformation.ProtectSection(PROVIDER);

//Decrypt the Connection Strings Section

if (cnStrSettings.SectionInformation.IsProtected)
{
cnStrSettings.SectionInformation.UnprotectSection();
}
ObjConfiguration.Save();

kick it on DotNetKicks.com

Mar 21, 2007

aspnet_regsql with SQLExpress database

Creating a new DB in VisualStudio.NET 2005 is as simple as "Select APP_DATA node -> Add New Item -> Sql Database" and wah-lah you have a new aspnet.mdf file located in your APP_DATA folder. However, when you run the tool ASPNET_REGSQL.exe in Wizard Mode (E.g. using the "-W" switch) there is no way to specify a SQLEXPRESS attached database - it only seems to support SQL Server 2005 (and earlier) database servers.

So, after several attempts, I finally figured-out the "right" way to do this:

aspnet_regsql -A all -C "Data Source=.\SQLEXPRESS;Integrated Security=True;User Instance=True" -d "C:\MyProject\APP_DATA\aspnetdb.mdf"

This will connect to the local SQLEXPRESS engine and attach the MDF file passed in the "-d" switch then create the appropriate objects in the DB.
================================================================

aspnet_regsql.exe -S server -d database -E -A all

While this concept still applies for SQL Server 2005 Express Edition, it can be a little harder to get the server and database names right. What database server is SQL Server Express installed on? And what's the database name for a .MDF file in the App_Data folder?

Assuming you are working on an ASP.NET application locally, the server name will be: localhost\SQLExpress

The database name is (and here's it can get a bit tricky), is the path to the MDF file when it was created. So, say that you have an ASP.NET application created in the classroom lab at C:\Labs\Website\App_Data\MessageBoard.mdf. The name of the database is C:\Labs\Website\App_Data\MessageBoard.mdf, meaning you could install the membership services from the command-line using:

aspnet_regsql.exe -S localhost\SQLExpress -d “C:\Labs\Website\App_Data\MessageBoard.mdf” -E -A all

Now, imagine that you zip up your files onto a USB keychain drive, go home, and copy your project files to C:\Home\Website. Now, if you wanted to create the services, you'd think you'd just type in:

aspnet_regsql.exe -S localhost\SQLExpress -d “C:\Home\Website\App_Data\MessageBoard.mdf” -E -A all

Ah, but the database name is C:\Labs\Website\App_Data\MessageBoard.mdf. Eep. So when you run the above command the database can't be found and cryptic error messages abound. Essentially, it can't find the database C:\Home\Website\App_Data\MessageBoard.mdf so it tries to create a database file in the default directory (%PROGRAM FILES%\Microsoft SQL Server\MSSQL.1\DATA) with the filename C:\Home\Website\App_Data\MessageBoard.mdf. This, of course, causes problems since that's not a valid filename. Ick.

So how do we fix this? There are a couple optios. The easiest is probably to download the (free) SQL Server 2005 Management Studio Express program and attach the database file. Then, from the Properties pane you can see the database name. You can then use this with aspnet_regsql.exe. (You could also rename the database at this point...)

If you want to be 3l33t you can use sqlcmd, attach the database (sp_attach_db) giving it a friendly name, which you can then use to run the aspnet_regsql.exe command line program against. Something like:

sqlcmd -S localhost\SQLExpress -Q “EXEC sp_attach_db 'Foobar', N'pathToDBfile'”

And then:

aspnet_regsql.exe -S localhost\SQLExpress -d Foobar -E -A all

kick it on DotNetKicks.com

Mar 13, 2007

Adding Asc/Desc Icon on Table Headers for Sorting

ListItemType itemType = (ListItemType)e.Item.ItemType;
// Don't bother too much for the footer, and separator items

if(itemType == ListItemType.Separator || itemType == ListItemType.Footer)
{
}
else if (itemType == ListItemType.Header)
{

TableCell TCell;
if(TCell != null)
{
// make a new label
Label sortSymbol = new Label();
sortSymbol.Font.Name = "Webdings";
sortSymbol.Font.Size = 10;

if(this.SortAscend == "Asc")
{
// Ascending
sortSymbol.Text = "5";
sortSymbol.ForeColor = System.Drawing.Color.Red;
theCell.Controls.AddAt(0, sortSymbol);
}
else
{
// Descending
sortSymbol.Text = "6";
sortSymbol.ForeColor = System.Drawing.Color.Blue;
theCell.Controls.Add(sortSymbol);
}

}

kick it on DotNetKicks.com

Mar 9, 2007

SPLIT function - TSQL

CREATE FUNCTION SPLIT (
@str_in VARCHAR(8000),
@separator VARCHAR(4) )
RETURNS @strtable TABLE (strval VARCHAR(8000))
AS
BEGIN

DECLARE
@Occurrences INT,
@Counter INT,
@tmpStr VARCHAR(8000)

SET @Counter = 0
IF SUBSTRING(@str_in,LEN(@str_in),1) <> @separator
SET @str_in = @str_in + @separator

SET @Occurrences = (DATALENGTH(REPLACE(@str_in,@separator,@separator+'#')) - DATALENGTH(@str_in))/ DATALENGTH(@separator)
SET @tmpStr = @str_in

WHILE @Counter <= @Occurrences
BEGIN
SET @Counter = @Counter + 1
INSERT INTO @strtable
VALUES ( SUBSTRING(@tmpStr,1,CHARINDEX(@separator,@tmpStr)-1))

SET @tmpStr = SUBSTRING(@tmpStr,CHARINDEX(@separator,@tmpStr)+1,8000)

IF DATALENGTH(@tmpStr) = 0
BREAK

END
RETURN
END

kick it on DotNetKicks.com

Mar 8, 2007

Encryption in SQL2005

I found this nice article on Encryption in SQL2005.

http://www.databasejournal.com/features/mssql/article.php/3461471 - Authentication
http://www.databasejournal.com/features/mssql/article.php/3481751 - Authorization

http://www.databasejournal.com/features/mssql/article.php/3483931 - Encryption

http://www.databasejournal.com/features/mssql/article.php/3488046 - Security

http://www.sqlservercentral.com/articles/SQL+Server+2005+-+Security/3058/

As a matter of fact we already have password hashing capability in SQL2000 itself, the PWDENCRYPT function is available to create a one-way hash.

In 2005 there are the EncryptByKey, EncryptByCert, EncryptByAsmKey and EncryptByPassPhrase methods that can be used for encrypting data.

For passwords the encryptByCert / EncryptByAsmKey or EncryptByPassPhrase can used which provide enough security.

EncryptByKey is symmetric key encryption which is usually combined with Certificates to encrypt the Symmetric key used for encypting large amounts data.

At the root level is the Service Master key which is automatically created during SQL2005 installation.

Then we have a Database Master Key which needs to be created using DDL statements for each Database on the SQL Server Instance. The database master key is created using the service master key along with an optional password.

  • create master key encryption by password = 'SecretPassword' ----this creates the DB master key
  • create certificate rbg_cert with subject = 'cert for rbg' ----creates a certificate using the DB Master key
  • create certificate rbg_cert encryption by password = 'secret' with subject = 'cert for rohit' ----- this creates a certificate using password as the Private Key instead of the DB master key.
  • create user rbg for certificate rbg_cert ----- creates the PROXY user
  • create login rbg_login from certificate rbg_cert --- creates a SQL login -- note logins are created in master DB, thus a rbg_cert should exist in master DB before you can run this command
Important system tables are
  1. sys.symmetric_keys - stores master and symmetric keys
  2. sys.databases --- list of all db's in the server
  3. sys.certificates -- lists certificates in a particular DB
  4. sysusers --- lists users in a particular DB, syslogins --- all logins

Then Certificates and Asymmetric keys are created using the database Master key and then we use the Encryption functions to encrypt and decrypt data/passwords. The EncryptByKey and EncryptByPassPhrase are symmetric encryption mechanisms which do not involve using the Database master key

kick it on DotNetKicks.com