Skip to content

Archive

Archive for januari, 2010

I enjoyed playing around with my own WordPress website at evict.nl so much that I also starded to remake my wifes website taalvos.nl immediately followed by making the website Mooijman.aero for a friend. Both sites still need a lot of content but the layout (and therefore my work) is now ready. Here is how these sites now look:

Did you ever have a method that returned a generic list of some type but you actually needed a generic list of one of its interfaces or base class? You probably solved this by cloning the method or by creating a new list while looping through all items. In the article below I will show you a nice and simple generic solution for this problem.

Let’s assume you have a class named Car that has an interface named IVehicle and you also have a class named Plane that also has the interface IVehicle. We also have a data repository that has a method for each of them for retrieving a list of items. Now we want to execute the IVehicle method named Move on all Car objects and Plane objects. We will start by retrieving both lists from our data repository object named MyRepository:

    var cars = MyRepository.GetCars()
    var planes = MyRepository.GetPlains()

Wouldn’t it be nice if we could just concatenate those 2 lists so that we could call the IVehicle method for all of them in one simple loop?

    var vehicles = cars.Concat(planes);
    foreach(var vehicle  in vehicles)
    {
        vehicle.Move();
    }

Unfortunately trying this will give you this error:
Error 1 The type arguments for method ‘System.Linq.Enumerable.Concat(System.Collections.Generic.IEnumerable, System.Collections.Generic.IEnumerable)’ cannot be inferred from the usage. Try specifying the type arguments explicitly.

If we do want to Concat the two collections together, then we first have to cast both collections to th IVehicle interface. At this moment C# 3.0 does not have a simple option to convert a generic list to one of its interfaces or base classes. The .ConvertAll is not easy to use. Fortunately Microsoft recognized this missing feature and in C# 4.0 you will be able to perform this cast by using Covariance and Contravariance. For now you have to use the difficult .ConvertAll method. The simple helper class below will make this easy for you.

    public static class GenericListConverter
    {
        public static T2 AsType<T1, T2>(this T1 model) where T1 : T2
        {
            return model;
        }
        public static IList<T2> ToListOfType<T1, T2>(this IEnumerable<T1> myList) where T1 : T2
        {
            return (new List<T1>(myList.ToList())).ConvertAll<T2>(AsType<T1, T2>);
        }
        public static IList<T2> ToListOfType<T1, T2>(this IList<T1> myList) where T1 : T2
        {
            return (new List<T1>(myList)).ConvertAll<T2>(AsType<T1, T2>);
        }
    }

Using this class is simple. You can just perform a ToListOfType on any generic IEnumerable or IList.

    var cars = myRepository.GetCars().ToListOfType<Car, IVehicle>();
    var planes = myRepository.GetPlains().ToListOfType<Plain, IVehicle>();

The result of this is that you have 2 generic lists of IVehicle and the Concat will now work.

In this case there is an alternative to the above helper class. It is possible to create a helper method that accept anything that implements the IVehicle interface. The code would then look something like:

    ...
        Move((List<Car>)cars);
        Move((List<Plane>)planes);
    ...
    public static void Move<TItem>(List<TItem> vehicles) where TItem : IVehicle
    {
        foreach (var vehicle in vehicles)
        {
            vehicle.Move();
        }
    }

Today I thought about my problem of having my old site still 1/2 alive next to my new WordPress site. On the internet there are still a couple of links that directly point to various files that aren’t used anymore. Wouldn’t it be nice if you could just remove all those old files and still come up with the right WordPress page?

I just made this possible by changing my custom 404 urlrewrite page. This is what my page now does:
1. get whatever is after the domain name from the url and open the wordpress index.php with that part behind it.
2. if the result is not a regular page, then get the words from the url and perform a search.

for instance the link http://evict.nl/error will search for the word error because there is no page named error. One of my old pages http://evict.nl/comdoc/default.asp will now search for ‘comdoc’ and still find the comdoc content (below this post).

Here is the complete sourcecode of my error.asp

<%
Response.Buffer = True
Response.Status = "200 OK"
Response.CharSet = "UTF-8"
Session.CodePage = 65001
myurl = QueryPath()
content = ReturnPage(myurl)
notfound = "Sorry, but you are looking for something that isn't here. You can search again by using the form on upper right of the page..."
if instr(content, notfound) > 1 or len(trim(content)) < 1 then
	Response.Write ReturnPage(SearchQueryPath())
else
	Response.Write content
end if
Response.End()

Function QueryPath()
	' The WordPress location
	w = "http://" + Request.ServerVariables("HTTP_HOST") + "/index.php"
	' Take whatever is after the host name
	q = mid(request.QueryString, instr(request.QueryString, Request.ServerVariables("HTTP_HOST")) , 999)
	' Take the part behind the first /
	QueryPath = w + mid(q, instr(q, "/") , 999)
