Posts for 2009

Last day at TechEd

It's friday, and TechEd is over for this time.

My first session on friday was about little-known secrets in Microsoft Silverlight 3. This was a really good session for advanced Silverlight development, and I took away many tricks - including the ability to download and use assemblies dynamically and asynchronously; and to use the OS client stack instead of the browser stack for network access.

Second session was about extending Visual Studio 2010's architecture modelling tools. This was a code-rich session, where we were walked through creating 3 extensions for the modelling tools. With VSIX packages, deployment of Visual Studio extensions are now much easier. The coding experience when creating extenions has also been made much nicer in the new verison of Visual Studio 2010. It is a no-frills experience, where you only need to work in the problem domain, and not jump through hoops to make Visual Studio do what you want.

The last session of this year's TechEd is about Pex and Code Contracts. I am writing this while waiting for the session to be begin - it's a very interesting topic, and I might do a full length blog post about Pex and Code Contracts at a later time.

This has been a very educational and interesting week. I have learned about architecture and design, new tools and techniques. In general, the quality of the talks has been very high (there were a few misses, but it's been an overall good experience). The only problem has been to select the right session, when there were multiple interesting selections in the same time slot, which happened to me a lot. For instance, I never got to see a talk about the Concurrency Runtime (CCR), because there were always something more interesting on the menu. Now, I need to get home and get into the gym - it's been a week with good foods, eggs and bacon each morning at the hotel, so I need it :-) I Might be coming back next year !


Day Four at TechEd over

TechEd is coming to an end, day four is now over. There are three sessions on friday, then it's over.

I started the day with a session on C# 4.0 Dynamic: The why’s and hows. It was being done by Alex Turner, who is Program Manager for the C# compiler. This was a very interesting walk through why C# should have dynamic features, and why it has been designed as it is. There has gone a lot of design thought into the dynamic design, and I certainly think that the final design they’ve chosen is the right one. He demoed creating your own dynamic types from C# which can respond to any method call – very cool. I can certainly see some good use cases for the C# dynamic keyword.

Next, I went to see a talk about Windows Communication Foundation: Developer’s Guide to Windows Communication Foundation, SOA and success. Interesting, and with some very good thoughts on interoperability. My most important take-away from that session, is that if you need to be interoperable, try to do REST.

In the afternoon, I went to see Tess Ferrandez present on ASP .NET post-mortem debugging (well, the techniques apply to any .NET process, I think, but it was presented towards ASP .NET). This is the kind of debugging you get to do when your process consumes too much memory, hangs, or explodes; in the production environment, without you being able to reproduce the issue locally. When this kind of debugging is needed, something is on fire, and you will get stress fixing it. But apart from that, I do find this kind of debugging challenging and kind-of-fun ;-) Tess demonstrated using WinDbg, SOS.dll (Son-of-Strike, someone please explain the name to me), Debug Diag and other tools. She demonstrated detecting a memory issue, a poor performance issue, and a crash issue using these tools. She also demonstrated doing these using Visual Studio 2010, with its new ability to open memory dumps, and do debugging on them. With this cool new feature, you can do almost everything you can do in a normal debug session, but in a memory dump, that you might have obtained from some production server. You can see the stack trace, the locals, and examine the value of objects. The only thing you cannot do, is run/step back/forward, of course, the dump is an image of the process at a specific time. Very neat is the Parallel Stacks feature, where Visual Studio will visualize the stack of each thread for you, which makes it easy to identify contention in your locking, as well as other thread sync issues.

Last session of the day was by Magnus Mårtensson. This was an architecture talk about design with dependency injection and ensuring extensibility. Very interesting.


Third day at TechEd

Once again, I attended some very interesting talks at TechEd. This mornings sessions was entitled “The daily Scrum”, about doing Scrum and agile development. This was mostly a Q&A session with answers to many of the practical problems one might encounter when trying to be agile.

Next, I had a real hard time deciding between staying on the agile track and attending the “Tools and Agile Teams” talk versus hearing Don Syme speak about F#. I chose the F# session, which I think was a good choice. Don is one of the primary architects behind F#, so it would have been a shame not to hear him speak about it. This talk really drove home some points about F#, and why it helps you do parallel programming, with immutability, the async language construct and Agents. Another good point is that F# should not be used for anything, and in a large application, Don suggested that only a small DLL might be written in F# - it should be used as a tool, where you needed. Don also showed some really impressing demos, using Direct3D from F#.

