Thursday, March 17, 2005

URL Rewriting

You can redirect users to a URL by using URL Rewriting in ASP.NET. To accomplish this, you can use a HttpModule that Scott Mitchell wrote to perform the redirects based on mapping rules configured in web.config for the web application. His article on this is here: URL Rewriting with ASP.NET

One thing that you might want to do is to allow users to navigate your site by using directory-only URL's like this: http://localhost/Products, which should redirect them to the http://localhost/Products/inventory.aspx page. IIS processes requests for directory-only URLs by first determining if the directory exists, and if it does, it then checks to see if the directory contains a default document. By default, the following files are default documents for directories: default.htm, default.asp, index.htm and iisstart.asp. If the directory does not contain one of the default files, IIS will issue a 403 Forbidden error. To require IIS to process the directory request for a directory that only contains the default.aspx file, you will need to add the default.aspx document to the default documents property via the property page for the virtual directory. Once this is done, you can add a rule to redirect /Products/default.aspx to /Products/inventory.aspx as described in Scott's article.

Variable scope and Debug vs. Release builds

Lately, I was debugging some code when I came across this little gem in global.asax.cs:


protected void Application_Start(Object sender, EventArgs e)
{
StartTimer();
}

public void StartTimer()
{
string METHODNAME = "StartTimer";

try
{
TimerCallback tcallback = new TimerCallback(TimerMethod);

Timer timer = new Timer(tcallback, null, new TimeSpan(0, 0, 1), new TimeSpan(0, 0, 10));
}
catch (Exception ex)
{
System.Diagnostics.Debug(ex.Message);
}
}

The code basically starts a timer when the web application starts (when the first web page request is issued by a client). The timer fired fine during debugging, but when I ran the web app without debugging, the timer didn't fire. I did fix the issue by scoping the timer object at the Global class level, rather than as a local variable within the StartTimer() mehtod (the timer object was only visible in StartTimer), but I wanted to find out why the debug build exhibited different behavior from the Release build. I stumbled across Mike Tautly's weblog On Garbage Collection, Scope and Object Lifetimes and he describes one reason for the issue: The JIT optimization will determine how long local variables are kept around before being garbage collected.

Monday, March 14, 2005

This page provides a good introduction to Page-User Control communication

http://www.openmymind.net/communication/index.html

Friday, March 11, 2005

Differences between Type.GetType() and typeof

Suzanne Cook has a good explanation for why GetType() only searches the current assembly in addition to mscorlib.dll when it tries to find a type.

http://blogs.msdn.com/suzcook/archive/2003/05/30/57158.aspx

You can use typeof() which will search all loaded assemblies within the current app domain.

Friday, March 04, 2005

"The dependency whatever.dll cannot be copied to the run directory because it would conflict with the dependancy..."

If you ever get a message along the lines of:

Warning: The dependency 'Foo, Version=1.0.1661.21305, Culture=neutral' in project 'Bar' cannot be copied to the run directory because it would overwrite the reference 'Foo, Version=1.0.1661.20048, Culture=neutral'

You can check out Scott Hanselman's site here for some tips:

Dependency Conflicts

In addition, you can also check the dependency list using ILDASM. If you open each dependent DLL in ILDASM and inspect the manifest, looking for references to 'Foo', you should be able to track down the assembly that is referencing the old assembly (in this case the 1.0.1661.20048 version of Foo). Usually the assembly is referencing a different version of the conflicting DLL (or the assembly is referencing multiple versions of the same DLL). Once you find the assembly, you can rebuild it or delete it from the bin directory and re-reference it.

Wednesday, March 02, 2005

Programatically POST xml to a page

In .NET you can use the HttpWebRequest class to make page requests. The HttpWebRequest class supports the GET and POST verbs. Suppose that you wanted to retrieve xml from a page by issuing a GET request for the page http://localhost/Test/Default.aspx?Name=Test&Email=Test. You could do this with the following code:


string uriString = "http://localhost/Test/Default.aspx?Name=Test&Email=Test";
HttpWebRequest httpRequest = null;
HttpWebResponse response = null;

string xml = "";
Uri uri = new Uri(uriString);
httpRequest = (HttpWebRequest)WebRequest.Create(uri);
response = (HttpWebResponse)request.GetResponse( );

if (response != null)
{
Stream responseStream = response.GetResponseStream( );
StreamReader reader = new StreamReader(responseStream, Encoding.UTF8);

try
{
xml = reader.ReadToEnd( );
}
finally
{
reader.Close( );
}
}

This will return the xml string into the xml variable.

Now suppose that you wanted to POST xml to the same web page. You can either post the xml directly to the page, or you could put the xml into a form variable and post it to the page. To post the xml as part of the form (in the 'BodyText' variable), you could do this:


XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load("test.xml");
body = xmlDoc.OuterXml;

string uriString = "http://localhost/Test/Default.aspx?Name=Test&Email=Test";
HttpWebRequest httpRequest = null;
HttpWebResponse response = null;

string xml = "";
Uri uri = new Uri(uriString);
httpRequest = (HttpWebRequest)WebRequest.Create(uri);

httpRequest.Method = "POST";
postData = HttpUtility.HtmlEncode(postData);
postData = HttpUtility.UrlEncode(postData);
postData = "BodyText=" + postData;
ASCIIEncoding encoding = new ASCIIEncoding();
byte[] bytes = encoding.GetBytes(postData);
httpRequest.ContentLength = postData.Length;
httpRequest.KeepAlive = false;
httpRequest.ContentType = "application/x-www-form-urlencoded";
Stream requestStream = httpRequest.GetRequestStream( );
requestStream.Write(bytes,0,bytes.Length);
requestStream.Close( );
response = (HttpWebResponse)request.GetResponse( );

if (response != null)
{
Stream responseStream = response.GetResponseStream( );
StreamReader reader = new StreamReader(responseStream, Encoding.UTF8);

try
{
xml = reader.ReadToEnd( );
}
finally
{
reader.Close( );
}
}

Be careful to not confuse HtmlEncode and UrlEncode. It seems that even though the content type is set to "application/x-www-form-urlencoded" that you should NOT JUST URL encode the xml string. The HttpWebRequest object will appear to process the message for some characters if the string is UrlEncoded, but for other characters, you will receive a '(500) Internal Server' error (this case is especially for xml strings that contain the < character). You should first HtmlEncode, then UrlEncode the string, then prefix the form variable. On the server side, you only have to HtmlDecode the string since the UrlDecoding is automatically done for you.

This page is powered by Blogger. Isn't yours?