Dominic Cronin's weblog
Over at the Indivirtual blog, I've posted about a diagnostic technique for use with the SDL Web broker database.
One of the basic operations that a Tridion developer needs to be able to do is getting the full XML of a Component. Sometimes you only need the content, but say, for example that you're writing an XSLT that transforms the full Component document - you need to be able to get an accurate representation of the underlying storage format (OK - for now let's just skate over the fact that different versions have different XML formats under the water)
In the balmy days of early R5 versions, this was pretty easy to do. The Tridion installation included a "protocol handler", which meant that if you just pasted a TCM URI into the address bar of your browser, you'd get the XML of that item displayed in the browser. This functionality was actually present so that you could reference Tridion items via the document() function in an XSLT, but this was a pretty useful side effect. OK... you had to be on the server itself, but hey - that's not usually so hard for a developer. If you couldn't get on the server, or you found it less convenient, another option was to configure the GUI to be in debug mode, and you'd get an extra button that opened up some "secret" dialogs that gave you access to, among other things, the XML of the item you had open in the GUI.
Moving on a little to the present day, things are a bit different. Tridion versions since 2011 have a completely different GUI, and XSTL transforms are usually done via the .NET framework, which has other ways of supporting access to "arbitrary" URIs in your XSLT. The GUI itself is built on a framework of supported APIs, but doesn't have a secret "debug" setting. However, this isn't a problem, because all modern browsers come fully loaded with pretty powerful debugging tools.
So how do we go about getting the XML if we're running an up-to-date version of Tridion? This question cropped up just a couple of days ago on my current project, where there's an upgrade from Tridion 2009 to 2013 going on. I didn't really have a simple answer - so here's how the complicated answer goes:
My first option when "talking to Tridion" is usually the core service. The TOM.NET API will give you the XML of an item directly via the .ToXml() methods. Unfortunately, someone chose not to surface this in the core service API. Don't ask me why? Anyway - for this kind of development work, you could use the TOM.NET. You're not really supposed to use the TOM.NET for code that isn't hosted by Tridion (such as templates) but on your development server, what the eye doesn't see the heart won't grieve over. Of course, in production code, you should take SDL's advice on such things rather more seriously. But we're not reduced to that just yet.
Firstly, a brief stop along the way to explain how we solved the problem in the short term. Simply enough - we just fired up a powershell and used it to access the good-old-fashioned TOM.COM. Like this:
PS C:\> $tdse = new-object -com TDS.TDSE PS C:\> $tdse.GetObject("tcm:2115-5977",1).GetXml(1919)
Simple enough, and it gets the job done... but did I mention? We have the legacy pack installed, and I don't suppose this would work unless you have.
So can it be done at all with the core service? Actually, it can, but you have to piece the various parts together yourself. I did this once, a long time ago, and if you're interested, you can check out my ComponentFactory class over on a long lost branch of the Tridion power tools project. But that's probably too much fuss for day to day work. Maybe there are interesting possibilities for a powershell module to make it easier, but again.... not today.
But thinking about these things triggered me to remember the Power tools project. One of the power tools integrates an extra tab into your item popup, giving you the raw XML view. I'd been thinking to myself that the GUI API (Anguilla) probably had reasonably easy support for what we're trying to do, but I didn't want to go to the effort of figuring it all out. Never fear: after a quick poke around in the sources I found a file called ItemXmlTab.ascx.js, and there I found the following gem:
var xmlSource = $display.getItem().getXml();
That's all you need. The thing is... the power tool is great. It does what it says on the box, and as far as I'm concerned, it's an exceedingly good idea to install it on your development server. But still, there are reasons why you might not. Your server might be managed by someone else, and they might not be so keen, or you might be doing some GUI extension development yourself and want to keep a clear field of view without other people's extensions cluttering up the system. Whatever - sometimes it won't be there, and you'd still like to be able to just suck that goodness out of Tridion.
Fortunately - it's not a problem. Remember when I said most modern browsers have good development tools? We use them all the time, right? F12 in pretty much any browser will get you there - then you need to be able to find the console. Some browsers will take you straight there with Ctrl+Shift+J. So you just open the relevant Tridion item, go to the console and grab the XML. Here's a screenshot from my dev image.
So now you can get the XML of an item on pretty much any modern Tridion system without installing a thing. Cool, eh? Now some of you at the back are throwing things and muttering something about shouldn't it be a bookmarklet? Yes it should. That's somewhere on my list, unless you beat me to it.
- Install a good byte editor. I personally use a freeware tool: http://mh-nexus.de/en/
- Understand how UTF-8 works and be prepared to decode characters with a pencil and a sheet of paper. Make reference to http://www.ietf.org/rfc/rfc3629.txt and particularly the table on page 3. This way you can translate UTF-8 to Unicode.
- Use the code charts at www.unicode.org/charts to verify the character in Unicode.
E2 84 A2
11100010 10000100 10100010
I have a Windows 2012 server that I run under VMWare. I've probably mentioned this image before, as it's the one I use for my Tridion research. I'm fairly unusual in that I like to have my database server running "on the bare metal" of my laptop rather than in the Windows Server image. It's probably just perversity or masochism or whatever, but that's how I roll. What this means is that I have two network interfaces on the image: one configured as "Host only", which I use for my database connections and other "on the box" stuff, and another running NAT. Sure, you could run a development image completely isolated from the Internet, but it'd be a pain, so I run the NAT interface as well.
All good in theory, but as it turned out, it was a pain anyway, because it was taking 10 seconds to resolve a DNS name. Don't ask me why 10 seconds - presumably it was hitting some timeout and then trying an approach that worked better. Anyway - it was getting annoying. Sure I could flip out of the image to run a browser outside, but nah! Apart from anything else, I hate to be irritated by things I don't understand. I don't mind having things I don't understand, - gee, you'd go crazy! - but if it's an in-your-face irritation, that's another story.
So I poked around a bit. I could run:
in my powershell on the image and it would take 10 seconds. Natively on the laptop - instant response. So I had a quick look in the VMWare network settings. There are some obscure settings on the NAT interface for policies for automatically detecting DNS servers. But hang on - was it attempting to get DNS from the Host only interface, or the NAT one? So what would nslookup tell me:
PS C:\Users\Administrator> nslookup Default Server: UnKnown Address: 192.168.126.1 > www.yahoo.com Server: [192.168.126.1] Address: 192.168.126.1 DNS request timed out. timeout was 2 seconds. DNS request timed out. timeout was 2 seconds. DNS request timed out. timeout was 2 seconds. DNS request timed out. timeout was 2 seconds. *** Request to [192.168.126.1] timed-out > server 192.168.146.2 Default Server: [192.168.146.2] Address: 192.168.146.2 > www.yahoo.com Server: UnKnown Address: 192.168.146.2 Non-authoritative answer: Name: ds-eu-fp3.wa1.b.yahoo.com Addresses: 2a00:1288:f00e:1fe::3000 2a00:1288:f006:1fe::3000 2a00:1288:f006:1fe::3001 2a00:1288:f00e:1fe::3001 126.96.36.199 188.8.131.52 Aliases: www.yahoo.com fd-fp3.wg1.b.yahoo.com ds-fp3.wg1.b.yahoo.com ds-eu-fp3-lfb.wa1.b.yahoo.com
OK - so the first thing that this told me was that the default lookup was on my Host only interface, and that this was failing. When I manually set the server to the one on the NAT interface, boom... the response came back in a split second.
Next problem - how do I get it to default to the one that works (yes - I could also attempt to get the Host only one working properly, but not if it's easy to switch to the other - llfe's too short, and with networking, getting it to stop being irritating is much more achievable than understanding!).
After a bit of Googling I discovered that you Windows brings up the network interfaces in a specified order, and the first one becomes the "primary" interface, which in turn is used as the default for DNS and goodness knows what else. All I needed to do was change the order. I picked up a hint from The Regime and was almost surprised to find that also in Windows Server 2012, you can get to the advanced settings of the network interfaces by hitting and releasing the Alt key. (Who knows about this stuff? Isn't that just disturbing?) A couple of minutes later I was testing it and finding that it worked.
So it's all good. I still don't understand networking, but that's never been a serious itch for me.
I'm currently developing a web application which will run on Windows 2008 R2 and which is intended to run in a 64bit Application pool. This means that I'm running IIS 7.5, and that the web application is installed with the 64 bit versions of the Tridion content delivery assemblies. As you'll know if you've tried to run this kind of web application in a 32 bit process, you pretty soon get exceptions telling you that you have an invalid format. This gets a little inconvenient if you just start to debug your web application in Visual Studio. By default, if you have a page selected, and hit the big green Run triangle, the page will launch in IIS Express. If you have IIS 7.5, then IIS Express runs a 32 bit process, so the default setup just isn't going to work for you.
So - what to do? I had two options:
- Configure the properties of the web application to debug using IIS rather than IIS Express
- Launch the web page directly from the browser, and attach the debugger to the correct w3wp.exe process.
To be honest, the second of these was the choice that most matched my usual debugging approaches. Having said that, I did try the first approach, but so far without success. Visual Studio 2012 has frozen on me a few times while trying this. I'm interested if anyone has any tips on getting this working, but right now, I'm happy enough that I was able to succeed in attaching a debugger to w3wp.exe.
My biggest challenge was to figure out which process I wanted to attach to. On my development server, I have quite a few web sites running, and it's not altogether obvious which w3wp.exe to attach to. Attaching to them all might work in a trivial case, but realistically, it takes quite a while to load all the dlls, and adding any more processes than necessary is just going to hurt too much. So - how do you find out which process it is?
The first step is to ensure you have the IIS powershell provider installed on your server. These days, this is shipped as a module, so if it's available on your system, you should be able to open a powershell and type:
If the response includes "WebAdministration" you are good to go. Just import the module as follows:
If this succeeds, you should be able to "change directory" into the IIS provider. (Although a PowerShell purist might prefer set-location... whatever floats your boat!)
If you can't find the module, then go into the Server manager, and check that you have the relevant role services for IIS installed. On other platforms, you might find that you can install it from the WebInstaller from the MSDN web site.
Now you're ready to find the process that you want to attach to: Assuming that your application pool is called "MyApplicationPool", then you can list its worker processes like this: (or use "dir" or "ls", either of which is an alias for "gci")
> gci IIS:\AppPools\MyApplicationPool\WorkerProcesses
Process State Handles Start Time Id -------- ----- ------- ---------- 2608 Running 776 1/2/2013 6:55:33 PM
This assumes, of course, that your app pool is actually running, but you'd have made sure it was before trying to debug it, right. Anyway - as you can see, the process id is there just to read off, and you can get straight on with your debugging session.