I've been hanging out on the #epicode IRC channel for the past few months, and over time I've played with several IRC clients such as XChat, Mibbit (for the Web) and HydraIRC. One of the things that you do most often on IRC is /msg people. The server that I use for #epicode is FreeNode. This server requires you to register you nick before doing a /msg. If you try to /msg without registering, you get an error message back from the server. XChat, annoyingly, didn't show me the IRC error and I spent quite some time trying to figure out what was wrong. Mibbit behaves nicely, but you have to enter your credentials every time which is a pain. (tip: on Mibbit,  click the 'Auth' link next to the server dropdown on the main page and you can enter your NickServ password straight in there!) HydraIRC behaves nicely too, but I've been having problems getting it to store my NickServ password so I don't have to enter it every time.

In theory, the password is saved by HydraIRC when you create a favourite, but it doesn't seem to work for channel favourites, only server favourites. No, I've no idea why. If you look in the XML profile file in the HydraIRC installation directory all the information looks correct. Maybe they work for you but they sure are a pain for me. Thankfully, there is an easy workaround. HydraIRC has a bit of a hack called Command Profiles. I wouldn't describe them as a well-documented feature but they do the trick. Essentially a command profile is just a set of IRC commands that can be run automatically when you connect to a particular IRC server. You can find the command profiles by going Options -> Prefs... -> Command Profiles. In there, you create a profile using a special name so that is picked up on logging in to a server. The name, in my case, is FreeNode_OnLoggedIn. Within that I simply put in my NickServ identification.

hydracps

When I go to my #epicode channel favourite now, it automatically runs my identification with NickServ so that I can /msg people without the pesky error message and having to register myself manually with NickServ every time!


Bookmark with :
Digg It! DZone StumbleUpon Technorati Reddit Del.icio.us Newsvine Furl Blinklist

At the EPiServer Partner Summit I was chatting over dinner to Andy Brodie of Networked Planet. He was remarking that it would be nice within EPiServer to have the capability to show site thumbnails when you hovered over hyperlinks. This intrigued me so when I got back to the UK I did some investigation. There are sites on the internet that do provide a service for this, such as websnapr, but ideally I wanted something that I had full control over.

Time to start coding :)

After some investigation on the web I found a great article about the WebBrowser control and ASP.NET. I tailored it to my needs and got a little thumbnail generator working. I also built a set of JavaScript functions that would show the thumbnails on hyperlinks using DHTML. Next I built a Control Adapter that would pick up EPiServer properties and parse them for hyperlinks. If it found hyperlinks it would insert references to my JavaScript functions. Lastly I wrapped all this in an assembly complete with my Single-Assembly VPP method and using dynamic web resource references.

And so HyperThumbnail was born. Go check it out on EPiCode or see the sample on B&D EPiLabs (hover over the hyperlinks in the content). Deploying to your own site couldn't be easier - simply drag-and-drop the DLL and a .browser file into your website folders.


Bookmark with :
Digg It! DZone StumbleUpon Technorati Reddit Del.icio.us Newsvine Furl Blinklist

Google have released a lovely little API for their Google Translate service. It uses a RESTful interface and returns a JSON object in the HTTP Response. The usual way to use this would be AJAX-style in client side JavaScript. This might not always be what you want to do though. For example, if you have a server resource in English and you want to show it in the page as Spanish you wouldn't want to render it in English and then have some page load event client side to translate it. You really want to do it server side and render it on the page as Spanish straight away.

Of course, Google know this and so they have provided a couple of snippets on their Google code site for PHP and Java. It should probably be expected, but they decided not to provide a nice .NET snippet. Looking around on the web, I can't find any .NET snippets for it and so I did some digging myself to put together a solution.

