elkdanger.co.uk http://www.elkdanger.co.uk Who knows? en-GB 2010-03-11T10:31:20.9421718Z 2010-03-11T10:31:20.9431484Z RssBuilder steve@elkdanger.co.uk steve@elkdanger.co.uk 5 New host at Poundhost http://stevescodingblog.co.uk/post/new-host-at-poundhost/ <p>I've just moved this site over to a VPS hosted by <a href="http://www.poundhost.com/" target="_blank">Poundhost.com</a>, which was both surprisingly cheap and good value for money. Now I get to completely control my hosting environment on my own Windows Server 2008 R2 box with IIS7, instead of letting some other company do it with certain restrictions.</p><p>I only found out about them really from a tweet which was re-tweeted by <a href="http://twitter.com/scottgu" target="_blank">Scott Guthrie</a> this week, and would encourage anyone thinking about getting a VPS to have a look at these guys.</p><p>Cheers Poundhost!</p> 2010-03-10T00:00:00Z http://stevescodingblog.co.uk/post/new-host-at-poundhost/ New WCF article over at CodeProject.com http://stevescodingblog.co.uk/post/new-wcf-article-over-at-codeprojectcom/ <p>Finally I found I had something to write about; <a href="http://www.codeproject.com/KB/WCF/wcffileserver.aspx" target="_blank">an article on creating a remote file store using WCF</a>, and it's hosted right now over at CodeProject.com. It basically shows you how to create a service-based remote file repository using the Windows Communication Foundation, which has been part of the .Net Framework since version 3.0.</p><p>Enjoy the article!</p> 2009-03-03T00:00:00Z http://stevescodingblog.co.uk/post/new-wcf-article-over-at-codeprojectcom/ Simple object conversion pattern http://stevescodingblog.co.uk/post/simple-object-conversion-pattern/ <p>Here's a quick conversion pattern you can use if you've got a lot of object conversion going on within your project, especially where databases and web services are involved. Bear in mind that this is essentially what the <a href="http://en.wikipedia.org/wiki/Adapter_pattern" target="_blank">adapter pattern</a> handles, but doesn't involve any sort of inheritence. It's like a cruder version of that pattern. It's also not as quick to use as a simple <a href="http://msdn.microsoft.com/en-us/vcsharp/aa336758.aspx#SelectTransformation" target="_blank">linq projection</a>. However, you might want to do that tranposition more than once, so you'd want to stick that logic into a utility method or something similar. </p><p>This approach just formalises that utility method and enables you to keep all these kinds of conversions in one place; under one roof, if you will. </p><p> My solution involves an interface and (optionally) a utility method. It's handy for when you've got a set of data objects that you want to easily transpose and modify in order to send through a web service call to a client. Even if Linq To Sql (for example) does support such serialisation with WCF services without having to do much work, this often isn't desirable as generally you, as the programmer, want more control over exactly which data is sent across the wire. You might want to do this to guarantee packet sizes, for example, not to mention keeping the interface intact since your domain objects will change.</p><p><!-- pagebreak -->Here's the interface for the converter. Objects which implement this interface support converting an object from one type to another:</p><pre class="c-sharp" name="code">public interface IConverter&lt;TInput, TOutput&gt; { TOutput Convert(TInput input); }</pre><p>Very simple. As an example, an object which converts a series of integers to a series of strings might look like this:</p><pre class="c-sharp" name="code">public class IntConverterConverter : IConverter&lt;int, string&gt; { public string Convert(int input) { return "Number: " + input.ToString(); } }</pre><p> The optional utility method I mentioned earlier is simply a wrapper for converting a whole bunch of inputs in one go. It produces a list of outputs where each item in the list has been converted from each item in the input list. It's also been implemented as an extension method, so this will work with anything which implements the IEnumerable&lt;T&gt; interface:</p><pre class="c-sharp" name="code">public static IEnumerable ConvertAll&lt;TConverter, TInput, TOutput&gt;(this IEnumerable inputs) where TConverter : IConverter&lt;TInput, TOutput&gt;, new() { IConverter&lt;TInput, TOutput&gt; converter = Activator.CreateInstance(typeof(TConverter)) as IConverter; List&lt;TOutput&gt; outputList = new List&lt;TOutput&gt;(); foreach (TInput input in inputs) { outputList.Add(converter.Convert(input)); } return outputList; }</pre><p>Here's an example of using this pattern to convert a bunch of domain objects to a set of data transfer objects (DTOs) with the intention of sending these objects to a WCF client. First, this is what the domain objects look like:</p><p><img src="../../assets/images/conversion_domain.png" alt="Person domain model" width="498" height="338" /></p><p>And here's the DTO I'm going to convert them to:</p><pre class="c-sharp" name="code">[DataContract] public class PersonDto { [DataMember] public string Name { get; set; } [DataMember] public string HomeTown { get; set; } [DataMember] public string [] EmailAddresses { get; set; } }</pre><p> The converter object to convert the domain object to the DTO is:</p><pre class="c-sharp" name="code">public class PersonDtoConverter : IConverter&lt;Person, PersonDto&gt; { public PersonDto Convert(Person input) { return new PersonDto() { Name = input.Name, EmailAddresses = input.EmailAddresses.Select(e =&gt; e.Address).ToArray(), HomeTown = input.HomeTown.Name }; } }</pre><p>&nbsp;</p><p> And a quick example of converting a set of Person domain objects to a set of DTOs:</p><pre class="c-sharp" name="code">using (ExampleDataContext dc = new ExampleDataContext()) { var people = from p in dc.Persons select p; var convertedPeople = ConversionHelper.ConvertAll(people); foreach(var person in convertedPeople) Console.WriteLine(person.Name); }</pre><p> So now instead of a hierarchy of objects representing a person and all the information we can associate with him, we've reduced it to a simple class with a fixed set of properties, allowing the domain object to change freely without affecting any public interfaces and services you might have. If the domain objects do change, you should only have to reflect that change in your conversion code in one place. You could go a step further and create an interface for each DTO which makes this even more flexible. </p><p>I've produced a small project containing all of the above code and the database schema for the DataContext used here, should you wish to borrow or play around with this at your own leisure.</p><p><a title="Download the example conversion pattern code" href="../../downloads/code/objectconversionexample.zip" target="_self">Download the example project</a></p> 2008-12-18T00:00:00Z http://stevescodingblog.co.uk/post/simple-object-conversion-pattern/ New blog up and running http://stevescodingblog.co.uk/post/new-blog-up-and-running/ <p>I've finally got my new blog finished and uploaded, and here it is. Actually, once I had finished <a title="Visit my personal blog" href="http://elkdanger.co.uk" target="_blank">my personal blog</a>, this one was just a case of altering the stylesheet and adding some bells and whistles, and I was good to go.</p><p>I've dumped Wordpress in favour of a custom implementation; I didn't need all the gubbins that Wordpress provided and since the advent of Linq and Linq To Sql I was able to find the time to complete such a project to my satisfaction. This time around, I'm using .Net 3.5, Linq To Sql and Sql Server and a whole lot of custom code.</p><p>These two sites make use of the <a href="http://urlrewriter.net/" target="_blank">UrlRewriter.Net</a> library, which is a must-have bit of code. I also employ this neat trick of <a href="http://www.codeproject.com/KB/aspnet/ViewStatePersistance.aspx" target="_blank">storing the Asp.Net viewstate on the server</a>, which can reduce the page size considerably.</p><p>I also created a base library for all my L2SQL data context needs, and I'll be writing about that shortly. I used it as a base for all my middle-tier data entity 'managers' to provide some uniformity when querying data, and also to manage the persistance of the data context.</p><p>One thing left to implement is <a href="http://en.wikipedia.org/wiki/Pingback" target="_blank">pingbacks</a>, which should be useful should anyone feel the need to link to my site. It would make an interesting project though.</p> 2008-10-15T23:00:00Z http://stevescodingblog.co.uk/post/new-blog-up-and-running/ LinqToLfsWorld 1.0.2 released http://stevescodingblog.co.uk/post/linqtolfsworld-102-released/ <p>Just a quick post to say that LinqToLfsWorld 1.0.2 has been released - you can grab it from <a href="http://www.codeplex.com/linqtolfsworld" target="_blank">the project homepage</a>.</p> <p>This version of the library adds:</p> <ul><li>Support for serialization and deserialization to/from Xml and Json</li><li>A new demo website page, demonstrating the serialization features.</li><li>Some helper constants for use in your car type, track ident and steering method queries</li><li>A couple of bug fixes</li></ul> <p>The entity classes also support exposure through WCF services - I haven't added a test for this scenario yet to the project, but have verified in my own quick test project that it does work as expected.</p> <p>I've written a more detailed account of how the serialization works on the <a href="http://www.codeplex.com/linqtolfsworld/Release/ProjectReleases.aspx?ReleaseId=14653" target="_blank">1.0.2 download page</a>.</p> 2008-07-13T23:00:00Z http://stevescodingblog.co.uk/post/linqtolfsworld-102-released/ Querying LfsWorld with LinqToLfsWorld http://stevescodingblog.co.uk/post/querying-lfsworld-with-linqtolfsworld/ <p>In this post I'm going to show you all the different types of queries you can perform with <a href="http://www.codeplex.com/linqtolfsworld" target="_blank">LinqToLfsWorld</a>. For an overview of what the library is and how it works, please feel free to <a href="http://coding.elkdanger.co.uk/?p=10" target="_blank">read an earlier blog post</a> which takes you through the demo website (included with the library download file).</p> <h2>The Queries</h2> <p>With the library you can perform all the queries that you would normally be able to using a plain url to LfsWorld (according to v1.4 of the pubstat service, which is the latest version at the time of release). These queries are accessed through the LfsWorldContext. All the examples below assume I have already initialised my context with the name <strong>lfswContext</strong>, and called Dispose() when I've finished with it. Disposing the context is important so that it can free up memory and unregister internal event handlers. If you don't dispose the context, you might find some weird things happening if you've handled the context's <strong>RequestMade</strong> event.</p> <p><!-- pagebreak --><img title="More..." src="http://coding.elkdanger.co.uk/wp-includes/js/tinymce/plugins/wordpress/img/trans.gif" alt="" /></p> <h2>Racer Stats</h2> <p><strong>Required parameters:</strong> RacerName<strong></strong></p> <pre class="c-sharp" name="code">var query = from stat in lfswContext.RacerStats where stat.RacerName == "elkdanger" select stat;</pre> <p>This query will either return no results or one result; LinqToLfsWorld supports the use of the <strong>Single</strong> and <strong>SingleOrDefault</strong> methods, so retrieving a single entity instance is quite easy.</p> <h2>Racer Fuel</h2> <p><strong>Required parameters:</strong> RacerName<strong></strong></p> <pre class="c-sharp" name="code">var query = from fuelInfo in lfswContext.RacerFuels where fuelInfo.RacerName == "elkdanger" select fuelInfo;</pre> <p>This query returns information about the fuel usage of a racer, on a given track in a given car.</p> <h2>Personal Bests</h2> <p><strong>Required parameters:</strong> RacerName</p> <pre class="c-sharp" name="code">var query = from pb in lfswContext.PersonalBests where pb.RacerName == "elkdanger" select pb;</pre> <h2>World Records</h2> <p><strong>Required Parameters:</strong> None</p><p><strong>Optional parameters:</strong> Car, TrackIdent</p> <pre class="c-sharp" name="code">var query = from wr in lfswContext.WorldRecords where wr.Car == "XRG" &amp;&amp; wr.TrackIdent == "000" select wr;</pre> <p>The values for TrackIdent and Car are exactly the same as the pubstat service normally accepts, according to the <a href="http://www.lfsforum.net/showthread.php?t=14480" target="_blank">pubstat documentation on lfsworld.net</a>.</p> <h2>Hotlaps</h2> <p><strong>Required parameters:</strong> RacerName<strong></strong></p> <pre class="c-sharp" name="code">var query = from hl in lfswContext.Hotlaps where hl.RacerName == "elkdanger" select hl;</pre> <h2>Hotlap Chart</h2> <p><strong>Required parameters:</strong> TrackIdent, Car</p><p><strong>Optional parameters:</strong> SteeringMethod</p> <pre class="c-sharp" name="code">var query = from hlc in lfswContext.HotlapChart where hlc.TrackIdent == "000" &amp;&amp; hlc.Car == "XRG" &amp;&amp; hlc.SteeringMethod == "ms" select hlc;</pre> <p>The values for TrackIdent, Car and SteeringMethod are exactly the same as the pubstat service normally accepts, according to the <a href="http://www.lfsforum.net/showthread.php?t=14480" target="_blank">pubstat documentation on lfsworld.net</a>.</p> <h2>Hotlap Log</h2> <p><strong>Required parameters:</strong> None </p><p><strong>Optional parameters:</strong> Steering, LogFilter, StartTime, Lines<strong></strong></p> <pre class="c-sharp" name="code">var query = from hll in lfswContext.HotlapLog where hll.Steering == "ms" &amp;&amp; hll.LogFilter == HotlapLogFilter.Top10 &amp;&amp; hll.StartTime == DateTime.Now.AddMonths(-1).ToUnixTimestamp(); &amp;&amp; hll.Lines == 90 select hll;</pre> <p>It's worth mentioning here the call to <strong>ToUnixTimestamp()</strong>. By importing the <strong>LinqToLfsWorld.Extensions</strong> namespace. As the name suggests, this method is an extension on the .Net DateTime object which translates it into a unix timestamp value.</p> <p>Similarly, by calling <strong>DateTimeExtensions.FromUnixTimestamp(timestamp)</strong> you can convert a timestamp value into a DateTime object; again after importing the <strong>LinqToLfsWorld.Extensions</strong> namespace.</p> <h2>Hosts</h2> <p><strong>Required parameters:</strong> None<strong></strong></p><pre class="c-sharp" name="code">var query = from host in lfswContext.Hosts select host;</pre> <h2>Teams</h2> <p><strong>Required parameters:</strong> None<strong></strong></p><pre class="c-sharp" name="code">var query = from team in lfswContext.Teams select team;</pre> <p>That is all the queries that can be performed with the LinqToLfsWorld library. Of course all of these queries can be made using the normal method syntax, such as in:</p><pre class="c-sharp" name="code">var query = lfswContext.RacerStats .Where(stats =&gt; stats.RacerName == "elkdanger").Single();</pre> <p>And of course, such is the nature of Linq, all these queries are only ever executed on the server when the results are enumerated.</p> 2008-06-24T23:00:00Z http://stevescodingblog.co.uk/post/querying-lfsworld-with-linqtolfsworld/ LinqToLfsWorld: A look at the demo website http://stevescodingblog.co.uk/post/linqtolfsworld-a-look-at-the-demo-website/ <p>Now that <a title="Grab the latest release of LinqToLfsWorld from the Codeplex project page." href="http://www.codeplex.com/linqtolfsworld" target="_blank">LinqToLfsWorld</a> has been out for a couple of days, I've got time to explain a bit more about the features, using the demo website as an example.</p> <p>The v0.8 Preview release contains the code library and the demo website for you to have a look at the interface first-hand. I should probably mention that for release 1.0 this will probably change; I'll make the demo website a separate and optional download, and the library in a separate download on its own. This blog post will use that demo website as an example.</p><p><!-- pagebreak --></p> <h2>The Code</h2> <p>Here's the code from the code-behind file, which I'm going to be referring to throughout this post:</p> <p><img src="../../assets/images/code_example_full.gif" alt="LinqToLfsWorld demo website code example" /></p> <p>If you've ever used Linq To Sql, you would be familiar with the methodology at work here. Essentially, to query LfsWorld you would do the following:</p> <ol><li>Create a new instance of the LfsWorldContext</li><li>Write a LINQ query to retrieve results using one of LfsWorld's services (hosts, racer stats, world records, etc).</li><li>Step through the returned data or bind to a data control.</li><li>Dispose the instance of LfsWorldContext</li></ol> <p>Let me explain a few things about this, starting with the LfsWorldContext itself.</p> <p>The context has a strongly-typed collection representing each of the services exposed in v1.4 of the pubstat service. To make these queries, it requires that you supply it your credentials which you use to access LfsWorld (either your username and password, or your ident key if you have one). You can do this in two ways - through the LfsWorldContext constructor, or through the configuration file (see <strong>Configuration</strong> below).</p> <p>The context has <strong>CachingEnabled</strong> set to <strong>true</strong> by default - I've explicitly set it above just for clarity. Whenever you make a request to LfsWorld, the response gets cached for later. This is done for performance reasons and, given that LfsWorld access isn't free for premium users, protected your wallet! The cache time can be configured using the <strong>CacheTime</strong> property on the context - just set this to a Timespan value of your choice.</p> <p>Another caching strategy at work here is to protect those users which do <strong>not</strong> have premium access to the LfsWorld service. Any request made within five seconds of another one will throw an exception, and no request is made to LfsWorld. This is also persistant across different context instances. This behaviour can of course be switched off if you do have premium access to the service, by setting the context's <strong>PremiumPubstatAccess</strong> property to <strong>true</strong>, which will allow you to make requests as quickly as you like. This property is false by default.</p> <p><img src="../../assets/images/code_handler.gif" alt="LinqToLfsWorld code demo showing the response event handler." /></p> <p>The next part at work here deals with an event handler, which allows you to detect when any request has been made through the context instance. This allows you to retrieve information about the url which was sent to LfsWorld, the response it got back, whether it was cached or not and the size of the data which was returned.</p> <p><img src="../../assets/images/code_query.gif" alt="" /></p> <p>This piece of code actually builds the query. Note that it does just <strong>build</strong> the query and does not actually execute it. This is the nature of Linq queries - the data isn't retrieved until the results are evaluated (by using a for-each loop or converting to a list, for example). You should also note that the queries here can be quite fickle. This is a limitation of the current version of LinqToLfsWorld and will be improved by the 1.0 release.</p> <p>What I mean by that is it is a bit limiting as to what you could use in that query. For example, if I was querying racer stats I would use a query like the following:</p><pre class="c-sharp" name="code">var stats = from s in context.RacerStats where s.RacerName == "elkdanger" select s;</pre> <p>This would work fine, as would:</p> <pre class="c-sharp" name="code">string name = "elkdanger" var stats = from s in context.RacerStats where s.RacerName == name select s;</pre> <p>But something like the following wouldn't (imaging GetRacerName() is some method I have created):</p> <pre class="c-sharp" name="code">var stats = from s in context.RacerStats where s.RacerName == GetRacerName() select s;</pre> <p>What you would find is the context would try to sent a url to LfsWorld which queries for a racer's statistics, would would pass through an empty racer name parameter, resulting in LfsWorld returning you no data. In fact, you'll find that <em>any </em>method operation inside that query would produce a similar result.</p> <p>Another thing you'll notice is that for the initial query, only the parameters that LfsWorld accepts for a given action will affect the query (for example, querying racer statistices only accepts a "racer" parameter) . This by design, and the intention is that users of LinqToLfsWorld will make their initial query using only the parameters available to them, evaluate that query and then use plain Linq To Objects to deal with any further filtering that they might need. This is the most flexible way and will give the programmer ultimate control over the resultset.</p> <p>At this point in the example, we evaluate the query by converting it to a list, and selecting only those hosts which are currently populated. At this point in the example we have a plain old list of host objects in memory, which we can treat just like any other object.</p> <h2>Configuration</h2> <p>One thing you can't see in the code above is the configuration. LinqToLfsWorld allows you to use a custom configuration section to specify the same settings for all of your LfsWorldContext instances (you can override them of course), making it easier to use this library from multiple places in the same project.</p> <p>The configuration file for the demo website project look like this:</p> <p><img src="../../assets/images/code_webconfig.gif" alt="" /></p> <p>These settings will apply to any instance of the LfsWorldContext that you create, but of course can be overridden by any instance also. The only required attribute here is <strong>authenticationMode</strong>, which should be set to 'IdentKey' or 'UsernamePassword'. Hopefully it should then follow that if you set <strong>authenticationMode</strong> to 'IdentKey', you must also supply the <strong>idenyKey</strong> attribute. Likewise for <strong>UsernamePassword</strong> authentication mode; you must supply the <strong>pubstatUsername</strong> and <strong>pubstatPassword</strong> attributes. For the next release an xml schema file will be available which will give you intellisense on this configuration section, so you don't have to remember these. For now you can refer to the example site.</p> <p>The next post will more than likely be an update on how progress is being made towards the release of v1.0, once I have improved the expression parsing side of things. Enjoy LinqToLfsWorld so far!</p> 2008-06-23T23:00:00Z http://stevescodingblog.co.uk/post/linqtolfsworld-a-look-at-the-demo-website/ LinqToLfsWorld 1.0 released! http://stevescodingblog.co.uk/post/linqtolfsworld-10-released/ <p>Just a quick post to say that LinqToLfsWorld 1.0 has been released; you can grab it from <a href="http://www.codeplex.com/linqtolfsworld" target="_blank">the project homepage on codeplex.com</a>.</p> <p>Whilst the interface hasn't changed, under the bonnet the expression parsing code has been vastly improved and you can now do a lot more with it, compared to the 0.8 release from the beginning of the month.</p> <p>For example, with the preview code you couldn't write a query such as:</p> <pre class="c-sharp" name="code">var stat = from stats in context.RacerStats where stats.RacerName == GetRacerName() select stats;</pre> <p>.. the point here being that the expression parser couldn't evaluate local expressions, i.e. any expression which didn't contain a parameter expression from inside the query itself (in the example above, this local expression would be the call to GetRacerName()). Now though, all expressions which <em>can</em> be evaluated before the query is even looked at <em>are</em> evaluated down to a constant value. This means you can call any method or access any property you like from inside the query.</p> <p>Some of the common selection methods are now supported also; you can directly call <strong>Single</strong>, <strong>SingleOrDefault</strong>, <strong>First</strong>, <strong>FirstOrDefault</strong>, <strong>Last</strong>, <strong>LastOrDefault</strong> and <strong>Count</strong> on an LfsWorldContext query. You can also call <strong>Select</strong>, provided the query only selects either a single entity or a list of entities. In other words, you cannot create an anonymous type from these queries. This limitation is trivial however, since you can just convert your results into a list and use plain Linq To Objects to select only the fields you need. The example website included with the download demonstrates this.</p> <p>This released also fixed a number of bugs which were flagged up from testing the preview version, mainly to do with caching and the expression engine.</p> <p>There are a couple of issues I'd like to sort out with regards to serialization, which will come out as some sort of '1.0.1' release perhaps. Over the next week or so I'm also going to give you a full run down of each type of query you can perform with this library on this very site.</p> <p>If anyone is using the library and finds any issues with it, please direct them to the <a href="http://www.codeplex.com/linqtolfsworld/WorkItem/List.aspx" target="_blank">issue tracker</a> on the project home page.</p> 2008-06-23T23:00:00Z http://stevescodingblog.co.uk/post/linqtolfsworld-10-released/ LinqToLfsWorld v0.8 Preview http://stevescodingblog.co.uk/post/linqtolfsworld-v08-preview/ <p>After a bit of umming and arrrring I managed to make quite a bit of headway with a project I've been mulling over for a while - <a title="Visit the LinqToLfsWorld project home page." href="http://www.codeplex.com/linqtolfsworld" target="_blank">LinqToLfsWorld</a>. It's a custom LINQ provider which allows the client to communicate with LfsWorld via its Pubstat web service.</p> <p>What is that exactly? <a title="Visit the Live For Speed home page." href="http://www.liveforspeed.net" target="_blank">Live For Speed</a> (LFS) is (primarly) an oAnline racing simulator, and <a href="http://www.lfsworld.net" target="_blank">LFSWorld</a> is an online base for checking your racing stats, viewing and comparing hotlaps and watching other races in real time via a neat flash application. <a href="http://www.lfsforum.net/showthread.php?t=14480" target="_blank">Pubstat</a> is it's webservice which you can query to retrieve information about racers, hosts, teams and hotlaps. You send it a url and it will return either JSON, PHP or XML formatted responses.</p> <p>Since it's url based, and it has a fairly simple interface, I thought it would be a good introduction into finding out what it takes to build a custom LINQ provider. My implementation isn't great nor totally versatile (yet), but it works and I'm pretty pleased with the project so far.</p> <p>The reason the release is tagged as 0.8 Preview is because there's a couple of issues I'd like to sort out before I give it that 'release 1.0' milestone; the object documentation (currently there isn't any) and I'd like to work a bit more on the expression visitor, to make the queries just a bit more friendly.</p> <p>So, if you're interested in having a look, please visit the <a href="http://www.codeplex.com/linqtolfsworld" target="_blank">project page on Codeplex</a> and download the latest release and/or the source code and play around with it. Send me any issues if you want via the issue tracker, and feel free to contact me with any suggestions or queries relating to the project.</p> <p>I'm going to publish a couple more articles over the course of the next couple of weeks as I improve the library, and to show you a couple more examples on how to use it.</p> 2008-06-01T23:00:00Z http://stevescodingblog.co.uk/post/linqtolfsworld-v08-preview/ Querystring Element Insertion http://stevescodingblog.co.uk/post/querystring-element-insertion/ <p>One problem I frequently come across is having to redirect to a page using the current query string in the request, but also having to add new parameters. Furthermore, the parameters I want to add might already exist in the querystring, and if you're redirecting to the same page all hell breaks loose within a few clicks of the link. </p> <p> The exact problem I'm trying to solve is this: I have one page which gathers parameters from the user for an advanced product search, which then passes the parameters through the querystring to a search results page. This page contains a GridView control that has column headings which also pass some values through the querystring (information about which column to sort on and in what direction - I'll blog about this another time). When the column is clicked, I still want to keep the information about the search and also the sort criteria. Not all of the parameters will be in the querystring at any given time. </p> <p> I have to deal with this problem on a few pages, and I need a way to quickly and easily redirect to a url passing the current querystring parameters whilst at the same time injecting one or more new parameters if they don't currently exist. If they do exist, I might want to re-assign it a new value. </p> <p> The (hopefully) obvious solution is to work with the querystring while it's still in the form of a Collection, rather than a string. Unfortunately for us, the Request.Querystring instance during a page is read-only. So how do we go about this? </p> <p>What I've come up with is a pattern for achieving the solution, rather than a handy method or object. It's quick, painless and flexible, and here's the code: </p> <pre class="vb" name="code">Dim newQsColl As New NameValueCollection(HttpContext.Current.Request.QueryString) newQsColl.Set(sortExpressionParam, sortExpression) newQsColl.Set(sortDirectionParam, CType(sortDir, Integer)) Dim newQs As String = newQsColl.GlueElements("&amp;amp;")</pre> <p> The last line I'll talke about in a second. This code snippet allows you to take the current querystring and essentially add more key/value pairs to it. Here I've used the 'Set' method to create the new key/value pairs; this method will add the new pair if the key doesn't exist, but will change the key if it doesn't exist. Exactly the behaviour I was after! </p> <p> An extra facility I wanted to finish this off was some easy method to glue the elements together in a format I could stick straight back into a hyperlink without any fuss. You could create a special lightweight class to do this, but since I'm using Asp.Net 3.5 I used an extension method. Ideally I'd like to implement the following on any IDictionary (since that interface follows the same key/value element structure), but alas NameValueCollection doesn't inherit from such an interface. </p> <p>Nevertheless here's my extension method, named 'GlueElements':</p><pre class="vb" name="code">&lt;Extension()&gt; _ Public Function GlueElements(ByVal collection As NameValueCollection, _ ByVal glue As String) As String Dim sb As New Text.StringBuilder() For Each key In collection.Keys sb.Append(String.Format("{0}={1}{2}", key, collection(key), glue)) Next Dim result As String = sb.ToString() If Not String.IsNullOrEmpty(glue) Then result = Left(result, result.Length - glue.Length) End If Return result End Function</pre> <p>This method simply loops through the keys in the collection and joins together the keys and values using a specified 'glue' string. It then outputs the result, stripping off the last instance of the glue before returning it. If you set the glue string to '&amp;', you end up with a string suitable for inserting straight into a url as a querystring.</p> 2008-04-01T23:00:00Z http://stevescodingblog.co.uk/post/querystring-element-insertion/ VB Dynamic Query Library woes http://stevescodingblog.co.uk/post/vb-dynamic-query-library-woes/ <p>According to my searches on the internet, not many people were having trouble trying to use the <a title="Read about and download the Linq Dynamic Query library" href="http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx" target="_blank">Linq Dynamic Query library</a> inside a class library project. </p><p>The problem was that with my Asp.Net web project, I wanted to have my middle-tier code inside a class library which would then be referenced by the website (and another planned website later on). This class library would contain (amongst other things) my Linq data context and the Dynamic Query library. However, whenever I added the Dynamic Query library to the project the compiler would start complaining about missing objects. </p><p>After much tearing my hair out and research I still couldn't find the problem so I left it to work on something else. A similar issue arised when I was working on a completely unrelated piece of code, so it wasn't just attributed to the Linq library in my original problem. The real issue? </p><p>VB.Net class library namespaces. When you create a VB.Net class library project, you can specify a default namespace for everything in that library, and so when you are creating something inside a<em> sub</em>-namespace you leave off the default namespace which is already set on the project. </p><p>The dynamic library is implemented inside the namespace <strong>System.Linq.Dynamic</strong>, and so when I added it to my class library project the namespace it was in was actually <strong><em>MyNamespace</em>.System.Linq.Dynamic</strong>. This meant that the <strong>System </strong>namespace now clashed with <strong>MyNamespace.System</strong>, and the data context which imports the System namespace, and was <em>in</em> MyNamespace, was importing the wrong one. Obviously, this was also happening to anything which imports the System or any sub-namespace of System. Which means essentially that the hellmouth opened and the world was in chaos. This issue doesn't arise in a normal web project, since you don't define a default namespace for classes. I haven't tried this, but I also assume the issue won't arise in a C# class library project since, while you can specify a default namespace for your classes, the compiler doesn't anonymously prepend your default namespace name onto the one you've explicitely set in the code file. </p><p>The solution is simple - dive into the code file for the Linq Dynamic Query library and remove the namespace declaration.</p> 2008-03-30T23:00:00Z http://stevescodingblog.co.uk/post/vb-dynamic-query-library-woes/ LCD HD44780 activities http://stevescodingblog.co.uk/post/lcd-hd44780-activities/ <p>This blog opener isn't strictly about coding, but having some time off work recently I decided to do something that, for me, is pretty cool. What could possibly be cooler than displaying car data from my favourite racing simulator <a onclick="javascript:urchinTracker('/outbound/article/www.liveforspeed.net');" href="http://www.liveforspeed.net" target="_blank">Live For Speed</a> on an external LCD device!</p><!--more--><p> <a title="Click to view a video of the LCD project in action" href="http://www.youtube.com/watch?v=Gm7BTG60tMw" target="_blank">View the finished project on YouTube</a></p><p><!-- pagebreak --> <img class="right" src="../../assets/images/lcd_finished2.jpg" alt="The finished product!" />The image on the right shows the finished display, showing the car speed, gear and fuel tank level. It's updated in real-time using the game's Outgauge system - Outgauge uses network packets to communicate with the world outside the game, and cool applications have been built to control external hardware devices, from <a href="http://www.youtube.com/watch?v=nggmr7WICuQ" target="_blank">real car gauges</a> to <a href="http://www.youtube.com/watch?v=sePqZbfT5bw" target="_blank">full-motion simulators</a>. The whole device is pretty simple, and cost me just shy of &pound;20 for parts. The LCD device is an HD44780-compatible supertwist LCD display (<a href="http://www.maplin.co.uk/Search.aspx?criteria=n27az&amp;source=15&amp;SD=Y" target="_blank">model #N27AZ from Maplin</a>), and then all you really need is a parallel cable and a power source. I've powered my device from three 1.5v AA batteries, so for convenience I added an on/off switch. You can also add a potentiometer to the contrast input to the device, but I chose not to since I want it to display at full contrast all the time. </p><p style="clear: left"><img class="right" src="../../assets/images/cable_finished.jpg" alt="The finished cable end" />The parallel cable was also a bit of a DIY project in itself. I couldn't easily find (nor was willing to pay delivery for) a D25 male-&gt;male cable, but I did have a D25-&gt;C36 cable handy. So, I slaughtered one end of it, cut of the wires I didn't need and wired a 25-pin plug on the end!</p><p> At the moment the device is powered on batteries, but I plan to change this so that it's powered from a standard hard-disk connector. I've found that when configuring the LCD to display data on two lines the contrast dips considerably (which is why in the video below I'm displaying the data on only one line), and it's been pointed out that this could be the batteries not being able to supply enough current. </p><h2><img class="right" src="../../assets/images/lcd_rig.jpg" alt="LCD Rig" />Connecting to the LCD</h2><p> The rest of the work is done in software. I used the excellent <a href="http://lfs.fullmotionracing.com/" target="_blank">LFSLib</a> to retrieve the data packets from Live For Speed, and my own custom library to interface with the LCD. There are a couple of methods you can use in .Net to send data through the parallel port, and I used the <a title="Read more about using inpout32.dll to send and receive data through a parallel port" href="http://www.codeproject.com/useritems/Inpout32_read.asp" target="_blank"><em>inpout32.dll</em></a> method. This Win32 library contains two main functions - one to send data and one to receive data. Once you've got the hang of using the parallel port, controlling the LCD unit is a fairly straight-forward affair. You basically send a byte of data representing an instruction, send a high voltage to the 'enable' pin (causing the LCD to read and act upon the instruction) then clear the enable pin again. There's an initialization sequence which you must follow, after which text data is sent by setting the RS pin to 'high' (letting it know you're going to send data) and then sending each character in turn down the data pins (setting the 'enable' pin high after every character). The LCD will advance the cursor after every character. You can optionally tell the unit where you want to start the text from, in case you wanted to centre the text on the display. </p><p style="clear: both">My device is not without it's issues (there's a rant coming up in a future post about the BackgroundWorker object) but it was a fun project to work on, and you should have seen the smile on my face once I got it working! If you know a little bit about electronics and can solder, definitely give some thought to attempting a similar thing. I've included some references below which helped me get this up and running. The next thing for me to do is to make an enclosure for it, and put the project to bed.</p> <h2>References</h2> <ul> <li><strong><a href="http://www.codeproject.com/csharp/csppleds.asp" target="_blank">I/O Ports Uncensored: Part 1</a> </strong>Covers controlling the parallel port and connecting to a simple LED circuit.</li> <li><a href="http://www.codeproject.com/csharp/cspplcds.asp" target="_blank"><strong>I/O Ports Uncensored: Part 2 </strong></a>Covers the circuit and pin-out of the HD44780-compatible display unit.</li> <li><a href="http://www.dutchforce.com/~eforum/index.php?act=idx" target="_blank"><strong>Electronics Forum</strong></a>: Helped a great deal when I was learning how to do all this stuff, and troubleshoot problems that were arising.</li> </ul> 2007-10-12T23:00:00Z http://stevescodingblog.co.uk/post/lcd-hd44780-activities/