Steve Trefethen
Contact me
About Me View my LinkedIn profile

Powered by discountASP.NET
referal ID: sdtref
Why recommend discountASP.NET?
Need consulting?
Need Consulting?

Spread Thunderbird

Disclaimer

The posts on this weblog are provided AS IS with no warranties, and confer no rights. The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.

TestComplete Keyword Testing Online Training

I will be presenting a three day webinar April 12-14th 2010 from 9am-1pm PST on AutomatedQA's TestComplete. The cost is $499/person and you can register on Falafel Software's website here. For detailed information on this training click here.

dasBlog provider for use with BlogEngine.NET

September 14 2009 8:36AM

I’ve used dasBlog since I first began hosting my own blog and previously considered a move to BlogEngine.NET (BE) but the URL’s aren’t compatible so there remains some investigation to figure out the best mechanism prior to switching. Unfortunately, dasblog seems to be on it’s final legs so spending time there at this point doesn’t seem wise.

To that end, I’ve been investigating various issues involved in a switch and in an attempt to make a transition easier I’ve created a BE provider which reads/writes blog posts and comments using dasBlog’s IBlogDataService rather than BE’s own XML provider. Basically, I’ve replace one XML provider with another, actually that’s not entirely true as this new provide is a descendant of XmlBlogProvider included with BE. Using this approach I avoid having to constantly re-import my blog data as I look into solving the URL issues.

I’ve made the code available via SVN on Google Code here so feel free to grab it and give it a go. I chose Google Code over Codeplex because the latter doesn’t want abandoned projects and I don’t see this as an ongoing project as it’s scope is quite narrow. What I’m interested in is any feedback regarding issues using the code and taking this sort of approach. In my initial playing around with BE it seems to function properly and allows me to use the “slug” feature of BE to “fix” at least part of the URL problem by simply removing spaces from Titles rather than replacing then with dashes.

Things I’ve tested (manually)

  • Adding/Editing/Deleting posts
  • Adding/Editing/Deleting comments

I haven’t played with images or attachments though my blog data seems to render fairly well. I can see some limitations such as no support for threaded comments though I don’t view this as a long term solution but I think it’s a step in the right direction.

Things that need testing/implementation:

  • DateTime conversions from dasBlog to BE
  • Image uploads
  • Windows Live support

Btw, I’m looking for help with the problem of retaining my existing URLs so if you’re a dasblog user and potentially interested in switching ping me and perhaps we can collaborate.

Digg It!DZone It!StumbleUponTechnoratiRedditDel.icio.usNewsVineFurlBlinkList

Tags: , , , .NET | Open Source | Programming

Text file processing with LINQ

September 09 2009 7:15AM

After working on this problem the other day I started Googling looking for posts written about using LINQ for text file processing. I found the post Parsing textfiles with LINQ (or LINQ-to-TextReader) by Arjan Einbu.

LINQ shows us alternate ways to write code, introducing a more declarative coding paradigm. To use LINQ over the lines of a file, we can read all the lines in the file into a collection, and use LINQ over that collection. There’s some overhead to this; the need to read the entire file upfront and to fit the entire file in memory at once.

The solution was to create an extension method on TextReader for IEnumerable<string>. That post was followed up by another post, rather unfortunately titled, improving upon the solution using  TextFieldParser class in the Microsoft.VisualBasic.FileIO namespace, something I wasn’t aware existed and now find it odd this class is stuck well off in left field.

One of the reasons this subject interests me is I’ve been working with EDI files for awhile now and querying data directly from this file format would be really nice. For example, given a PO with line item segments like this:

PO1*1*36*CA*11.15*PE***VP*RRSKRC85*PI*0001111091127~
PID*F****PRSL ROMNE BBY TRAY ORGNC~
PO1*2*84*CA*11.15*PE***VP*RSMKRC85*PI*0001111091131~
PID*F****PRSL SPRG BBY TRAY ORGNC~
PO1*3*84*CA*11.15*PE***VP*RBSKRC85*PI*0001111091128~
PID*F****PRSL SPNCH BBY TRAY ORGNC~
PO1*4*72*CA*11.15*PE***VP*RHEKRC85*PI*0001111091126~
PID*F****PRSL SPRG W/HRB CLM ORGNC~

