November 23, 2010
@ 08:54 PM

A few years ago I needed the ability to “autolink” text – basically, I had a list of keywords and anytime those keywords were displayed on a page I needed to have them turned into a link. The code is relatively straightforward, but I thought it might be of some use to other people.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;

namespace RCSSolutions
{
    public class Term
    {
        public string LinkTerm { get; set; }       
        public string Url { get; set; }
        public string Target { get; set; }
    }

    /// <summary>
    /// Adds links to a passed in string based on records in
    /// the SourceAutolink table.
    /// </summary>
    public class AutoLinker
    {            
        private string m_linkStyle = "";

        /// <summary>List of words which auto link</summary>
        public List<Term> LinkWords { get; set; }

        /// <summary>The CSS class to assign to the link tag</summary>
        public string LinkStyle
        {
            get { return this.m_linkStyle; }
            set { this.m_linkStyle = value; }
        }

        public AutoLinker (List<Term> linkWords)
        {
            LinkWords = linkWords;
        }

        /// <summary>
        /// Adds any links to the passed in content.
        /// </summary>
        /// <param name="content">Content to evaluate</param>
        /// <returns>Marked up results</returns>
        /// <developer>Paul Mrozowski</developer>
        /// <created>07/07/2008</created>
        public string AutoLink(string content)
        {
            if (this.LinkWords == null)
                return content;
           
            StringBuilder result = new StringBuilder();

            // Replaces HTML (and html-like) tags with spaces (we want to keep
            // the same relative positions of everything else in the text since
            // we're going to use them to do the final replacements.)
            string newSentence = Regex.Replace(content,
                                     @"<(.|\n)*?>",
                                     match => " ".PadRight(match.Length));

            string tmpContent = content;

            // Loop through each link term, search for matches. Save each of them into a new collection
            // We're going to use the results to sort the matches in decending order by location. That
            // way we can perform the replacements w/o moving the starting location of the other replacements.
            foreach (var linkRow in LinkWords)
            {
                var allMatches = new List<Match>();
                MatchCollection matches = Regex.Matches(newSentence, linkRow.LinkTerm, RegexOptions.IgnoreCase);
                foreach (Match match in matches)
                    allMatches.Add(match);

                var orderedMatches = from m in allMatches
                                     orderby m.Index descending
                                     select m;

                // General idea is to grab all of the text following the match, get the newly
                // link word w/html markup and insert it before the this text. Then truncate
                // the original content to remove everything from the starting position of the
                // match to the end of file - this is basically done so I don't have to track
                // the current position within the file. After we're done with the loop we
                // insert anything that's left to the beginning of the new string.
                foreach (Match item in orderedMatches)
                {
                    string endOfMatchedStringToEOF = tmpContent.Substring(item.Index + item.Length);
                    result.Insert(0, GetAutolinkText(linkRow, item.Value) + endOfMatchedStringToEOF);
                    tmpContent = tmpContent.Substring(0, item.Index);
                }
            }

            result.Insert(0, tmpContent);

            return result.ToString();
        }

        /// <summary>
        /// Get the replacement text.
        /// </summary>
        /// <param name="token">Word token</param>
        /// <param name="content">Original content</param>
        /// <returns>Empty string if no replacement</returns>
        /// <developer>Paul Mrozowski</developer>
        /// <created>07/08/2008</created>
        private string GetAutolinkText(Term linkTo, string match)
        {
            string newWord = match;

            if (this.m_linkStyle.Length == 0)
                newWord = string.Format("<a href='{0}' ", linkTo.Url);
            else
                newWord = string.Format("<a class='{0}' href='{1}' ",
                                        this.LinkStyle,
                                        linkTo.Url);

            if ((linkTo.Target ?? "").Length > 0)
                newWord += string.Format("target='{0}' ", linkTo.Target);

            // We pass in the original match term to maintain its case (the initial match was case-insensitive).
            newWord += string.Format(">{0}</a>", match);

            return newWord;
        }
    }
}

Usage is simple – create a list of terms that you want linked (along with the URL, style (if any), and target) and pass it to the AutoLinker class, then call AutoLink with your source text. It will return the text with the links embedded in it. Here’s a sample from a console application:

        static void Main(string[] args)
        {
            var terms = new List<Term>();
            terms.Add(new Term() { LinkTerm = "Hello", Target = "_blank", Url = "http://www.rcs-solutions.com" });

            string sentence = "Why, hello! This is a sentence where I'm going to link to the word \"hello\".";
            Console.Write(sentence);
            var linker = new AutoLinker(terms);
           
            Console.Write(linker.AutoLink(sentence));
            Console.ReadKey();
        }

 
Categories: .NET