Before I throw out the snippet, it's worth explaining briefly what JSON is and what libraries are available. JSON is an object definition 'language' similar conceptually to XML in that it is effectively name tags / value pairs but it has the added advantage that it is part of the JavaScript language definition and can be 'eval'ed in JavaScript to give you a client-side object. This is great for AJAX websites. Whilst you could cook your own JSON handler, there are a few JSON libraries out there for .NET. In fact, Windows Communication Foundation has some JSON support built-in. The only problem is that most of the libraries out there are to do with serializing and deserializing .NET objects as JSON objects. That's fine as far as it goes, but it relies on you already having a well-defined .NET type. With Google Translate, we are getting a JSON object as a string that has no well-known .NET type to deserialize to. It might be possibly in theory to map it to an object or even map it to XML but I explored those options and found them incredibly convoluted.

Thankfully you don't need to write your own little JSON parser though because I did find one library out there to do the job, LitJSON. It has a couple of the usual serializer/deserializer features but in addition it also has a feature to parse JSON into a simple hashtable/array. I tried to do something similar with JSON to XML with WCF but couldn't get it to work. One of my colleagues, Stephen Horsfield, did - and I've included his technique after mine.

And so to the code. The snippet below assumes that you are running this in a web form with the following four web controls:

  • txtSource - textbox for source text
  • txtTranslated - textbox for translated text
  • ddlFrom - drop down list with the 2-letter language values for the source language
  • ddlTo - drop down list with the 2-letter language values for the destination language

Of course you could easily swap these with command line args or whatever you like. I have put the snippet in C# and the .NET 2.0 framework, but of course you could rework it for VB.NET or even for .NET 1.0.

   1: // do a check to make sure that we aren't making Google unhappy
   2: if (txtSource.Text.Length > 500)
   3: {
   4:     throw new Exception("Google Translation license forbids more than 500 characters to be translated at once!");
   5: }
   6:  
   7: // create the web request to the Google Translate REST interface
   8: WebRequest oRequest = WebRequest.Create("http://ajax.googleapis.com/ajax/services/language/translate?v=1.0&q=" + HttpUtility.UrlEncode(txtSource.Text) + "&langpair=" + ddlFrom.SelectedValue + "%7C" + ddlTo.SelectedValue);
   9:  
  10: // make the web call
  11: WebResponse oResponse = oRequest.GetResponse();
  12:  
  13: // grab the response stream
  14: StreamReader oReader = new StreamReader(oResponse.GetResponseStream());
  15:  
  16: // put the whole response in a string
  17: string sContent = oReader.ReadToEnd();
  18:  
  19: // parse the string into the litJSON simple object model
  20: JsonData oData = JsonMapper.ToObject(sContent);
  21:  
  22: // write out the translated text
  23: txtTranslated.Text = oData["responseData"]["translatedText"].ToString();

You could enhance this by using the Google Translate API call to auto-detect the source language, but for simplicity I haven't bothered with that extra step.

So lets see what it would look like with WCF. You'll need to include a using statement for System.IO, System.Xml and System.Runtime.Serialization.Json (and reference the appropriate DLLs):

   1: XmlDocument doc = new XmlDocument();
   2: XmlDictionaryReader xr = JsonReaderWriterFactory.CreateJsonReader(s,
   3: XmlDictionaryReaderQuotas.Max);
   4: doc.Load(xr);
   5: xr.Close();
   6: s.Close();

For more details see the complete post on Steve's blog.

And that is how easy it is to call Google Translate from .NET! I'm currently thinking of some funky ways that I could integrate it with the EPiServer Edit mode. There are all sorts of possibilities. Suggestions on a postcard of how you might want it to look. Maybe a right-click option on the navigation tree? Maybe an extra button in the editor? Maybe something that catches the event when a language for a page is created?

