July 2004 - Posts
Here's something that mired me down for several hours, so may it be Googled and seen and used by Sharepoint developers:
We're developing a solution right now based on SPS and WSS sites, under several different Site Collections, that involves copying files between sites.
The copying itself is done the same as the MSDN samples show - adding the byte stream to the FileCollection of the destination library - but since we're just passing the bits, the file's metadata isn't automatically copied from one List to the other.
If we're copying Office documents, we have automatic demotion and promotion of metadata properties from the Sharepoint List into the document, which then goes back into the new list. But if we're copying non-Office documents, the metadata is simply lost.
This was bypassed with a simple function after copying that also synchronizes the metadata - but that's where I ran into a strange anomaly having to do with SPFieldLookups - fields that derive their list of possible values from a list in the site.
The format that is saved in the metadata for these kind of fields contains both the identifier of the item in the lookup-list, and the actual string to be displayed, in this format:
“1;#myValue” - with myValue being shown in the list.
Now I want to copy this string from one SPListItem to another - but keep getting strange SPExceptions saying that the data is in an invalid format and suggesting that it is, perhaps, read-only. Preposterous, of course.
More digging and hacking showed that in order to copy the value, we only have to copy the number, not the value.
It DOES make sense, now that I understand it - I only want to pass the ID, after all, not the whole string value - that's why it's a lookup field. I assume that it's stored inside the list for caching, so we won't have to go to the lookup list every time, but still - an explanation, a sample or a meaningful error message would have been appreciated.
Using System.DirectoryServices to manage IIS servers and directories is a long-established practice (or is it? Should I elaborate on that? Write a short article?), but I ran into a problem today when I wanted to turn an ordinary directory under IIS (6.0) into an Application. It seems that among the many Metabase properties available, the only one relevant is AppRoot, and the MSDN strongly urges one not to touch it since it is managed internally.
The alternative is simply to access the IisWebDirectory object (part of the IIS ADSI Object model) and call the AppCreate (or AppCreate2, or AppCreate3 under IIS6) to create the application.
Very nice and simple, except that I'm working with a DirectoryEntry object and don't have AppCreate to save my life.
The thing to do in this case is to access the NativeObject property of the DirectoryEntry, cast it into an IisWebDirectory, and call the method – but for some reason, I don't seem to have that class registered anywhere. The IIS Adsi object model (as added via References -> COM -> Active DS IIS Extension or Active DS IIS Namespace) don't seem to have IisWebDirectory or IisVirtualWebDir defined, which means I am quite stumped. Looked around for it, in the Registry and other common COM hangouts, but couldn't find any reference.
My final solution was to simply bypass the problem using direct means – reflection:
DirectoryEntry vdir = new DirectoryEntry ("IIS://localhost/W3SVC/1/Root/MyVDir");
Object nativeObject = vdir.NativeObject;
native.GetType().InvokeMember("AppCreate3", BindingFlags.InvokeMethod, null, native, new object[] {2, "DefaultAppPool", false}); // 2 means to use an Application Pool.
Is there a slightly neater solution? Does anyone know where the IisWebDirectory object is hiding?
I am not a SQL Server Guru, I admit. Far from it, actually. But still, this shouldn't be this hard.
I was cheerfully punching away Sharepoint code on my Win2003 machine, when suddenly the power died. Cries of alarm, black smoke from the generator - the works. Not too much of a problem, since I am a reflexive (not to say spasmodic) CTRL-S presser, so it was just a matter of waiting for the power to come back and resume working.
Except that when it did, it seemed my SQL Server (2000, sp3a) decided to call it quits. Whenever I would start the service, it would immediately after launching die again, with an event-log message that the LSN passed to the 'model' database was incorrect.
Some checking revealed that the LSN is the Log Sequence Number, and my guess is that the power failure happened exactly while it was processing transaction logs - but should that be fatal?
Furthermore, if it is - shouldn't there be any way of clearing it up? Is there no command-line tool to let me declare the DB consistent?
What I was forced to do, eventually, is copy my MBF files aside, run the rebuildm.exe command to rebuild the Master database from the original CD, and then re-attach my databases - luckily unharmed and unchanged.
At last, I have a glowingly positive, happily cheerful and satisfyingly pleased entry instead of my usual rant.
I installed the Whidbey Beta 1 build yesterday, and immediately started checking out the beta of VSTOv2. After the grief I went through with the Smart Documents API, I wanted to see if the much-anticipated ActionsPane interface gives me a decent replacement.
Two hours of API-learning and online help-reading later, I had in my hands a rather neat (though not very innovative) CD catalog template, with a fully functional and interactive task-pane
A reminder to those lost:
The SystemInformation class, containing many useful tidbits of information like the running computer name, number of monitors and whether we're on a network, resides in System.Windows.Forms of all places.
Sure, most of the information there is GDI and Forms related, but why do I need to include and reference this in a console application if all I want is the name of the computer? A more generic SystemInformation should be sitting directly under the System namespace.
VB 2005 has the My namespace for easy access to such information - but this is basic enough to be CLR-wide.
More Posts