You can calculate the total quantity, highlighted in yellow, of all line items using LINQ like this:

using (var reader = new StreamReader("c:\\edi\\inbound\\850_09022009_1311_89.txt"))
{
    var query = (from line in reader.GetSplittedLines("*")
                            where line[0].Equals("PO1") && line[2].Length > 0
                            select Convert.ToInt32(line[2])).Sum();
... }

Using Arjan’s implementation of GetSpittedLines, that’s his name not mine for the extension method he wrote, you can apply logic to any of the columns from the file which is pretty cool.

Of course, there are a myriad of ways of doing the same thing but it’s interesting to have access to the columns allowing for calculations and querying. For my EDI work I’m using FileHelpers which works well though I really like this LINQ option. That said, I haven’t done any benchmarking so I’m not sure about the performance but most of the PO’s I’m working with are less than 4KB and the volume isn’t so great that this would be a major factor. At any rate, I hope you find useful for you too.

Btw, if you’re looking for custom EDI implementations feel free to contact me.

Digg It!DZone It!StumbleUponTechnoratiRedditDel.icio.usNewsVineFurlBlinkList

Tags: , .NET | Development

Mail Server Log MIME Header Parsing

September 06 2009 5:12AM

imageThe other day a friend, whose not a developer, approached me looking for help with a problem they were having dealing a few large server log files. The file contained 100’s of MIME headers listed one after the other each with a starting comment and separated by a blank line. I was given a sample containing 1400 MIME headers which at first I opened in Windows Notepad and looked like what you see to the right. They had been trying to work with this file using Excel but not having much luck because the headers were inconsistent sizes and I imagine extracting the right fields was clearly a problem. The desired result was a format from which they could perform some analysis of the data and particularly of the X-Originating-IP field.

After about 10 seconds of staring at the data in Notepad I opened it in Notepad++ and things looked a bit more sane and it sort of dawned on me what my friend’s first thoughts probably were when they first glanced at this file. Excel looked better but didn’t make the process any easier.

image

A few choices entered my mind:

  • Write a simple parser, regex etc.
  • Look for an existing MIME parser
  • Use VS.NET editor Macros to extract the content
  • grep/findstr

My focus desire was to:

  • not spend much time
  • produce a CSV file
  • do something my friend could duplicate (lessen “support”)

I opted to search for a MIME parser largely because I figured one written in C# had to exist then write a tool to spit out a CVS file. My first Google search was “parse email header C#” which gave me a few interesting links but nothing that really caught my eye. The next attempt was “parse MIME header C#”:

image

Bingo.

The CodeProject article is largely code snippets and the first one looked interesting.

Mime m = Mime.Parse("message.eml");
// Do your stuff with mime

I thought, if there is .eml message parsing then I’m good regardless of the fact that it was expecting a file. I downloaded the source and it compiled without error, always encouraging. Next, I looked into the parsing support:

// Summary:
//     Parses mime message from byte[] data.
//
// Parameters:
//   data:
//     Mime message data.
public static Mime Parse(byte[] data);
//
// Summary:
//     Parses mime message from stream.
//
// Parameters:
//   stream:
//     Mime message stream.
public static Mime Parse(Stream stream);
//
// Summary:
//     Parses mime message from file.
//
// Parameters:
//   fileName:
//     Mime message file.
public static Mime Parse(string fileName);

Sweet.

For testing I saved off a single MIME header and created a simple console application to try and parse a fake .eml file which worked like a charm. All that was left to do was write some code to read the log file one header at a time and spit out a .CSV file.