Interfaces are an integral part of .NET, yet a lot of new .NET developers (especially those coming from weakly-typed languages, or languages where interfaces aren't supported) have difficulty in understanding why they're needed and how (and when) they're used. If you find yourself in that group you're in good company. It's not a difficult concept but it can be a bit foreign to developers new to them.

Let's get the textbook definition out of the way, then take a look at what it really means (and why you should even care). From Wikipedia:

"Interface generally refers to an abstraction that an entity provides of itself to the outside. This separates the methods of external communication from internal operation, and allows it to be internally modified without affecting the way outside entities interact with it, as well as provide multiple abstractions of itself. It may also provide a means of translation between entities which do not speak the same language, such as between a human and a computer."

Hmm - OK. While technically correct that doesn't really help, does it? Did your eyes glaze over like mine did while reading that? Maybe if we back up a bit and look at what a class is we might be able to make some sense of this.

The Basics

A class is a collection of methods, properties, and events. It is assumed that each of these methods, properties, and events "do something". At least in most cases (we're going to ignore the idea of an abstract class for right now). So far, so good. You can create a new instance of this class and do things with it, pass it around to other classes as a parameter, etc. In a weakly typed language (also known as a "dynamic language") you can pretty much pass any type of class around without having to worry about the type - as long as your code doesn't try to access a property or method that object doesn't have, you're good to go. The upside to this is that it's pretty flexible. The downside to this is that mistakes aren't caught at compile time - your app. just blows up at runtime (so you'd better test!). Strongly-typed languages take a different approach: you must define the types that can be passed as parameters to methods. That's OK as long as there is only one specific type your method acts on, or the type you're passing in inherits from the base type of the parameter - it's pretty straightforward. The upside is that mistakes (like trying to access a property or method that doesn't exist) is caught at compile time. The downside is that it's not as flexible as a dynamic language.

So what do I mean by "not as flexible"? On the surface it seems pretty reasonable that a strongly-typed method only accepts specific types - how else would the compiler (and you) know that it's safe to access a specific method or property? It doesn't. It only can accept that specific type of class, or any subclass of that same type.

Why is it OK to accept a subclass of the type? Well, the compiler can be sure that the subclass has the same exact properties & methods as its parent (it doesn't care if you add more of them or override the behavior).

But what if it doesn't? What if you had a class that wasn't of the correct type necssary to pass into a method and it didn't inherit from that type either? Let's take a look at an example of this. I wanted to keep it simple enough to understand, but have it be a REAL scenario (not some contrived example). Those goals are a bit difficult to balance so I error'd on the real scenario side of things. Hopefully it'll help you understand WHY some things are the way they are in the framework in addition to understanding interfaces.

A Real Example

For example, let's suppose we create a collection class that can have a collection of objects (that are all of the same type) and we want to have a method which can sort them. You want to write a generic Sort routine on your collection class that can sort any kind of collection of objects, as long as they're the same type. The first issue you'd run into is, "How do I generically create some code which can compare ANY type?" Remember - you have to be able to compare strings, numbers, date/times, maybe custom types someone may have created, etc. So it's not really possible to be able to compare ANY type. You could cover the basic types and then require the user to subclass your collection for any other custom types. It's a bit clunky, but it would work.

What if, instead, we decided that we'd have another class responsible for doing the sorting. We'd provide a default implementation and if you had your own custom types that needed to be sorted you could pass in your own implementation. That's a bit better. The developer would still need to subclass from our default implementation (since we've still got the strongly-typed issues here - again, dynamic languages don't have this "issue"). We could have the developer pass in their version of the class which does the comparison into the Sort() method. The passed in class would have a Compare() method and let's say it takes two parameters of the types of the same type of object and returns an integer value indicating whether one of the objects is less than, greater than, or equal to the other.

Let's take a look at what the code might look like for all of this:

public class Comparer
{
    public int Compare(object x, object y)
    {
        // Code to do comparisons here
    }
}

public class SampleArrayList
{
    public virtual void Sort()
    {
        this.Sort(new Comparer());
    }

    public virtual void Sort(Comparer comparer)
    {
        // Do sorting here. Call out to comparer object to do the actual comparison
    }
}

 

SampleArrayList list = new SampleArrayList();
// Add items to the list
list.Sort(); // default implementation
list.Sort(new SomeComparerSubclass()); // A custom sort


That looks OK. If I wanted to create my own comparison class all I'd do is subclass from Comparer and override Compare() with my own implementation. But let's take a step back and think about this for a bit. If you create a new class and want a method that can compare one instance of that class to another instance of it, where's the best place for the code? Doing comparison's is a pretty fundamental capability of a class - we do it all the time with string's, numbers, datetimes, etc. so clearly it belongs with the class, right? Your only other alternative would be to put it into another class that acts as a kind of "helper". That's effectively what we've forced on any developers that want to use the sorting capability of our collection for their own custom classes. They MUST create a helper class to do a comparison or they'd all have to inherit from our Comparer class (and use it as their base object). That might not be the end of the world but we're only talking about a single example - there are a lot of other places where this scenario comes up.

OK, having to create another class which only does a comparison for a specific type isn't all that great. Since it makes more sense to have a comparison handled by the object being compared, let's say we add a method called CompareTo() to any class when we want to be able to compare it against another instance. In our Comparer class we'll call that method and, hey, our comparer class is now a bit more generic right? We know that in .NET all objects inherit from "System.Object" so having our Comparer class's Compare() method accept "objects" means we can use it with ANY type. I don't actually have to create a new class for each and every item I'm going to compare! But wait - we're STILL going to have the problem with calling the CompareTo() method on our class in the collection; we're back to having to inherit from a common base class.

 

public class Comparer
{
    public int Compare(object x, object y)
    {
        // Code to do comparisons here
        return x.CompareTo(y.CompareTo());
    }
}

But now how can we call the CompareTo() method on those objects? How do we even know if those objects have a CompareTo() method? Since .NET is strongly typed you can't do this - it won't even compile. The class type "object" doesn't have a "CompareTo" method. The .NET compiler knows that and it won't let you do that.

This is begining to feel like a circular issue, isn't it?

Breaking the Cycle

OK, now what? Well, you could jump through a lot of hoops and use reflection to make the method call for you. But it's a lot of work. In a dynamic language (such as Visual FoxPro) code like that is perfectly valid - I can pass any object type into a method like that and access any properties or methods and VFP doesn't care. If the object doesn't have those properties or methods it will just blow up at runtime. I'm a good developer so I won't pass in something that would blow up. .NET sucks - it makes things so difficult.

You're basically stuck at this point - you can't do what you'd like to do in .NET. If .NET supported the idea of multiple inheritance (where class C could inherit from Class A and from Class B at the same time), we'd be able to still make this work. But it doesn't.

Interfaces to the Rescue

That's where interfaces come in (finally!). Let's take another stab at a more concrete definition of an interface: An Interface is a definition of the types of properties, events, and methods a class needs to implement. It's nothing more than a list of properties, events, and methods (and the various types associated with them) that a class has to have. While we can't inherit from multiple classes in .NET, we can inherit from multiple interfaces.

Getting back to our example, we could define an interface that consists of a public method called CompareTo that accepts one parameter of the "System.Object" type ("object" for short). This method needs to return an integer: Less than zero means this instance is less than the object passed in, zero means it's equal, and greater than one means it's greater than the passed in object.

Here's what it might look like:

public interface IComparable
{
    int CompareTo(object obj);
}

While we're at it, it seems like we might want to do something similar to our Comparer class:

public interface IComparer
{
   int Compare(object x, object y);
}


Now all we'd need to do is make sure that any class that we want to compare inherits from the IComparer interface and then "implements" the specified properties, methods, and events (PEM). That is, you need to make sure your class has all of the same PEM's as the interface. Then you use the interface as the parameter type instead. Since we can inherit multiple interfaces on a given type we have a way of giving our classes the cameleon-like ability of appearing as exactly the right type to methods, regardless of what class it really inherits from. We'd do the same thing for any class which can compare two different classes.

So we can rewrite the above code:

public class Comparer : IComparer
{
   public int Compare(object x, object y)
   {
       // Code here which compares x to y and returns integer
   }
}

public class MyCustomClass : IComparable
{
   public int CompareTo(object obj)
   {
   }
   public int CompareTo(MyCustomClass obj)
   {
   }
}


And we rewrite the Sort() method on our collection class SampleArrayList to accept objects of type "IComparer" instead of "Comparer": 

public void Sort(IComparer comparer)
{
   // Code here that iterates over the collection and class Compare()
   // with two of the items in our internal list.
}


Suddenly all of this starts working again - you get compiler-time checking to make sure things don't blow up, Intellisense works, etc. In fact the compiler verifies that you have, in fact, done all of this correctly - if your classes don't implement IComparer or IComparable it will let you know. You have the ability to create a custom class that compares objects in different ways (which makes it easy to come up with different ways of sorting, ex. ascending, descending) and have generic code which will work in most cases.

Conclusion

The scenario I described above plays out throughout the .NET framework. Fundamental things like garbage collection are handled via the IDisposable interface, iterating over a collection (think foreach) is handled by IEnumerable, comparing objects (like we described above) is handled by IComparer and IComparable. Interfaces are used extensively. Hopefully you've gotten a feel for why they're needed and how they're used inside of .NET.

Originally published in Universal Thread Magazine, April 2009


 
Categories: .NET | C#

I've been working on a server monitoring Windows service recently - it's meant to keep an eye on our servers for various types of failures and, if possible, automatically recover from them. One of the failures our website experiences once in a while has to do with our forums. I integrated a third party forum package into our site so our stores have a place to post messages and talk with one another. Occasionally (and I have yet to reproduce the failure steps) it will fail, complaining that it can't find some configuration file. The quick fix is to reset IIS; usually I'll just remote into the server and do an IISRESET from the command prompt. I wanted my service to keep an eye out for this type of failure and automatically recycle IIS. Long term I'd love to track down this failure and fix it the proper way but in the meantime I just want to be able to recover gracefully.

I found the ServiceController class after a bit of digging and wrapped it up into two static methods I could call to reset IIS. I just had to figure out the name of the service I needed to refer to. The easiest way I found of finding this was to just cycle through the services and display their names. You could write a quick console app. to do this, but I just used LINQPad, switched it to C# Statements, added a reference to the System.ServiceProcess.dll (hit F4), then added the namespace System.ServiceProcess and ran the code.

As an aside: I can't say enough nice things about LINQPad - it makes it so nice to be able to test out new classes and ideas. Its name would lead you to believe it's only good for testing LINQ queries, but you can test out almost any .NET code you want. I spent the whopping $19 to upgrade to the full version, which adds Intellisense (the free version doesn't include that). I've added LINQPad to my "must have" .NET toolkit.

image

You might be wondering what the Dump() method does, since it's not part of the ServiceController class. LINQPad has a nice extension method named Dump() that makes it trivial to dump out the response from almost anything. My sample doesn't show it, but it even handles nested classes nicely. OK, enough fawning...

I ran this code which made it really easy to find the service names I was interested in. Once I had them I wrapped up a few of the services I wanted to be able to cycle in their own methods. I ended up wrapping the Start/Stop calls in a try/catch; it would throw an exception if I tried starting a service which was already running or stopping a service which had already stopped.

private void ResetIIS()

{

    StopService("W3SVC", 10);

    StartService("W3SVC", 15);

}

 

private void ResetStateServer()

{

    StopService("aspnet_state", 15);

    StartService("aspnet_state", 15);

}

 

public static void StopService(string serviceName, int timeoutSeconds)

{

    using (ServiceController controller = new ServiceController(serviceName))

    {

        try

        {

            controller.Stop();

            controller.WaitForStatus(ServiceControllerStatus.Stopped, TimeSpan.FromSeconds(timeoutSeconds));

        }

        catch (InvalidOperationException ex)

        {

            // Service may already be stopped

        }

    }           

}

 

public static void StartService(string serviceName, int timeoutSeconds)

{

    using (ServiceController controller = new ServiceController(serviceName))

    {

        try

        {

            controller.Start();

            controller.WaitForStatus(ServiceControllerStatus.Running, TimeSpan.FromSeconds(timeoutSeconds));

        }

        catch (InvalidOperationException ex)

        {

            // Service may already be running

        }   

    }           

}

 

private void ListServices()

{

    ServiceController[] services = ServiceController.GetServices();

    foreach (ServiceController service in services)

    {

        string name = service.DisplayName + " : " + service.ServiceName;

        Console.WriteLine(name);

        //name.Dump();

    }

}


Links:

http://www.linqpad.net


 
Categories: .NET | C#

April 21, 2009
@ 06:38 PM

Check out my article in this month's UT Magazine (April 2009) about interfaces in .NET. I try to explain the how's and why's of them, especially when coming from a loosely-typed language (such as VFP). Hopefully you'll find it useful.


 
Categories: .NET

Extension methods were added as a new compiler feature in .NET 3.5. More specifically, that means you can use VS 2008 to use an extension method and then use VS's multi-targeting to run it under .NET 2.0. They're basically a means of tacking on methods onto existing classes or interfaces w/o actually needed to subclass or modify an interface. It's used extensively by (and added because of) LINQ. The methods aren't really part of the class, but the way you use them (and the way they appear in intellisense) make them feel like they're now part of the class. They're essentially static methods scoped to a specific interface or class.

I've been playing around with them a bit and ran into a case where I thought they'd be kind of a cool fit. I've needed to be able to convert a datatable into a comma-delimited file (CSV) so it can easily be opening in something like Excel, or pretty much anything that understands CSV files. I could create a separate class to do this, but it seems like this should be part of the DataTable class. To write an extension method you basically create a static method in a static class and prefix the first parameter with "this". Yep, that's about it.

I wanted it to basically work like this:

DataTable table = myBizObj.DataSet.Tables["SomeTable"];
string csv = table.ToCSV();

Creating the CSV is pretty straightforward - I loop through the column headers to generate the first header row, then I loop through each row in the table, then each item in the ItemArray of the row. I specifically decided to use quotes as delimiters around everything to keep it simple - the rules as to when you can/should include quotes for a CSV are pretty complicated. The only thing I do is escape out embedded quotes in the data by doubling them, ex. " becomes "". As soon as I had it working, I decided to create a few more overloads to let me control whether a header row was required, and the actual delimiter used (ex. instead of comma you could change it to a | pipe for example). Their is some example code in the XML help at the top of the class. In addition, I'm actually using this for a web page so it might be helpful to see what that code looks like:

string results = act.DataSet.Tables[tableName].ToCSV();

string mimeType = RCSSolutions.Web.Utility.DetermineMimeType("csv");

Response.ContentType = mimeType;

Response.AddHeader("Content-Length", results.Length.ToString());

Response.AddHeader("Content-disposition",

                   string.Format("attachment;filename={0}", "DelimitedList.CSV"));

Response.Write(results);

Response.End();

I'm calling out to another helper class which returns the mime type - in this case, all it does is return "application/csv". The above code basically pops open a dialog box with the file name filled in the browser on the client side.

using System;

using System.Collections.Generic;

using System.Data;

using System.Linq;

using System.Text;

 

namespace RCSSolutions.Utility

{

    /// <summary>

    /// <para>Various extension methods.</para>

    /// </summary>

    /// Sample of using ToCSV

    /// <example>

    /// DataTable table = dv.Table;

    /// // Assumes table is a DataTable

    /// string result = table.ToCSV(true);

    /// System.IO.File.WriteAllText(@"C:\sample.csv", result);

    /// System.Diagnostics.Process proc = new System.Diagnostics.Process();

    /// proc.StartInfo.FileName = @"C:\sample.csv";

    /// proc.StartInfo.UseShellExecute = true;

    /// proc.Start();

    /// </example>

    public static class Extensions

    {       

        /// <summary>

        /// Converts the passed in data table to a CSV-style string.      

        /// </summary>

        /// <param name="table">Table to convert</param>

        /// <returns>Resulting CSV-style string</returns>

        public static string ToCSV(this DataTable table)

        {

            return ToCSV(table, ",", true);

        }

 

        /// <summary>

        /// Converts the passed in data table to a CSV-style string.

        /// </summary>

        /// <param name="table">Table to convert</param>

        /// <param name="includeHeader">true - include headers<br/>

        /// false - do not include header column</param>

        /// <returns>Resulting CSV-style string</returns>

        public static string ToCSV(this DataTable table, bool includeHeader)

        {

            return ToCSV(table, ",", includeHeader);

        }

 

        /// <summary>

        /// Converts the passed in data table to a CSV-style string.

        /// </summary>

        /// <param name="table">Table to convert</param>

        /// <param name="delimiter">Delimiter used to separate fields</param>

        /// <param name="includeHeader">true - include headers<br/>

        /// false - do not include header column</param>

        /// <returns>Resulting CSV-style string</returns>

        public static string ToCSV(this DataTable table, string delimiter, bool includeHeader)

        {

            StringBuilder result = new StringBuilder();

 

            if (includeHeader)

            {

                foreach (DataColumn column in table.Columns)

                {

                    result.Append(column.ColumnName);

                    result.Append(delimiter);

                }

 

                result.Remove(--result.Length, 0);

                result.Append(Environment.NewLine);

            }

 

            foreach (DataRow row in table.Rows)

            {

                foreach (object item in row.ItemArray)

                {

                    if (item is System.DBNull)

                        result.Append(delimiter);

                    else

                    {

                        string itemAsString = item.ToString();

                        // Double up all embedded double quotes

                        itemAsString = itemAsString.Replace("\"", "\"\"");

 

                        // To keep things simple, always delimit with double-quotes

                        // so we don't have to determine in which cases they're necessary

                        // and which cases they're not.

                        itemAsString = "\"" + itemAsString + "\"";

 

                        result.Append(itemAsString + delimiter);

                    }

                }

 

                result.Remove(--result.Length, 0);

                result.Append(Environment.NewLine);

            }

 

            return result.ToString();

        }

    }

}


 
Categories: .NET | C#

I recently added a maintenance form to our website which allows a user to add and delete entries to a list of banner ads stored in a simple XML file. Previously we've just been maintaining them manually by editing the XML directly and copying the associated banner images into a folder on the website. When you delete an ad, I decided to NOT delete the associated image since they may be reused (and I wanted to avoid forcing the user to upload the image again). However, we'd still like to periodically clean out this folder and "archive" the images so they're not cluttering up the selection screen.

I basically needed some code which would get me a list of files in the banner images folder which were not referenced in my banner XML file. It can be kind of clunky to iterate through XML but they've made it much easier with the introduction of LINQ. I fired up LINQPad (which, BTW, is an AWESOME free tool for testing out LINQ code) and tried out a few ideas. As a side note, it looks like Intellisense is now available if you purchase a copy of LINQPad.

http://www.linqpad.net/

I started with querying the filesystem to get a list of files:

  

DirectoryInfo info = new DirectoryInfo(@"X:\inetpub\wwwroot\images\banner");

FileInfo[] files = info.GetFiles();

 

files.Dump();

 

.Dump() is an extension method available in LINQPad which dumps out the results of the query (we haven't actually used LINQ yet to do anything).

Here's what it looks like:

FileInfoLinq

You might notice that Directory contains a DirectyInfo element. If you click on the down arrow it will expand out these values as well.

So I now had a list of files, I wanted to then get a list of images referenced in my banner file. Here's the format of the XML file:

<News>   
   <NewsItem>
       <Title>Supertooth3-banner.gif</Title>
       <Image>/images/banner/Supertooth3-banner.gif</Image>
       <Height>183</Height>
       <Link>/PortalView.aspx?navto=/Supertooth3-banner.gif</Link>
       <Date>July, 19th, 2003</Date>
       <Target></Target>
   </NewsItem>   

  

 

I haven't really been using Title for anything besides the name of the image file, so I was able to take a bit of a shortcut here and use it for my comparison. To pull out the list of images used in the XML, I wrote this query:

XDocument doc = System.Xml.Linq.XDocument.Load(@"X:\inetpub\wwwroot\adv.xml");

doc.Dump();

 

var news = from item in doc.Descendants("Title")

           orderby item.Value

           select item.Value;

news.Dump();

 

Which produces this:

XmlTitlesLinq

I noticed that the banner images folder contained a bunch of other files that I really didn't want to consider for filtering, so I needed to narrow my query to files that had specific extensions. C# doesn't really have a direct equivalent for INLIST, but we can do this a slightly different way for the same effect.

First I define an array of valid extensions, then (inside the where clause of the LINQ query) I check to see if this list of file types contains the filetype of the file I'm currently evaluating. It's a bit backwards, but it's simple and it works.

string[] fileTypes = { ".jpg", ".gif", ".png" };

var imgFiles = from file in files

               where (fileTypes.Contains(file.Extension))

               orderby file.Name

               select file.Name;

 

imgFiles.Dump();

 

Now I've got a list of files from my XML and a list of files from the banner images folder. I want to get a list of files from the banner images folder that aren't in the XML list. I do this via a final query:

var extra = from singleFile in imgFiles

            where !(news.Contains(singleFile))

            select singleFile;

extra.Dump();   

This returns my extra files. Now I can just use this list to move my images into an archive folder periodically.

If I put it all together, I end up with this:

 

XDocument doc = System.Xml.Linq.XDocument.Load(@"X:\inetpub\wwwroot\adv.xml");

DirectoryInfo info = new DirectoryInfo(@"X:\inetpub\wwwroot\images\banner");

FileInfo[] files = info.GetFiles();

doc.Dump();

files.Dump();

 

var news = from item in doc.Descendants("Title")

           orderby item.Value

           select item.Value;

news.Dump();

string[] fileTypes = { ".jpg", ".gif", ".png" };

var imgFiles = from file in files

               where (fileTypes.Contains(file.Extension))

               orderby file.Name

               select file.Name;

 

imgFiles.Dump();

 

var extra = from singleFile in imgFiles

            where !(news.Contains(singleFile))

            select singleFile;

extra.Dump();   

Links:

http://www.linqpad.net/


 
Categories: .NET | C# | LINQ

November 26, 2008
@ 08:50 PM

I thought this was an interesting question that has come up a couple of times in the last few days over on the Universal Thread. In VFP you can create a subclass of a form, customize it, then configure VFP to use this subclass as the "template" for any new forms you create (by going into Tools > Options > Forms and setting the base class).

The question was, how do I do this in .NET?

It's pretty easy - create your form and add any controls, methods, properties, etc. that you want. Then go to File > Export Template. An Export Template Wizard will open. Change the selection to an "Item template" and click Next.

Export Template Wizard

 

On the next screen put a checkmark next to the item(s) you want included in the template. If you have other dependencies (like external classes) you can also select them here. Then click Next again.

Export Template Wizard Select Item to Export

Now you can select any external references you want to include. For example, if you created a project which includes a set of base controls that you used on your form, you may want to select them here (so when you use this template these references will automatically get added to your project). Click Next.

Export Template Wizard Select Item References

Finally you can select an icon that is associate with this template, enter the template name, description, and it's output location. I'd suggest leaving the "Automatically import the template into Visual Studio" option checked. If you don't like the output location, unfortunately you can't change it here. You have to change it via Tools > Options > Projects and Solutions. Finally click Finish.

Export Template Wizard Select Template Options

At this point, when you do an "Add New Item" you should be able to scroll to the bottom of the templates and see "My Templates" - the new template you created should exist there.

Although I showed this for a WinForms application, this can actually be used with any class (and for ASP.NET applications). For example, I have a base business object class I use. Every time I create a new one I just select a template based on a subclass of it to create the new one.


 
Categories: .NET | Visual Studio

August 12, 2008
@ 10:17 PM

I ran across a really cool .NET library on a recent project I've been working on. We have an internal website where we post news, documentation, etc. - basically a Content Management System (CMS). We're working on a new set of documentation that is being done inside of a third party help builder application. We need to import the HTML files it generates into our website (so we get all the things it offers, like security, searching, revision tracking, view statistics, etc.). So basically, I need to run through a lot of HTML files, build a tree of the documents (similar to the help file) and rewrite all of the URL's and image links to point to the correct URL inside of the site. I initially started looking at various regular expressions that I might be able to use over at http://regexlib.com/. Almost every single one of them had some comment about it failing under some circumstances. The HTML is surprisingly clean, but I was still nervous about it. So I looked at using GOLD to parse the HTML. However, from some of the comments I found it still didn't make everything as easy I would have liked. I finally ran across HtmlAgilityPack over on CodePlex . It's a .NET library which lets you read AND write changes to an HTML file via a simple API.

Here's a chunk of code from my importer so you can get a feel for how it works:

HtmlDocument doc = new HtmlDocument();

doc.Load(content.FullDocumentPath);

HtmlNodeCollection linkNodes = doc.DocumentNode.SelectNodes("//a/@href");

 

Content match = null;

// Run only if there are links in the document.

if (linkNodes != null)

{

    // Fix up the URL's

    foreach (HtmlNode linkNode in linkNodes)

    {

        HtmlAttribute attrib = linkNode.Attributes["href"];

        // If it's an internal page anchor, ignore it

        if (attrib.Value.StartsWith("#"))

            continue;

 

        string path = this.GetAbsolutePath(content.DocumentLink, attrib.Value);

        match = this.m_contentList.Find(p => p.DocumentLink == path);

 

        if (match != null)

            attrib.Value = match.GetUrl();

        else if (!path.ToLower().StartsWith("http://") && !path.ToLower().StartsWith("mailto:"))

            Console.WriteLine("Cannot find matching document, searched for " + path);                       

    }

}

 

Basically, doc.DocumentNode.SelectNodes("//a/@href") returns a collection of links in the document (it uses XPath syntax for the selection string). From there, I just iterate through them, build the new URL, then save the modified Url via code that just does: linkNode.Attributes["href"].Value = "New URL Here". I also needed to strip out all the script tags inside of the document, so it uses similar syntax:

private void StripOutScripts(HtmlDocument doc)

{

    // Strip out the scripts

    HtmlNodeCollection scriptNodes = doc.DocumentNode.SelectNodes("//script");

    if (scriptNodes != null)

    {

        foreach (HtmlNode scriptNode in scriptNodes)

        {

            scriptNode.ParentNode.RemoveChild(scriptNode, false);

        }

    }

}

 

I do the same sort of thing - iterate over the collection, except this time tell it to remove the nodes from the document (note that I'm grabbing the parent node, since the current node is everything contained within the script, excluding the <script> tags. By getting the parent, we get that and the tags themselves.

Each collection has a WriteContentTo() method which can write the HTML for that section of the document to a Stream. What's really nice about this entire library (besides how simple it was to use) was the fact that it doesn't seem to mangle the existing HTML when using WriteContentTo() (at least from what I've seen). Only one minor complaint - the docs are a bit weak. It just includes the standard documentation of the classes, not much in the way of examples. However, it's pretty consistent so it doesn't take much to get started with it.

What a great library - it couldn't be simpler. It saved me a ton of time.

Links:

http://www.codeplex.com/htmlagilitypack
http://regexlib.com/
http://www.devincook.com/goldparser/


 
Categories: .NET | C# | Developer Tools

August 5, 2008
@ 08:48 PM

This was an interesting issue I ran into today. We've got a utility I wrote which can search Outlook MSG files from a desktop interface. As part of the program you can print the results to a PDF - I'm using Crystal Reports to do the printing. We had this application installed on a desktop machine for a while but decided to move it over to one of our servers which had a lot more hard drive space. After moving it, when we attempted to print we'd get the error:

"An error has occurred while attempting to load the Crystal Reports runtime"

At first I thought it might be related to needing the CR DLL's installed instead of just being deployed in the app's directory. We installed them and tried again - same exception. Further down in the error (which was actually helpful - imagine that!), "Please install the appropriate Crystal Reports redistributable (snip) containing the correct version of the Crystal Reports runtime (x86, x64, or Itanium).

Hmm...x86 vs x64 - that has to be it - this was Windows 2003 Server (64 bit) vs. XP. I actually just recently listened to a DotNetRocks podcast which talked about .NET applications running under a 64 bit OS. They mentioned that, by default, most .NET applications are compiled under "Any CPU". That means the code get's JIT'ed to 64 bit code under a 64 bit OS - sounds OK. The only catch is that all the components must also be compiled the same way, otherwise you run into problems. I didn't really want to have two different sets of DLL's so I went back into my application and changed it from "Any CPU" to x86 code and recompiled. Order was restored to the universe.

Links:

http://www.dotnetrocks.com


 
Categories: .NET

July 12, 2008
@ 10:34 AM

I mentioned Dependency Injection / Inversion of Control (DI/IoC) recently and I really didn't explain what it is, why you might want to use this particular pattern, and why on earth you'd need a framework for it. It's a fancy name for a fairly simple concept. Instead of creating objects inside of your classes, you let the calling code "inject" the necessary instances into your code. It's probably easiest to see this in some code. I'm going to show both C# and VFP code, since I don't want you to get the idea that this is a .NET-only type thing.
 

   1 public class SampleDependency

   2 {

   3    public string SayHello()

   4    {

   5       return "Hello";

   6    }

   7 }

   8 

   9 public class Sample

   10 {

   11    protected SampleDependency m_depend;

   12 

   13    public SampleDependency Depend

   14    {

   15       set { this.m_depend = value; }

   16    }

   17 

   18    public Sample(SampleDependency depend)

   19    {

   20       m_depend = depend;

   21    }

   22 }

 

      Sample sample = new Sample(new SampleDependency());

 

VFP Version
DEFINE CLASS SampleDependency AS Session 
   FUNCTION SayHello() 
      RETURN "Hello" 
   ENDFUNC 
ENDDEFINE 

DEFINE CLASS Sample AS Session 
   oDepend = NULL 
   FUNCTION Init(toDepend) 
      This.oDepend = toDepend 
   ENDFUNC 
ENDDEFINE 

loSample = CREATEOBJECT("Sample", CREATEOBJECT("SampleDependency"))
 

Notice that in both cases, we are passing in the instance we want the class to use instead of letting the class create the instance itself. That's all DI/IoC is. Honest, that's it. This is DI via a constructor (you can also do it via a property setting instead; notice in the sample C# code I created a write-only property which could hold the reference).

So the next obvious question is, why? What's wrong with just creating the object inside of the class?

One thing DI gives you is the ability to easily swap in different objects. In the C# example, we probably would change the parameter from a specific type to an interface. Now any class which implements that interface can be injected into this class. In VFP, since it's not strongly typed, you can just pass in whatever instance you'd like (it's up to you to make sure it doesn't blow up at runtime by accessing some method or property which isn't on the passed in object). My initial thought after seeing this was, well, can't I just use an abstract factory pattern instead? In an abstract factory you delegate object creation to a "object factory" - usually passing in a name or calling a method which returns the actual instance you'd like to use. This sounds like almost the same thing.

An abstract factory does let you do that, but it doesn't let you easily do something the DI/IoC pattern does: test your objects. Let's suppose you want to write a test for a class which uses another class to send out an e-mail. You aren't really trying to test sending an e-mail - that's just one of the things the class you're testing happens to do during some process. In fact, you really don't want to send out an e-mail; we don't want to spam our users. If you happen to use the abstract factory pattern, you would need to modify it to create your dummy/stub/mock object for sending an e-mail (in VFP that's most likely by editing a record in a table, but the idea is the same), then test the object in question. If you used the DI/IoC pattern the only thing you need to do is pass in your dummy/stub/mock object. No other modifications are necessary.

OK, so this all looks simple enough. Why would you need a framework for the above?! One of the biggest reasons - less typing. You'll notice that in order to use any of these objects you may have to pass in a bunch of other dependency objects (which themselves may have other dependencies). For a complex set of objects that could really suck. A DI framework does that for you along with the benefits of an abstract factory, all rolled up into one. In your code you call the DI framework and tell it to get you an instance of a class - it figures out what objects need to be passed in for you so you don't need to do it. In your tests, you can instanciate the objects directly and pass in your stub/dummy/mock objects instead.

Links:

http://weblogs.asp.net/rosherove/archive/2007/09/16/mocks-and-stubs-the-difference-is-in-the-flow-of-information.aspx
http://www.hanselman.com/blog/ListOfNETDependencyInjectionContainersIOC.aspx


 
Categories: .NET | Software | VFP

July 6, 2008
@ 12:24 PM

I attended a Day of Dot Net event in Lansing a few week back. If you're not familiar with them, they are free mini-conferences (one day) about, not surprisingly, .NET.

I had originally planned on driving out to it Saturday morning, but then Jenn pointed out I'd have to get up really early to get there around 8am. I already work in Farmington, which is 45 minutes to 1 hour from home (and 45 minutes to 1 hour closer to Lansing) and would end up being a really long day for me. So I ended up just staying at a hotel in Lansing Friday night. That turned out to be a great idea. Note to self: the Best Western in Lansing feels and smells like a 80's style bowling alley.

When I got to the hotel, I had some time to look up directions to the college where it was being held. It was only a few miles away, so I decided to not bother to drive over there on Friday night (which is what I would normally have done). In the morning I followed the directions Google Maps had given and found myself in a church parking lot (hmm..."Day of Dot Net and Evangelical Revival??"). I checked the map a few times and it looked OK, and I was exactly where it said I should be. I think that was about the point where I starting cursing out Google maps. I had left all my information about the conference in the trunk so I had to get out of the car to get at it. I happened to notice that the road I was on looked like it actually continued around the side of the church (imagine a light bulb going off above my head: "hey...maybe...."). I jumped back in the car and drove around the parking lot and sure enough, the trees suddenly cleared on my left hand side where the college was hiding. I noticed another car stop right about where I stopped, so it wasn't just me being dense (honest!). Note to organizers - great event, but a small sign would have been appreciated.

When I got into the building (which also wasn't marked, so I still wasn't entirely sure I was at the right entrance), I was surprised at how few people were there - that kind of surprised me since I wasn't able to make it to the last DoDN because it had filled up. It turns out that as the morning wore on the sessions really started to fill up.

The sessions were an hour long - which is REALLY short; they flew by. The sessions all seemed to run a few minutes long which pushed into the next session running a bit longer. The lunch break helped to reset everything.

A few notes to the various presenters:

  • The bottom 1/3 of the screen really isn't visible if you're sitting in the back of the room. I was sitting in the second row and couldn't read some of it.
  • White text on a black background might be easier on your eyes for development, but it's impossible to read when it's projected up on a screen. I'd suggest sticking with black text on a white background.
  • Don't try to wing demo's. Only a few people can successfully pull that off - you're probably not one of them.

I actually ran into a few people I knew - one was someone from the local VFP user group, the other was a old-VFP developer that I haven't seen in a few years. That was a nice surprise. Overall, I was impressed by the number of people who attended, considering you're basically giving up a weekend day to attend. It's nice to see that some people actually care about getting better as developers (either that or they, like me, needed a few new shirts for their wardrobe).

One session happened to stand out in my mind - a session about Dependency Injection / Inversion of Control (specifically, the Windsor framework) by Jay Wren. Well organized, hit every question I had about DI/IoC. Honestly, I didn't "get" DI/IoC before this session; yeah, I understood what it was, but not really why on earth I might need a framework for it. It is actually an elegant way of solving a particular development problem, giving you the benefits of a factory pattern and the flexibility of DI, without getting in your way (at least that's what my notes say). I had the "a ha!" moment, then promptly lost it in one of the other sessions. I'm sure it will come to me at some point, although at this point I'm getting a bit nervous ;-)

At the end of the conference, they ended up giving away of ton of stuff. Just not to me. Oh well, maybe next time.

Overall, I definitely attend another one - a big thanks to the organizers and presenters and sponsors, I know it's a lot of work to put something like this on - it was appreciated. Just try to make sure you've got some soft drinks (Coke, Mt. Dew, etc.) available in the morning next time around <g>. It's hard for some of us to get moving in the morning without some caffeine (for us non-coffee drinkers). Sure I feel all healthy from the orange juice I ended up drinking, but it didn't help much to put a spring in my step.

Links

http://www.dayofdotnet.org/Lansing/2008/
http://jrwren.wrenfam.com/blog/


 
Categories: .NET | Conference

December 12, 2007
@ 10:23 PM

I've been spending a lot of time lately doing some winter cleaning. We're trying to free up some space in the basement for a play area for Brendan. It's amazing how much stuff you can collect. We've thrown away a LOT of stuff - I'm pretty sure the garbage guys hate us by now. Jenn mentioned that one of them didn't look too pleased when he tried to lift one of the bags we put out. We've been donating anything with think might still be useful, and we have people who drive through our subdivision on garbage days looking for interesting finds. More power to them, I say; I'd rather someone finds some use for this stuff instead of throwing it out. Besides, who's got the patience for a garage sale? And who really wants to deal with people trying to get half price for an item marked $1 that originally cost $50.

Since I've been involved with computers for quite some time (and not all of it as a developer), I've managed to collect quite a collection of old computers. Old Pentiums, 486's, a few 386's, motherboards, cases, power supplies, an unbelievable amount of cables, network cards, video cards, etc. I'm planning on posting that stuff on our local freecycle site to see if anyone might be interested in it before tossing it. One of my regrets with a lot of this is that I didn't give it away sooner, while it still may have been of more use to someone. I guess that may have been why I kept it.

A big part of this collection is a ton of books and magazines. I've whittled the magazines down to something manageable, but I still have way too many books. I'm sure I'll add more to the list as soon as I can convince myself that I really don't need them anymore, and once I have time to go through the ones still hiding in the basement (and hopefully before some of them aren't useful anymore). Here's a list of what's on the chopping block (you might be surprised; there are some good books here):

  • Apple II Plus/IIe Troubleshooting & Repair Guide, Robert C. Brenner. Sams. ISBN: 0-672-22353-8
  • DNS and BIND 3rd Edition, Paul Albitz & Cricket Liu. O'Reilly. ISBN: 1-56592-512-2
  • XML Extensible Markup Language (w/CD), Elliotte Rusty Harold. IDG Books. ISBN: 0-7645-3199-9
  • The Unified Modeling Language User Guide, Booch, Rumbaugh, Jacobson. Addison-Wesley. ISBN: 0-201-57168-4
  • The Visual FoxPro 3 Codebook (CD is missing), Yair Aan Griver. Sybex. ISBN: 0-7821-1648-5
  • Object Orientation in Visual Foxpro, Savannah Brentnall. Addison-Wesley. ISBN: 0-201-47943-5
  • Object Models: Strategies, Patterns, & Applications (Second Edition), Coad, North, Mayfield. Yourdon Press. ISBN: 0-13-840117-9
  • Visual Basic 6 Business Objects, Rockford Lhotka. Wrox. ISBN: 1-861001-07-X
  • ASP.NET 2.0 Unleashed, Stephen Walther. Sams. ISBN: 0-672-32823-2
  • Hacker's Guide to Visual FoxPro 6.0, Granor, Roche. Hentzenwerke Publishing. ISBN: 0-96550-936-2
  • The Inmates Are Running The Asylum, Alan Cooper. Sams. ISBN: 0-672-31649-8
  • About Face: The Essentials of User Interface Design, Alan Cooper. IDG Books. ISBN: 1-56884-322-4
  • The Improvement Guide, Langley, Nolan, Nolan, Normal, Provost. Jossey-Bass. ISBN: 0-7879-0257-8
  • HTML: The Complete Reference (Second Edition), Thomas A. Powell. Osborne. ISBN: 0-07-211977-2
  • Effective Techniques for Application Development w/VFP 6.0, Booth, Sawyer. Hentzenwerke. ISBN: 0-96550-937-0
  • What's New in Visual FoxPro 8.0, Granor, Hennig. Hentzenwerke. ISBN: 1-930919-40-9
  • CrysDev: A Developer's Guide to Integrating Crystal Reports, Craig Berntson. Hentzenwerke. ISBN: 1-930919-38-7
  • Advanced Object Oriented Programming w/VFP 6, Egger.  Hentzenwerke. ISBN: 0-96550-938-9
  • Client/Server Applications w/VFP & SQL Server, Urwiler, DeWitt, Ley, Koorhan. Hentzenwerke. ISBN: 1-930919-01-8
  • C# Unleashed, Joseph Mayo. Sams. ISBN: 0-672-321-22-X
  • Measuring and Managing Performance in Organizations, Robert D. Austin. Dorset House. ISBN: 0-932633-36-6
  • Windows 2000 Server Resource Kit (No CD), 8 books total
     

If anyone might be interested in this stuff (books or computer techno-rubble), drop me a line (I can take a pic. of the computer stuff). All of it free as long as you pick up the shipping cost. I hope I don't regret giving away some of this, these books have served me well <g>

 

Links:

http://www.freecycle.org


 
Categories: .NET | Other | VFP

There is a ton of great .NET content available on the web; everything from simple code snippets to full blown apps. I really appreciate that people put the time into this stuff and make it available. But I have one request: would it kill you to include the namespace references in your sample code? There are thousands of classes in .NET - I hate having to try and figure out where these classes are hiding in order to get my code to compile (esp. since I’m normally looking at this code because I'm not familiar with the class or classes required to do whatever it is I'm trying to accomplish. Having said that, I never realized VS would actually help resolve these references for me. If you right-click on a type (in this case, I right-clicked on File), there is a Resolve Namespace option on the content menu:

 

namespace

Very nice!
 
Categories: .NET

A while back I needed a routine which would display the first few hundred characters of a longer chunk of text. Obviously, it's easy enough to do that with the Substring method of a string. However, I wanted to do this on a word boundary (I didn't want to end up with half of the word being displayed). So I wrote a simple routine which broke up the string into an array (using Split()), then rebuilt the string (keeping track of the length along the way). Maybe 25 lines or code or so. It seemed to work OK, so I was good to go.

The other day I realized I needed to adjust the code to strip out HTML markup before displaying the text - you can imagine how "nice" that might look if I happened to chop off an ending tag somewhere. I knew I had a third party library to do this; there are a lot of really useful little routines hiding in the West Wind Web Store .NET 2.0. So I took a look through the library and found what I was looking for. While looking for it, I noticed another routine which appeared to do exactly the same thing I wanted. Except it was like 5 lines and much easier to understand. Doh!

30 seconds later I rewrote my routine. Here it is...

        public static string TruncateString(string source, int maxLength, string ending)
        {
            // Do we even have to truncate it?

            if (source.Length <= maxLength)
                return source;

            string text = source.Substring(0, maxLength);

            text = text.Substring(0, text.LastIndexOf(" ")); 

            return text;
        }


 
Categories: .NET