Lastly, a tip on the 2-letter languages. I used the System.Globalization feature of .NET to create the drop down lists with their names. Snippet below:

   1: CultureInfo [] aCultures = CultureInfo.GetCultures(CultureTypes.NeutralCultures);
   2:  
   3: foreach (CultureInfo oCulture in aCultures)
   4: {
   5:     if (ConfigurationManager.AppSettings["SupportedLanguages"].IndexOf(oCulture.TwoLetterISOLanguageName) >= 0)
   6:     {
   7:         ListItem oItem = new ListItem(oCulture.EnglishName, oCulture.TwoLetterISOLanguageName);
   8:  
   9:         ddlFrom.Items.Add(oItem);
  10:         ddlTo.Items.Add(oItem);
  11:     }
  12: }

All that is needed after that is a line in the web.config like so:

   1: <appSettings>
   2:   <add key="SupportedLanguages" value="ar,bg,zh,hr,cs,da,nl,en,fi,fr,de,el,hi,it,ja,ko,no,pl,pt,ro,ru,es,sv"/>
   3: </appSettings>

Hope this is useful to someone. There's a whole load more that could be done such as error checking and catching but that is for a later post once I work out how far I can take this.


Bookmark with :
Digg It! DZone StumbleUpon Technorati Reddit Del.icio.us Newsvine Furl Blinklist

As part of the launch of Interakting, the pan-european web agency brand of Business & Decision, the E-Business blogs have been reskinned. The blog engine we use is built on SubText, a great little .NET blog engine. Not the easiest to skin, but manageable.

Have a browse around. It's the same guys blogging the same great stuff - just a little less blue/grey and a bit more pink :)

 


Bookmark with :
Digg It! DZone StumbleUpon Technorati Reddit Del.icio.us Newsvine Furl Blinklist

The company I work for, Business & Decision, is launching a new brand for their global digital agency function; "Interakting". Apparently "Business & Decision" works better as a brand in their other areas (Business Intelligence, Customer Intelligence and Management Consulting) than it does in E-Business. No shock there then :)

It's not officially launched in the UK yet, but you can get a sneak peek of our branding at our shiny new Interakting UK website.

The site was built in our Interakting office here in Oxford, and is running on EPiServer 5. Any feedback let me know and I'll get them through to the team. You may also recognise the tag cloud - it's CloudCuckoo - and we've put it in a little wrapper to make tagging only available to site editors!


Bookmark with :
Digg It! DZone StumbleUpon Technorati Reddit Del.icio.us Newsvine Furl Blinklist

My flight is booked and I'm looking forward to the summit! The agenda looks packed and I'm especially interested to see what is put on the developer second day 'stream'. At the moment it's just TBA... although there's plenty of other tasty tidbits on the other days too (like the MOSS/EPiServer slot with Mats Hellström).

I'm flying out on the early doors SAS flight from Heathrow on the 29th. If there's any other UK partners out there on the same flight, give me a shout and maybe we can link up on our way.


Bookmark with :
Digg It! DZone StumbleUpon Technorati Reddit Del.icio.us Newsvine Furl Blinklist

Whilst building the CloudCuckoo module, I used a neat trick to register my custom VPP on-the-fly by using an attribute flag to mark it as an EPiServer plugin. This would cause EPiServer to find it and intialise it when I first hit the EPiServer site. This worked fine on my machine and some others, but I was finding that on one specific machine it wasn't firing properly. EPiServer was calling it to initialise it, but the problem was when I tried to access the HttpContext. In a nutshell, for some reason when this machine fired up the plugin to initialise it, it was losing or not passing in the HTTP context. Typically, this would happen if there was a funny AppDomain issue or if something was being recycled, but all the configuration looked fine. The code causing the problem is below:

   1: if (HttpContext.Current == null)
   2: {
   3:     // Running from the scheduler, skip registration
   4:  
   5:     System.Diagnostics.Debug.Write("VppInitializer called without HttpContext. Exiting");
   6:  
   7:     return;
   8:  
   9: }
  10:  
  11: // Register
  12:  
  13: Assembly lateBoundAssembly = System.Reflection.Assembly.LoadFrom(HttpContext.Current.Server.MapPath(@"\bin\BusinessDecision.CloudCuckoo.dll"));

