.Net, ASP.Net, C#, VB.net, SQL Server, Xml, CSS, Design Patterns related tips, tricks, code snippets, articles, links, thoughts, etc. from Binu & Subi Thayamkery.

Binu Thayamkery is a seasoned software architect with more than 13 years of experience in developing enterprise grade connected systems using Microsoft Technologies. In his current position as a lead consultant-solution architect with Prudential Financial, he is working on architecture of next generation investment reporting framework using .net 3.5/WCF/AJAX, etc. He holds a Masters Degree in Computer Science from Colorado State University. Subi Thayamkery is an experienced software developer with more than 8 years of developing various application software systems ranging from workflow automation systems to compliance management tools. She currently works as a technology consultant for Prudential Financial where she helps develop a new system for corportate governance department. She holds an Electrical Engineering degree from New Jersey Institute of Technology.

Tuesday, December 27, 2005

Listing Files in a Directory using .Net

Level: Beginner

DirectoryInfo class is useful for creating, moving, and enumerating through directories and subdirectories.

for example, you can make a new directory like this,

DirectoryInfo di = new DirectoryInfo(@"c:\TestDir");
if (!di.Exists)
di.Create();


FileInfo class provides instance methods for the creation, copying, deletion, moving, and opening of files, and aids in the creation of FileStream objects.

Here is a simple code snippet to list all files in a given directory (example takes a directory path as input and returns an array list of files)

private ArrayList GetFileList(string inputDir)
{
ArrayList fileList = new ArrayList();
DirectoryInfo di = new DirectoryInfo(inputDir);
//GetFiles method accepts filter patterns like "*.xml"
FileInfo[] fArray = di.GetFiles("*.*");

foreach(FileInfo fi in fArray)
{
fileList.Add(fi);
}
return (fileList);

}

Friday, December 23, 2005

Random Image Rotator with CSS and ASP.Net

Level: Intermediate

For my header image I have defined something in CSS like this,
#pic { BACKGROUND: url(pic.jpg) repeat-x; }.
This works fine for a static image. If you want to rotate your image, you will need to dynamically grab that image to get there. ( Google this need, and you will find a lot of pages with PHP solution ). Here is what you do in .Net to rotate images with CSS !

Your CSS file will change to reflect the ASPX page now serving the images,

#pic { BACKGROUND: url(http://localhost/imgPick/pick.aspx) repeat-x; }

And here is the code that goes to page load of pick.aspx

private void Page_Load(object sender, System.EventArgs e)
{
string imagePath = GetRandomImageFileName();
//Open the image file
System.Drawing.Image image = System.Drawing.Image.FromFile(imagePath, true);
Graphics graphic = Graphics.FromImage(image);


//To draw some text on that image !
Font drawFont = new Font("Arial", 16);
SolidBrush drawBrush = new SolidBrush(Color.Black);
float x = 150.0F;
float y = 50.0F;
graphic.DrawString("dotNetCouple :)", drawFont, drawBrush,x,y);

//Switch page output type to "jpg"
HttpContext.Current.Response.ContentType = "image/jpg";
MemoryStream stream = new MemoryStream();
image.Save(stream, ImageFormat.Jpeg );
//Write the image from memory to the response stream
stream.WriteTo(HttpContext.Current.Response.OutputStream);


}

private string GetRandomImageFileName()
{
Random random = new Random();
int arrIndex = random.Next(0, 2);
//I have an array of 3 images here!
//change this routine to your suite your needs !
string[] imgNames = new string[]
{
@"c:\binu\html\css\pic.jpg",
@"c:\binu\html\css\pic1.jpg",
@"c:\binu\html\css\pic2.jpg"
};
return (imgNames[arrIndex]);

}

and your HTML could look like this,


Some Text, This text will still be shown if there is no image served !



put all these together, and there you have it, a CSS based image rotator.

Tuesday, December 20, 2005

HTTP 502 Error while downloading exe from website

Level: Beginner

Have you ever got HTTP 502 error or CGI error while trying to download an exe from an IIS 5.0/ASP website ? If yes, it is worth checking "Execute Permissions" on that virtual directory. If the permissiona are set to "Script Only" then the executable files are treated like static HTML files and when try to access with a link like this, download of the file will start. If this is set to "Scripts and Executables" it will think that you are trying to execute the exe and will end up in HTTP 502 or CGI error in IIS!

Monday, December 19, 2005

Validating XML using XMLValidatingReader

Level: Beginner

You can use XmlValidatingReader class to validate an cml file against an XSD schema, Here is the code snippet to do it,



XmlSchemaCollection schemaCol = new XmlSchemaCollection();
schemaCol.Add("",schemaFile);
XmlTextReader textReader = null;
XmlValidatingReader vReader = null;
try
{
textReader = new XmlTextReader(xmlFile);
// create a validating reader.
vReader = new XmlValidatingReader(textReader);
// validate using the schemas stored in the schema collection.
vReader.Schemas.Add (schemaCol);
// set the validation event handler
vReader.ValidationEventHandler += new ValidationEventHandler(ValidationCallBack);
// read and validate the XML data.
while (vReader.Read()){}
}
catch (Exception ex)
{
return (false);
}
finally
{
// close the readers

vReader.Close ();
textReader.Close ();
}