After lunch, I attended Roy Osherove’s talk about unit testing. His main points where to write maintainable, consistent and readable unit tests, and proceeded to show this can be done. He suggested using test reviews in order to get started writing good unit tests, which I think is a very good idea. Very insightful talk.

The last session of today was about cloud computing: “ Deep Dive into Developing Line-of-Business Applications Running in the Cloud ”. I don’t think this was a good session. There was too much demoing of an app in the cloud, and too little talk about the actual architecture behind it. Also, the presenters neglected to do any introduction to the Azure tools, I guess they expected everyone attending to know about those in advance.


Day Two At TechEd Europe

Today started off fresh with 2 Sharepoint sessions The first one was an introduction to Sharepoint 2010 for developers, and while I haven’t done any development on Sharepoint before, based on the feedback, it will be tons easier to do Sharepoint development with 2010. The second session on Sharepoint was somewhat relevant and somewhat a  miss. While it did provide some good information, there was not really anything new, if you had attended the first session.

During lunch, I had been invited to a lunch session by Microsoft Denmark on IIS 7.5. The speaker was  a real expert on the subject, Bernhard Frank. Very interesting and good  food, but had to cut the session short in order to make it to the next session.

Next was a presentation by Brian Harry about TFS 2010 and its new version control features. There are some real goodies coming ,, in 2010, and Brian demonstrated better branching and branch visualization, support for rollback and improved labeling. Very nice, and something I can really see the need for in my own organization.

I also attended a session on software architecture by Ralf Westphal. He discussed architecture at a high level, and you should not view the architecture as UML class diagram, layered architechture diagram or something like that. Instead he advocated functional  building blocks, or functional units as he called it; which recursively consists of yet another set of functional units. This way, you get a hierarchy of functional units from the one application, through synchronous components till methods in a class. While surely one of the most abstract talks today, I took some very good points with me from the talk.

Lastly today, there was an ASP .NET MVC2: “What’s new” session that I attended. It really competed with the “Pumping Iron” session (about IronRuby/Python), but as it turns out, that session was overbooked, so I made the right choice. There is some really great improvements in MVC2, which boils down to improving productivity on the framework. This means support for partial renderings based on invoking of controllers, and templated views. A cool demo was demonstrating the validation features, where you can define your validation rules in the model (as annotations out-of-the-box, but it’s extensible, so you can store your rules wherever you like). I think MVC2 might just be the release that is mature enough to be tried out on a real project – I am sure our frontend developers will love it.


Got a Twitter account

Oh, BTW, I got a twitter account. Follow me on http://twitter.com/dennisriis, if interested.

TechEd Europe 2009 Day One

Today was my first day at TechEd Europe 2009 in Berlin, after having arrived to the hotel on sunday evening. I chose to drive to Berlin myself from Denmark, which went just fine, until I scratched a rim on the way down into a very narrow passage to the parking garage. Damn. The TechEd experience so far has been just great, although there was some queue for registration this morning. I guess it is hard to avoid when you have 7000+ people attending an event, and they all, more or less, arrive at the same time.

My first session at TechEd was titled "ADO.NET Entity Framework in Microsoft Visual Studio 2010 and Microsoft .NET Framework 4" and was about Entity Framework 4 with speaker Eric Nelson. Wait-a-minute, you might say, because last version of the EF was the initial release, 1.0. It seems that the EF has skipped a couple of versions so that it gets the same version number as the .NET Framework it ships with. That being said, the EF ships some of it's features as a separate download, but the core should be in .NET FX 4.

So what's to say about EF4 ? Well, it seems that Microsoft has fixed it. By that I mean that many of the problems that existed with the initial version has been eliminated or the experience has been improved. This includes better tooling and designer support. There is support for model-first development, where you drag-and-drop your model in a designer, and lets the framework generate the database for you (technically speaking, this also existed in v1, but it required you to do a lot of manual stuff, or as Eric Nelson put it, you would be in for a whole world of pain taking that route.