When I ran DebugView I could see that the plugin was bombing out due to no HTTP context and never getting to the registration. After trying for a while to get the HTTP context and failing, I decided to tweak things around. First I changed the way the plugin was detected to using inheritance, as described in this post by Allan Thræn. That worked insofar that it did exactly the same thing - but I preferred to use inheritance so left it in there anyway :) I then decided to eliminate the need for the HTTP context at all. The only reason it was there was to get the path using Server.MapPath, but it occurred to me that given my Single-Assembly-Plugin approach, all I had to do was grab the codebase property of the current assembly! That had the added advantage that I was no longer limiting the DLL to having to reside in the BIN folder. In theory it could now even go in the GAC. The updated code looks like this:

   1: Debug.Write("VppInitializerX Loading CloudCuckoo VPP from: " + typeof(VppInitializerX).Assembly.CodeBase);
   2:  
   3: // now binds without using HttpContext
   4:  
   5: Assembly lateBoundAssembly = System.Reflection.Assembly.LoadFrom(typeof(VppInitializerX).Assembly.CodeBase);

As you can see, this code is much cleaner and, most importantly, it works on that machine that was being problemmatical. This is probably a good thing to bear in mind for any EPiServer plugins called in this way - using HTTP context might be risky.


Bookmark with :
Digg It! DZone StumbleUpon Technorati Reddit Del.icio.us Newsvine Furl Blinklist

I've recompiled the CloudCuckoo binary against EPiServer v5 SP1 to save you having to recompile the project yourself. (it was originally built against vanilla v5) Enjoy!

Get CloudCuckoo here


Bookmark with :
Digg It! DZone StumbleUpon Technorati Reddit Del.icio.us Newsvine Furl Blinklist

The EPiCloud module that I've been working on for a while is finally ready for release! Due to the EPiServer preferred module naming policy (no EPi.... please!) we had a few thoughts around the office here and one of my colleagues, Alan Bartlett, came up with CloudCuckoo. The name appealed to me because it was rather different and also has mild amusement value. The best part is this though - I have obtained clearance to release the module for FREE on EPiCode!

The module and sourcecode is available on EPiCode here.

I also finished off the tag moderation part of the plugin, which can be seen on the screenshot below:

There's a few more things that might be nice to add, but for now it's good to get version 1.0 out there and let people start to play with it. If you decide to evaluate/use it and have any feedback at all please let me know.


Bookmark with :
Digg It! DZone StumbleUpon Technorati Reddit Del.icio.us Newsvine Furl Blinklist

I've just spent the last few days in a Commerce Server 2007 training course, which was surprisingly interesting. One of the things that leapt out at me was that there are a couple of partners who have worked with Commerce Server 2002 and EPiServer together. It's something that has interested me too and I see even more possibilities with Commerce Server 2007. Hmm...

As soon as I got back I got busy getting EPiCloud release ready (and thinking of a nice name for it). In doing that I came across this old error again: "The trust relationship between the primary domain and the trusted domain failed".

You may remember my blog about it a while ago, but that was a slightly different scenario. Then I was on my corporate network and getting SQL/Windows authorisations muddled up. This time I was working on my laptop at home. Turns out that EPiServer v5 was trying to resolve a SID against the domain controller, and as I was disconnected at the time it failed. Even connecting to my work VPN didn't help. I even tried logging on locally to my laptop and it was failing. Every time it would throw the error and according to the stack trace it was when it was trying to resolve the VPPs, although I'm not sure how right that was.

Ultimately, the only thing that worked was to temporarily drop my laptop off the domain and onto a workgroup. I then changed all my authorisations to SQL just to check and re-added it to the domain. It promptly broke again, as I expected, so I once more dropped it off the domain.

On Tuesday once I'm back in the office I'll grab a VPC which isn't on a domain and continue my development on there. That should get around the problem of having to mess around the domains on my laptop!


Bookmark with :
Digg It! DZone StumbleUpon Technorati Reddit Del.icio.us Newsvine Furl Blinklist