Monday, October 12, 2009

Using gmail from C# and inspecting HttpRequests

This post can help you with two things

  1. Sending mail via gmail or google apps through C#.
  2. Inspecting the contents of an HttpRequest as a string similar to HttpRequest.SaveAs.


Today while working on a code for fun project at lunchtime we wanted to see the HttpContext.Request.  Initially we were calling HttpRequest.SaveAs(context.Server.MapPath("Request.txt"),true) and life was good.  When we deployed to our test server hosted by Verio, an awesome company, we got an access denied exception when trying to write.  Our corporate firewall prevented us from changing the folder permissions, and we couldn't figure out how to do it through our ftp client, FileZilla.  We decided to email the request to ourselves with the following code:

SmtpClient mailer = new SmtpClient("smtp.gmail.com", 587);
//mailer.EnableSsl = true;
mailer.Credentials = new NetworkCredential("emailAddress@yourDomain.com", "YourPassword");
mailer.Send("sender@sender.com", "recipient@recipient.com", "snazzySubject", Request.RequestAsString());

Running that code we get: System.Net.Sockets.SocketException: No connection could be made because the target machine actively refused it 216.239.59.109:587.  This is our firewall blocking us again.

At home I got "The SMTP server requires a secure connection or the client was not authenticated. The server response was: 5.7.0 Must issue a STARTTLS command first."

Uncommenting the mailer.EnableSsl line above and rerunning fixed the problem and my email arrived!

//End point #1 and begin point #2
Here is the code duplicating the request.saveAs functionality:  RequestAsString is an extension method.  In my code I put it in the System.Web namespace so it shows up for me when using System.Web.


/// <summary>
/// Turns an HttpRequest into a string for inspection.  Similar to request.SaveAs.
/// </summary>
/// <param name="request">The request to turn to a string.</param>
/// <returns>A string to inspect the HttpRequest.</returns>
public static string RequestAsString(this HttpRequest request)
{
    StringBuilder returnValue = new StringBuilder()
        .Append(request.HttpMethod + " " + request.RawUrl);
    if (returnValue.ToString().EndsWith("?"))
    {
        returnValue.Length = returnValue.Length - 1;
    }
    returnValue.Append(" " + request.ServerVariables["SERVER_PROTOCOL"])
        .Append(Environment.NewLine)
        .Append(TurnNamedValuesToLists(request.Headers, ": ", Environment.NewLine))
        .Append(Environment.NewLine)
        .Append(request.ContentEncoding.GetString(request.BinaryRead(request.ContentLength)));

    return returnValue.ToString();
}

/// <summary>
/// Splits out a NameValueCollection.
/// </summary>
/// <param name="target">The collection to be split.</param>
/// <param name="seperator">Seperates the key from the value in the output.</param>
/// <param name="terminator">Put at the end of the key and the value.</param>
/// <returns>A string of all the key value pairs.</returns>
private static string TurnNamedValuesToLists(NameValueCollection target, string seperator, string terminator)
{
    StringBuilder returnValue = new StringBuilder();
    string[] keys = target.AllKeys;

    foreach (var key in keys)
    {
        returnValue.Append(key + seperator + (string)target[key] + terminator);
    }
    return returnValue.ToString();
}

Monday, October 5, 2009

Useful Visual Studio 2008 Settings

Here are some Visual Studio 2008 settings I have turned on to speed up my development time.
  1. Default Browser - I use Chrome as my default browser, but our application is targeting IE.  To have Visual Studio launch IE instead of chrome I found out one can right click a .aspx page select 'Browse ' With' and then from the next dialog set Internet Explorer as default.
  2. Autorecover - Sometimes over bad VPN connections AutoRecover will freeze the VS User Interface.  I used to change the autorecover path but now I go to settings --> Environment --> Autorecover and uncheck the save checkbox.
  3. Source Control - Settings --> Source Control --> Environment  I check get everything when a solution or project is opened.  VS still prompts for get latest on open so you are in control, but it is a nice reminder to sync up.  For saving I have 'Prompt for check out' selected to avoid silent checkouts.  Some files like .vsmdi and some dependant files need to be checked out prior to editing for this to work.  For Editing I have 'Do nothing' so I can edit and continue without checking out files.
  4. Outlining - Settings -->Text Editor --> C# --> Advanced I uncheck 'Enter outlining mode when files open.'  This prevents regions from hiding code from me when I open the file.  I also uncheck 'Surround generated code with #region' because I don't like regions.  Ever.
  5. Debugging - Settings --> Debugging --> General I uncheck 'Require source files to match the original version'  This is another one for edit and continue debugging.  Sometimes I'll notice something I want to change, like changing a string literal to reference a constant from a helper class, but don't want to stop my debugging.
  6. Symbols - Settings --> Debugging --> Symbols I cache my symbols to c:\debugsymbols so they can be shared between VS and Windbg.