Something I am more excited about is the ability to control the generated code using T4 templates. This enables different scenarious such as POCO objects, which was missing from v1. There are some built-in templates so you don't need to write them from scratch. If you adhere to the "develop against an interface" to "do TDD" group of people (count me in), it would be quite easy to change the built in templates, so that you would get some nice interfaces to work against. Very nice.

Also, Eric demoed a Code-Only, or "persistance ignorance" support in EF4. With this, you can take some objects, and persist them to a database, and the framework will itself create a database, the schema, and do CRUD operations. While nice for demos, I really can't see the application of this for real-world projects larger than toy-size.

It seems that EF4 is now a serious contender in the ORM world, and I think I will try it out on a real project when I get the chance (of course, it probably needs to go out of beta first).

 

Next session was about ASP .NET 4 and Visual Studio 2010 improvements. This was a very interesting lap around a lot of small improvements and features, that will life better and easier for the web developer. This includes an inheritable viewstate setting, better controls for ClientID generation and better standards-compliant markup from the built in controls; as well as better control over the markup that is emitted. Also, a Code nugget syntax for emitting HTML encoded strings has been added, which will prove handy. One of the things that looks really good is the improved Publish dialog in 2010 and the support for Web.config merges, so that you can have one .config to rule them all, but keep transformations that you can apply automagically when deploying. Together this means, that you can click a button and get your website deployed. I didn't have the chance to ask if this is supported as MSBuild tasks as well, but I suspect it is. I'll have to track down someone who can answer this during the conference. Shouldn't be too hard :-)

 

The rest of the day was keynote sessions. First was the "Developer General" session, by Jason Zander (project manager for the Visual Studio team). Jason talked about the development ecosystem and the effort Microsoft has put into VS 2010 to make a better development experience. This includes push-of-a-button deployment of Sharepoint parts, instead of 22 manual steps. He might have been exaggerating about the 22 steps, but is sounds nice. Oh, he also announced that Microsoft has acquired the Teamprise client suite, which makes it possible for non-Windows, non-Micrsoft, non-.NET devs to work with Team Foundation Server.

Lastly there was the "real" keynote by Stephen Elop, President of Microsoft Business Division. This was a typically "fluffy" talk which did not have much real content for developers. It was interesting though, and he demoed some new features in Windows Server 2008 R2 and Exchange Server 2010. He got the biggest applause when demonstrating, that Outlook Web Access 2010 now runs seamlessly in Firefox & friends :-)

Tomorrow, I have another busy day lined up. Just have to figure out how to be 3 places at once ...

 


Sitecore Dictionary gotcha when using the master database

During some projects at work, we were having a real weird problem with the Sitecore Dictionary feature. This is the built in feature in Sitecore that lets you localize short texts, such as what to put in the "Read more" or "Next page" links on a web page. Of course, there are many ways to do this, but since Dictionary items is a supported Sitecore feature, and they can be edited from within the Sitecore environment, it seems reasonable to use this for Sitecore sites.

This is how it works: You put dictionary items under /sitecore/system/Dictionary. Each dictionary item consists of a shared key and a localized phrase field. That is, the key is the same for all languages, the phrase varies by language. To get a phrase at runtime, you use the static Translate.Text method and pass the key as a parameter, and it will return the correct phrase in the current context language (or you can explicitly pass a Language). This is also described on SDN here (you will need an SDN account to access the article). There even is an XSLT extension function for the Translate methods. Very nice.

The problem we were facing started to occur when we moved some of our front-end developers (who does most of the localization texts) away from working on a test-server, and instead having their own development version on their own workstation, working there (the way it really should be done - also gives you a better chance of running CI). The problem was, that on one developer's workstation you would see one set of Dictionary items on the website, on another workstation there would be a different set. Sometimes all dictionary phrases was completely missing. Inside the Sitecore Content Editor, the data seemed to be correct.

So I started digging around to find an explanation. I started using Reflector to determine what was really going on in the Sitecore.Globalization.Translate class. I quickly found out, that the class internally keeps a Hashtable containing the languages, and in that a Hashtable for each language's texts, in memory. Great for quick lookups. So when and how is the Hashtable filled with data ? This is where it gets tricky. When a phrase is first requested (after a application restart), Sitecore will look for a file called dictionary.dat in the temp directory and try to load it. This is where the Translate class keeps it's persistent cache: Each time a key is added, it will get saved to the file (in addition to being kept in memory); and it will try to load it from there when a phrase is requested, and there is no dictionary data in memory. If reading this file fails, it will rebuild it from the data in the database. Here lies the first problem: You might know that Sitecore operates with a core database (for Sitecore itself), a master database for content and a web database that content is served from. As it turns out, the dictionary will only ever be re-populated with data from the core database. This is hard-coded in the class. And we were adding all our Dictionary items to the master database (since this is really where they should be, it is content). This was my first "that's funny" moment - If the dictionary cache only rebuilds from core; how could our setup ever have worked ??