End Function

Function SearchQueryPath()
	' The WordPress location
	w = "http://" + Request.ServerVariables("HTTP_HOST") + "/index.php?submit=Find&s="
	' Take whatever is after the host name
	q = mid(request.QueryString, instr(request.QueryString, Request.ServerVariables("HTTP_HOST")) , 999)
	' Take the part behind the first / and remove all / and \
	c = LCase(replace(replace(mid(q, instr(q, "/") + 1 , 999),"/"," "),"\"," "))
	' Remove the default.asp or .asp or .
	SearchQueryPath = w + replace(replace(replace(c,"default.asp",""),".asp",""),"."," ")
End Function


Function ReturnPage(myPage)
    on error resume next 
	br = Request.ServerVariables("HTTP_USER_AGENT") 
	set xmlhttp = CreateObject("MSXML2.ServerXMLHTTP")  
	xmlhttp.open "GET", myPage, false 
	xmlhttp.setRequestHeader "Content-Type", "text/HTMI"
	xmlhttp.setRequestHeader "CharSet", "UTF-8"  
	xmlhttp.setRequestHeader "User-Agent",br 	' Required for the WPtouch iPhone Theme
	xmlhttp.send ""  
	if err.number <> 0 then 
		Response.Status = "404 Page not found"
		ReturnPage = "404 Page not found"
	else 
		ReturnPage = xmlhttp.responseText  'responseBody 
	end if 
	set xmlhttp = nothing 
End Function
%>

It’s now a litle more than a week since I installed WordPress on my website. Installing WordPress, finding a good looking theme, finding and adding nice plugins and migrating the content from my old site was quite easy. The thing that costed me the most time was a good way to do the url rewrite. I solved that by creating a simple error.asp page and assigning that page to the 404 error. You can find more info about this error.asp here.

One other point that I wanted to solve is that I have multiple domains running on 1 website and I do want multiple WordPress installations but not for all domains. I also did not want to use WordPress MU because of compatibility and flexability issues. I solved this by conditionally setting the database table prefix in the wp-config.php for the WordPress instances I wanted and adding a conditional redirect in the index.php for the none WordPress domains I have. Here is the code that I use.

wp-config.php

$table_prefix  = 'wp_';
$sl = strlen($_SERVER['SERVER_NAME']);
$d = substr($_SERVER['SERVER_NAME'], $sl - 10); 
if ($d == 'taalvos.nl'){
	$table_prefix  = 'taalvos_';

index.php

$d = substr($_SERVER['SERVER_NAME'], $sl - 16); 
if ($d == 'de-rozemarijn.nl'){
	/** redirect function from wp-app.php should also be included. */
	redirect('default_rozemarijn.asp');
} 

The number of Plugins that are available for WordPress can be overwhelming. Below is a list of the Plugins that I installed. Thanks Thushan for a couple of nice tips.

Add to Any: Share/Bookmark/Email Button

Help readers share, bookmark, and email your posts and pages using any service.

Acronyms

A plugin to wrap acronyms in posts and comments with appropriate acronyms. Allows users to manage lists of acronyms through admin interface. Based on Joel Bennett’s Acronym Replacer plugin (http://www.huddledmasses.org/) and Joel Pan’s NP_Acronym plugin for Nucleus CMS.

Akismet

Akismet checks your comments against the Akismet web service to see if they look like spam or not. You need a WordPress.com API key to use it. You can review the spam it catches under “Comments.” To show off your Akismet stats just put <?php akismet_counter(); ?> in your template. See also: WP Stats plugin.

All in One SEO Pack

Out-of-the-box SEO for your WordPress blog. Options configuration panel

Google XML Sitemaps

This plugin will generate a special XML sitemap which will help search engines like Google, Yahoo, Bing and Ask.com to better index your blog.

New Tag Cloud

The plugin provides an widget wich shows a tag cloud with the tags used by the new WordPress own tagging feature

SyntaxHighlighter Plus

An advanced upload-and-activate WordPress implementation of Alex Gorbatchev’s SyntaxHighlighter JavaScript code highlighting package. See WordPress.com’s “How do I post source code?” for details. Click here for options.

TinyMCE Advanced

Enables advanced features and plugins in TinyMCE, the visual editor in WordPress.

Tweetable

Integrate Twitter with your WordPress blog. Automatically tweet new posts, display your latest tweet in your sidebar, etc.

WordPress Related Posts

Generate a related posts list via tags of WordPress

WPtouch iPhone Theme

A plugin which formats your site with a mobile theme for the Apple iPhone / iPod touch, Google Android and other touch-based smartphones.

As of now my old website is completely migrated to a WordPress driven site. Almost all existing content was migrated from classic ASP. If you find any link that is not working or if you are missing content that was not migrated, then please leave me a message.

Hmmm… I just found out that the details of a post are not available.