And your Event Handler to handle the validation callbacks,

private void ValidationCallBack (object sender, ValidationEventArgs args)
{
this._xmlFeedValid = false;
}



Access Denied Error with MSXML 4.0 SP2

Level: Advanced

If you have recently updated your MSXML 4.0 with SP2 and started getting an "Access Denied" error, then read on...
According to this Microsoft article, Security in the implementation of the MSXML 4.0 SP2 ServerXmlHttp object has been enhanced to check the Internet Explorer security policy setting for submitting non-encrypted form data.

Follow these steps to configure IE Security,


1. Click Start, click Run, type mmc, and then press ENTER.
2. On the File or the Action menu, click Add/Remove Snap-in.
3. In the Add/Remove Snap-in dialog box, click Add.
4. On the Standalone tab, click Add. In the Available Standalone Snap-in dialog box, click Group Policy , and then click Add. The Group Policy Wizard appears.
5. In the Group Policy Wizard, Click Finish
6. Close the Add Standalone Snap-in window by clicking the Close button
7. Click OK in the Add/Remove Snap-in dialog box.
8. Under User Configuration, expand Windows Settings, expand Internet Explorer Maintenance, and then click Security.
9. In the right pane, double-click Security Zones and Content Ratings.
10. Under Security Zones and Privacy, click Import the current security zones and privacy settings, and then click Modify Settings.
11. Select the zone that you would like to modify, and click Custom Level
12. Modify the settings to enable the Submit nonencrypted form data option by selecting the enable radio button for that option. If it is already enabled, then just click the OK button. The zone where the setting should be enabled is determined by the zone where the target URL of the POST operation is classified. For example, when you post to an Internet URL, you must enable this option for the internet zone.
13. Restart the process that is running ServerXMLHTTP. To do this, you may have to restart your computer.

Friday, December 16, 2005

Creating DataSet from XML and XSD

Level: Beginner-Intermediate

If you want to read your XML file into a DataSet, you could use the ReadXml method of the DataSet. You can read the XSD for the same XML file using ReadXMLSchema method. Here is how to use these methods,


string doc = @"c:\test.xml";
string docSchema = @"c:\test.xsd";
XmlDataDocument myXmlDataDocument = new XmlDataDocument ;


We will use a StreamReader to read the schema file,

StreamReader reader = new StreamReader(docSchema);
//this will read the schema to DataSet
myXmlDataDocument.DataSet.ReadXmlSchema(reader);


[do not forget to close the StreammReader in your actual code]

//this will read the XML
myXmlDataDocument.Load(document);


DataSet also has a ReadXML method you can use to read the XML. This method can be used instead of XMLDataDocument's Load method. ReadXML method takes a second parameter that specifies XMLReadMode [enumeration].
Read more about this on MSDN:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfsystemdatadatasetclassreadxmltopic.asp

All these methods works well with simple XML and XSD. In my experience, if you have many complex types and relations in XML/XSD, ReadXMLSchema method gives undefined error! on some types [native and sometimes derived!] and subsequently Load fails!!

How to share transaction between classic ADO and ADO.Net

Level: Advanced

If you want to share a transaction between your ADO connection and your ADO.net connection, you can use bound connections. Now you might ask why would you ever want to do that, I was faced with a scenario where i was calling my .net modules from my existing VB code using COM interop. (I am planning to discuss COM Interop sometime soon!). So in my case VB/ADO was starting a transaction, then it calls a .net module to do something where I needed the data that was part of the VB/ADO transaction. So only way for me toto get to that data was by enlisting my ADO.Net calls in the same transaction.
Now to the point, we need to make 2 steps,
Step 1: Get a unique identifier for my ADO transaction using sp_getbindtoken
Step 2: Enlist my ADO.net transaction using that identifier and sp_bindsession
Note: You will need to pass the transaction identifier to your .net code

Example: VB Code:
Set cmd = New ADODB.Commands
SPName = "sp_getbindtoken"
cmd.CommandText = sSPName

cmd.ActiveConnection = oDBConnection
cmd.CommandType = adCmdStoredProc
cmd.Parameters.Append cmd.CreateParameter("@out_token", adVarChar, adParamOutput, 255)
cmd.Execute
transactionID = cmd.Parameters(0).Value

Pass this transactionID to .net code

In .Net side, (C#)

string spName = "EXEC sp_bindsession '" + sToken + "'";
SqlCommand cmd = new SqlCommand("EXEC sp_bindsession '" + sToken + "'",sqlConnection); cmd.CommandType = CommandType.Text;
try {
sqlConnection.Open();

cmd.ExecuteNonQuery();
cmd.Connection = null; }
catch (SqlException ex) { throw (ex); }

IMPORTANT!!!
When you are executing sp_bindsession, SQL Server somehow expects the T-SQL statement to be executed using the provider.If you user any other formats to execute this, it will not work!!!

Once you have completed these 2 steps, your ADO.Net transaction is enlisted in the parent ADO transaction and you will be able to see the data that was changes/inserted by the ADO within the ADO.Net process.

If you are using SqlHelper (Microsoft Data Access Application Block), you will have to modify the SqlHelper class to take this new transaction identifier as one of the parameter to SqlHelper methods and call sp_bindsession where ever you are using a transaction.