Time to research some more. After some more tinkering around, I found the Sitecore.Globalization.ItemSaveEventHandler. This is an event handler, that is hooked up to the ItemSaving event in web.config. What this does, is that whenever an item is saved, if it is of type "dictionary item", it will add the key and phrase to the internal language hashtable, which will also trigger a save of the dictionary.dat file. This event handler however, does not care which database is being used. Both master and core (and web for that matter) database saves, will trigger a update of the cache.

This explained everything. If Sitecore is being used on the same machine only, dictionary items in the master database, will work. If it is deployed to production, it will work, because we typically copy the entire website folder, including the temp files, and thus the "correct" dictionary.dat. However, if Sitecore is used in parallel on different servers, you will start seeing the errors we were seing, inconsistent and/or missing dictionary entries. This could be an issue during development if you setup the environment on different developer workstations, but also in staging environments or in load-balanced environments (depending on your setup). If dictionary items (again, in the master database), is saved in parallel on different environments, it will generate different dictionary.dat files with different phrases, and it is impossible to merge. And if you lose dictionary.dat, you can't restore the master dictionary entries without saving each item again.

Revisiting the SDN documentation, though it is quite thin on the subject, it does state that you should add your own dictionary items to the core database. It feels wrong to do this, since our own dictionary items would then be mixed with Sitecore's own internal ones; and because I don't think the core database is a place to store customer data. So I guess it is not a bug that storing dictionary items in the master is not supported, but it would be a nice and reasonable feature. But I do think that there is a bug here; in that it is at all possible to use dictionary items stored in master, when it is not supported. It should definitely work consistently; and not be some half-baked feature that works "occasionally, if you use the right setup". It should also be noted that the Dictionary node is already in the master database in a clean installation, so there are no alarm clocks going off when the novice Sitecore programmer starts using it.

Now, we already have solutions in production using this approach, and time committed on ongoing projects for using it this way. So we needed a way to ensure that dictionary items in the master database would behave consistently and just work.

The solution is below. It is basically a class that can rebuild the Sitecore dictionary from both databases. It reuses the Sitecore logic by invoking their Load and Save methods using reflection, and overwriting the static _languages hashtable field in the Translate class. This is really not pretty, it is a ugly hack, and I would definitely prefer not to use reflection to call into methods that were never intended to be used from outside the class. That being said however, it seems to work - but of course there are no guarantees, and if it blows up or kills your kitten; I'm not responsible.