I made one minor change to the MIME parsing code which was to change it’s HeaderFieldCollection from an IEnumerable to IEnumerable<HeaderField> so as to leverage LINQ to search for the “X-Originating-IP”. Of course, I later found out that the code attached to the article is outdated.

At any rate, I quickly had the file parsed, output to .CVS using a simple console application with input and output filename params which I mailed off. So, if you’re looking for MIME header parsing this library worked well for the 1400 headers I tried and I’m glad I could offer this tiny bit of help in a situation that sounds very serious for the folks involved.

Btw, kudos to Ivar Lumi for making this available, heck I think writing this post took longer than developing the solution.

Digg It!DZone It!StumbleUponTechnoratiRedditDel.icio.usNewsVineFurlBlinkList

Tags: , ,

An HttpHandler for use with Facebook

June 18 2009 5:40AM

imageIn my SocialMine Facebook application, which uses MIT’s Simile Exhibit, I needed to fetch Facebook FQL query results from the Exhibit client-side JavaScript. While it may not sound that complicated it’s not something directly supported by the Facebook Developer Toolkit (FDT). I created an HttpHandler to respond to the Exhibit requests for the JSON data which populates the Exhibit. The HTTP request includes a Referrer header that contains the necessary data, fb_sig_user and fb_sig_session_key to construct an instance of facebook.Components.FacebookService. For completeness here is a list of the queryparams contained in the Referrer URL:

auth_token=1379094a2a42e1c0037a33048912a875
fb_sig_in_iframe=1
fb_sig_locale=en_US
fb_sig_in_new_facebook=1
fb_sig_time=1245301045.1412
fb_sig_added=1
fb_sig_profile_update_time=1241328269
fb_sig_expires=0
fb_sig_user=719571200
fb_sig_session_key=c93185e145713ce98d72dfc2-719571700
fb_sig_ss=57abbef0284354d029fe8a19fa00dfce
fb_sig_ext_perms=offline_access,email,auto_publish_recent_activity
fb_sig_api_key=33c52d0a0c9867f677a1f05154c28478
fb_sig_app_id=5012360767
fb_sig=9ad664af23910ca18aeb203203c366cd

The HttpHandler is an abstract class with a single abstract method called FacebookRequest descendents override to handle the request. As you can see below the handler is quite simple, parsing the queryparams into a Dictionary, creates an instance of the FacebookService and calls FacebookRequest passing the service instance and the HttpContext passed to the handler.

public abstract class FacebookHandler : IHttpHandler
{
    private const string REQUEST_SESSION_KEY = "fb_sig_session_key";
    private const string REQUEST_USER_ID = "fb_sig_user";

    #region IHttpHandler Members

    public bool IsReusable
    {
        get { return false; }
    }

    void IHttpHandler.ProcessRequest(HttpContext ctxt)
    {
        facebook.Components.FacebookService f = new facebook.Components.FacebookService();
        f.ApplicationKey = WebConfigurationManager.AppSettings["APIKey"];
        f.Secret = WebConfigurationManager.AppSettings["Secret"];

        Dictionary<string, string> dic = new Dictionary<string, string>();

        string[] split = ctxt.Request.UrlReferrer.Query.Split(new char[] { '?', '&', '=' });
        // Skip the first item since it’s the "?"
        for (int i = 1; i < split.Length - 1; i += 2)
        {
            if(i < split.Length)
                dic.Add(split[i], split[i + 1]);
        }

        f.SessionKey = dic[REQUEST_SESSION_KEY];
        f.uid = Convert.ToInt64(dic[REQUEST_USER_ID]);
        FacebookRequest(f, ctxt);
    }
    #endregion

    protected abstract void FacebookRequest(facebook.Components.FacebookService fbservice, HttpContext ctxt);
}

The JavaScript of Simile Exhibit requests the JSON data using the following LINK tag:

<link href="friendsjson.aspx" type="application/json" rel="exhibit/data" />    