To use it, simply call the Rebuild method. I used a custom IHttpHandler for the purpose, so I can call the URL whenever needed (don't deploy the handler it into production however ;-) ). After the cache has been rebuilt, you can share the dictionary.dat with other development machines just by copying it, or you can just rebuild when needed at each developer's discretion.

         1: using System;
         2: using System.Reflection;
         3: using Sitecore.Data;
         4: using Sitecore.Configuration;
         5: using System.Collections;
         6: using Sitecore.Data.Items;
         7: using Sitecore.SecurityModel;
         8: 
         9: namespace Webdanmark.SitecoreCMS.Common.Utility
         10: {
         11:     /// <summary>
         12:     /// This class supports rebuilding the Sitecore dictionary from both Core and Master databases.
         13:     /// Default implementation from Sitecore can only rebuild from Core, which leads to various issues if
         14:     /// the temp dictionary.dat file is lost, or editing happens on multiple servers.
         15:     /// </summary>
         16:     /// <remarks>
         17:     /// This class tinkers with Sitecore private methods and internal workings. Not pretty.
         18:     /// This is a hack to workaround a limitation in Sitecore without re-implementing the whole thing.
         19:     /// </remarks>
         20:     public class DictionaryRebuilder
         21:     {
         22:         /// <summary>
         23:         /// Event fired when progress in the task occurs.
         24:         /// </summary>
         25:         public event EventHandler<DictionaryRebuilderEventArgs> Progress;
         26:         /// <summary>
         27:         /// Databases.
         28:         /// </summary>
         29:         private readonly Database[] databases;
         30:         /// <summary>
         31:         /// The Translate type.
         32:         /// </summary>
         33:         private readonly Type translateType;
         34:         /// <summary>
         35:         /// Load method.
         36:         /// </summary>
         37:         private readonly Action<Hashtable, Item> loadMethod;
         38:         /// <summary>
         39:         /// Binding flags for a private static member.
         40:         /// </summary>
         41:         private static readonly BindingFlags privateStatic = BindingFlags.Static | BindingFlags.NonPublic;
         42:         /// <summary>
         43:         /// Save method
         44:         /// </summary>
         45:         private readonly Action saveMethod;
         46:  
         47:         /// <summary>
         48:         /// Initializes a new instance of the <see cref="DictionaryRebuilder"/> class.
         49:         /// </summary>
         50:         public DictionaryRebuilder()
         51:         {
         52:             databases = new[] { Factory.GetDatabase("core"), Factory.GetDatabase("master")};
         53:             translateType = typeof(Sitecore.Globalization.Translate);
         54:             loadMethod = (Action<Hashtable, Item>) FindMethod<Action<Hashtable,Item>>("Load", privateStatic, typeof (Hashtable), typeof (Item));
         55:             saveMethod = (Action) FindMethod<Action>("Save", privateStatic);
         56:         }
         57:  
         58:  
         59:         /// <summary>
         60:         /// Rebuilds the dictionary cache.
         61:         /// </summary>
         62:         public void Rebuild()
         63:         {
         64:             Hashtable rootTable = new Hashtable(10);
         65:             foreach (var db in databases)
         66:             {
         67:                 var langs = db.Languages;
         68:                 SendMessage("\nProcessing {0} database, {1} languages.", db.Name, langs.Length);
         69:                 foreach (var language in langs)
         70:                 {
         71:                     string languageKey = language.ToString();
         72:                     Hashtable languageTable;
         73:                     if (rootTable.ContainsKey(languageKey))
         74:                         languageTable = (Hashtable)rootTable[languageKey];
         75:                     else
         76:                         rootTable[languageKey] = languageTable = new Hashtable();
         77:  
         78:                     RebuildLanguage(db, language, languageTable);
         79:                 }
         80:             }
         81:             SendMessage("\nLanguages loaded.");
         82:             ReplaceSitecoreTable(rootTable);
         83:             SendMessage("Writing data cache to file.");
         84:             saveMethod();
         85:             SendMessage("\nDone.");
         86:         }
         87:  
         88:         /// <summary>
         89:         /// Finds the method.
         90:         /// </summary>
         91:         /// <typeparam name="TDelegate">The type of the delegate.</typeparam>
         92:         /// <param name="name">The name.</param>
         93:         /// <param name="bindingFlags">The binding flags.</param>
         94:         /// <param name="parameterTypes">The parameter types.</param>
         95:         /// <returns></returns>
         96:         private Delegate FindMethod<TDelegate>(string name, BindingFlags bindingFlags, params Type[] parameterTypes)            
         97:         {
         98:             MethodInfo method = translateType.GetMethod(name, bindingFlags, Type.DefaultBinder, parameterTypes, null);
         99:             return Delegate.CreateDelegate(typeof (TDelegate), method);
         100:         }
         101:  
         102:         /// <summary>
         103:         /// Replaces the sitecore table.
         104:         /// </summary>
         105:         /// <param name="hashtable">The hashtable.</param>
         106:         private void ReplaceSitecoreTable(Hashtable hashtable)
         107:         {
         108:             FieldInfo fi = translateType.GetField("_languages", privateStatic);
         109:             fi.SetValue(null,hashtable);
         110:         }
         111:  
         112:         /// <summary>
         113:         /// Rebuilds the language.
         114:         /// </summary>
         115:         /// <param name="db">The db.</param>
         116:         /// <param name="language">The language.</param>
         117:         /// <param name="languageTable">The language table.</param>
         118:         private void RebuildLanguage(Database db, Sitecore.Globalization.Language language, Hashtable languageTable)
         119:         {
         120:             using (new SecurityDisabler())
         121:             {
         122:                 var dictionaryRoot = db.GetItem("/sitecore/system/dictionary", language);
         123:                 if (dictionaryRoot == null)
         124:                 {
         125:                     SendMessage("\tNo dictionary found in {0} for {1}", db.Name, language.Name);
         126:                     return;
         127:                 }
         128:  
         129:                 SendMessage("\tProcessing {0}", language.Name);
         130:                 loadMethod(languageTable, dictionaryRoot);
         131:             }
         132:         }
         133:  
         134:         /// <summary>
         135:         /// Sends the message.
         136:         /// </summary>
         137:         /// <param name="msg">The MSG.</param>
         138:         /// <param name="inserts">The inserts.</param>
         139:         private void SendMessage(string msg, params object [] inserts)
         140:         {
         141:             if (Progress != null)
         142:             {
         143:                 var args = new DictionaryRebuilderEventArgs {Message = String.Format(msg, inserts)};
         144:                 Progress(this, args);
         145:             }
         146:         }
         147:  
         148:         /// <summary>
         149:         /// Event arguments
         150:         /// </summary>
         151:         public class DictionaryRebuilderEventArgs : EventArgs
         152:         {
         153:             /// <summary>
         154:             /// Gets or sets the message.
         155:             /// </summary>
         156:             /// <value>The message.</value>
         157:             public string Message { get; set; }
         158:         }        
         159:     }
         160: }

 And you could use it like this:

        1: DictionaryRebuilder builder = new DictionaryRebuilder();
        2: builder.Progress += (s, e) => Response.WriteLine(e.Message);
        3: builder.Rebuild();

If you want to display progress while rebuilding, hookup the Progress method to some event handler. The one in my example won't compile for you, since Response.WriteLine is an extension method in one of our common libraries.

Disclaimer: The contents of this Blog post is my own opinions only. I am not affiliated with Sitecore in any way. Some of the technical details was extracted using Reflector, and some are educated guesswork. I might be wrong, and Sitecore might very well change the implementation in a later version, so that the information above does no longer apply. This was done on Sitecore 6.0.1. rev 090212, but I suspect that the general idea is the same in previous Sitecore versions. 


Getting your public IP from a PowerShell script

I often work on computers at different locations, and often, I need to know what public IP I am using to connect to the internet. Of course, this is easy to find out - I can just go to a website that tells me my IP, such as http://myip.dk/.

But I find this to be suboptimal. If I am configuring something, finding the IP involves firing up a browser, going to the site, and copying the IP displayed. It is a speed bump when I am trying to be productive - and the display-my-ip sites are often covered in commercials, which I dislike.

So today, I decided to write a PowerShell script that can tell me my current public IP address. First, I needed a reliable way of finding it. Of course, I could just screen-scrape off a site such as http://myip.dk/, but it has some disadvantages. I can't know if the html structure will change - and it would mean that I would have to download all of the HTML just to get a few bytes of IP address. Furthermore, I don't know whether it would be legal at all.

Therefore, I started by writing a small ASP .NET HTTP handler, that could tell me my IP. I put the following simple code in the ProcessRequest method:

 1:     public void ProcessRequest (HttpContext context) {
 2:         context.Response.ContentType = "text/plain";
 3:         context.Response.AddHeader("X-RemoteIP", HttpContext.Current.Request.UserHostAddress);
 4:         context.Response.Write(HttpContext.Current.Request.UserHostAddress);        
 5:     }

This simply writes the IP address the handler is accessed with, to the response as well as to a custom http header. I then deployed this handler to my website.

Next, writing the PowerShell script, was equally simple; we can simply use the handy System.Net.WebClient class:

 1: $ipFinderHost = "http://www.somedomain.org/GetIP.ashx"
 2: $c = new-object System.Net.WebClient
 3: $c.DownloadString($ipFinderHost)

And voila, I have a PowerShell script that displays my public IP address. And, since I have the PowerShell Community Extensions installed, I can use the set-clipboard cmdlet to copy it to the clipboard.

 1: get-myip | set-clipboard

Much nicer than manually copying from the text in a browser :-) If you decide to use this script yourself, obviously you will need to change the URL in the script to where you have deployed the GetIP.ashx handler.