The reference to friendsjson.aspx isn’t actually an ASPX as it’s handled by a descendent of this HttpHandler which is registered in the httpHandlers section of the web.config as follows:

<add verb="*" path="friendsjson.aspx" type="FBFQL.JSONHandler" />
In my application the FacebookRequest method queries using FQL for profile data and returns a JSON result that populates the Exhibit.

Btw, if you're looking for help on Facebook development be sure to read my wiki article.
Digg It!DZone It!StumbleUponTechnoratiRedditDel.icio.usNewsVineFurlBlinkList

Tags: , ,

Using Google Maps for Geocoding in C# Part 2: Deserializing to a class

December 02 2008 3:32PM

In my previous post, I illustrated how to geocode a city state combination using Google’s Map API and a comment was asked why not deserialize to a class. Well, I could have done that but in the app I’m playing around with that wasn’t really necessary although there is more useful data than just the coordinates so here’s part two.

Once you have the XML data you can construct a C# class that would allow for deserializing to an object. Generating the C# classes is straight forward and requires you to run XSD.EXE (installed with VS.NET) on the XML file to generate an .xsd file. Next, run XSD.EXE again on the .xsd with /classes to generate C# classes. Below is the output from the command line of XSD.EXE and you’ll notice I got an error the first time around (for the work around keep reading):

[c:\temp]"\Program Files\Microsoft Visual Studio 8\SDK\v2.0\Bin"\xsd geo.xml
Microsoft (R) Xml Schemas/DataTypes support utility
[Microsoft (R) .NET Framework, Version 2.0.50727.42]
Copyright (C) Microsoft Corporation. All rights reserved.
Writing file 'C:\temp\geo.xsd'.

[c:\temp]"\Program Files\Microsoft Visual Studio 8\SDK\v2.0\Bin"\xsd geo.xsd /cl
asses
Microsoft (R) Xml Schemas/DataTypes support utility
[Microsoft (R) .NET Framework, Version 2.0.50727.42]
Copyright (C) Microsoft Corporation. All rights reserved.
Schema validation warning: The 'urn:oasis:names:tc:ciq:xsdschema:xAL:2.0:Address
Details' element is not declared. Line 23, position 22.

Warning: Schema could not be validated. Class generation may fail or may produce
 incorrect results.

Error: Error generating classes for schema 'geo'.
  - The element 'urn:oasis:names:tc:ciq:xsdschema:xAL:2.0:AddressDetails' is mis
sing.

If you would like more help, please type "xsd /?".

To work around the above error I deleted the value of the xmlns attribute on the <AddressDetails> node then reran the above commands resulting in this C# file.

Finally, to deserialize the XML I used the following code which is a modified version of the function from my previous post (with minimal error checking I might add). Btw, here is a page that discusses .NET XML serialization:

private string GeoCode(string city, string state, string country, string zip)
{
    string url = "http://maps.google.com/maps/geo?output=xml&key=<your_API_key>&q=" + System.Web.HttpUtility.UrlEncode(city + " " + state);
    WebRequest req = HttpWebRequest.Create(url);
    WebResponse res = req.GetResponse();
    StreamReader sr = new StreamReader(res.GetResponseStream());
    try
    {
        System.Xml.Serialization.XmlSerializer serializer = new System.Xml.Serialization.XmlSerializer(typeof(kml));
        using (System.IO.StringReader reader = new System.IO.StringReader(sr.ReadToEnd()))
        {
            kml item = (kml)serializer.Deserialize(reader);
            if(item.Items.Count() > 0 && item.Items[0].Placemark.Count() > 0 && item.Items[0].Placemark[0].Point.Count() > 0)
                return item.Items[0].Placemark[0].Point[0].coordinates;
            else 
              return "";
        }
    }
    finally
    {
        sr.Close();
    }
}
Digg It!DZone It!StumbleUponTechnoratiRedditDel.icio.usNewsVineFurlBlinkList

Tags: , ,

Using Google Maps for Geocoding in C#

December 01 2008 9:05AM
Recently, I wanted to find out how to programmatically find the longitude and latitude given a city and state. From my previous work using Google Maps I knew this was possible. I did some digging and found Google Maps API supports a particular URL for geocoding a specific location. The URL looks like this:
http://maps.google.com/maps/geo?output=xml&key=<your_google_api_key>&q=<city_state>
Simply specify your Google API Key and your URL encoded city and state and you will get a result similar to the following (for "scotts valley ca"):
<?xml version="1.0" encoding="UTF-8" ?>
<kml xmlns="http://earth.google.com/kml/2.0"><Response>
  <name>scotts valley ca</name>
  <Status>
    <code>200</code>
    <request>geocode</request>
  </Status>
  <Placemark id="p1">
    <address>Scotts Valley, CA, USA</address>
    <AddressDetails Accuracy="4" xmlns="">
      <Country>
        <CountryNameCode>US</CountryNameCode>
        <CountryName>USA</CountryName>
        <AdministrativeArea>
          <AdministrativeAreaName>CA</AdministrativeAreaName>
          <Locality>
            <LocalityName>Scotts Valley</LocalityName>
          </Locality>
        </AdministrativeArea>
      </Country>
    </AddressDetails>
    <Point>
      <coordinates>-122.0120480,37.0555750,0</coordinates>
    </Point>
  </Placemark>
</Response>
</kml>
Hint: For illustration purposes this works without using an API Key although you should review Google’s Maps TOS.

Getting Geocode Information Programmatically

I wrote the following C# function (which lacks error checking) to fetch the above XML response from the Google Maps service. As you can see I’m using a simple regular expression to locate and return the actual coordinates.

private string GeoCode(string city, string state)
{
    string url = "http://maps.google.com/maps/geo?output=xml&key=<your_API_key>&q=" + System.Web.HttpUtility.UrlEncode(city + " " + state);
    WebRequest req = HttpWebRequest.Create(url);
    WebResponse res = req.GetResponse();
    StreamReader sr = new StreamReader(res.GetResponseStream());
    try
    {
        Match coord = Regex.Match(sr.ReadToEnd(), "<coordinates>.*</coordinates>");
        if(!coord.Success) return "";
        return coord.Value.Substring(13, coord.Length - 27);
    }
    finally
    {
        sr.Close();
    }
}

This turned out to be a lot less painful than I had originally thought it might be all thanks to Google’s Maps service. Have you done anything similar/easier/better?
[Update: Dec, 2 2008] Using Google Maps for Geocoding in C# Part 2: Deserializing to a class
[Update: Dec, 16 2008] Status codes returned by this service.

Digg It!DZone It!StumbleUponTechnoratiRedditDel.icio.usNewsVineFurlBlinkList

Tags: , ,

VS.NET needs implicit closing of debugger files like Delphi

October 28 2008 4:18PM

One of the features I really miss from Delphi is the option to close files implicitly opened while debugging. You know, those files that are opened by the debugger as your stepping through code. In Delphi, those files are closed automatically at the end of the debug session thus helping keep you focused on the code you’ve been working on. I was just wading through all of the open files in my current solution and trying to close files I no longer wanted open the vast majority of which were opened during a debug session. After closing 6-8 files manually I clicked on the tab dropdown and there was still a huge list of open files so my usual approach is to close all my tabs and start opening files individually again. Here is the option as it appears in Delphi, note the default is checked. I’m sure lots of Delphi developers now take this option for granted.

Delphi Environment Options dialog

I wonder if CodeGear will have this in Prism? Anyone know how/where to make a VS.NET feature requests?

[Update: Oct. 30, 2008] Thanks to a comment I’ve logged a suggestion for this feature and if this is something you would like to see as well please vote for this request. Warning, that link may require login.

Digg It!DZone It!StumbleUponTechnoratiRedditDel.icio.usNewsVineFurlBlinkList

Tags: ,