Getting Absolute URLs in SharePoint

This is a bit of a reminder for myself, but quite a lot of the URLs you deal with in SharePoint development are relative – that is, something like an SPList.DefaultViewURL might be:

/sites/web/lists/list/allitems.aspx

That’s fine … but sometimes you need a full absolute URL. For example, you might be sending out an email with a hyperlink in it – a relative URL ain’t going to cut it.

Fortunately, there is a very useful function – SPSite.MakeFullUrl() :

Returns the full URL for the specified server-relative URL.

That’s great – but it raises some questions. What about Alternate Access Maps? What URL would be returned? Well, predictably, the URL used in the SPSite Constructor in the first place. Mostly, they either accept a URL (which defines a zone), or they accept a GUID and an SPUrlZone value. There is a constructor that just accepts a GUID – which will then use the default zone. Similarly, the constructor accepting a GUID and SPUserToken also uses the Default Zone.

(If you open it up in reflector, you can see it just calling a private constructor passing the SPUrlZone.Default value).

Getting Absolute URLs in SharePoint

"To save to the server, correct the invalid or missing required properties"

I’ve been working on a custom field for, well, a while now, and after making some changes I started to get the error “To save to the server, correct the invalid or missing required properties” when trying to edit a document and save the changes back in Word 2007. This was a little strange, as I’d already sorted out hiding the custom field from the document information panel, and things had been working fine since then.

New documents seemed to be alright, but the older ones weren’t. So, maybe the problems were all the old documents, rather than my field.

Eventually, I came across this knowledgebase article – so I “inspected” the document, removed any of it’s custom data, and resaved it – and it worked fine.

What I think happened here was, I was testing different settings for Content Approval and Versioning on my document libraries. I think the troublesome documents were created when one of those was set to be ‘on’, and I subsequently turned it ‘off’. This meant that the document actually had extra data that referred to a column that no longer existed (I think) – which probably means this is related to Content Approval.

But I’d be curious if anyone else has managed to cause this error, and how they did so.

"To save to the server, correct the invalid or missing required properties"

Inconvenient GetCustomProperty and SetCustomProperty

So, I’m working on a custom field definition for SharePoint. My field has a few custom properties that you need to fill in when you create it. However, after creation, those fields were empty – they were simply never set. You could then update them, and that worked fine, but creation was broken.

The code I’d inherited was trying to solve this problem (it’s a known issue) this way – which is a bit ugly. It also holds memory for the Dictionary of values that, as far as I could see, was only being freed on IISReset. Yuck. And it didn’t work in our code, despite matching the example in that thread quite closely.

Fortunately, I came across a neat post on Gunnar Peipman’s blog – Temporary Solution for GetCustomProperty an SetCustomProperty Errors. I don’t like using reflection to invoke the methods I need to use, but at least it’s a solution, even if not ideal. And it works!

Please go to Gunnar’s post – but just in case his blog goes down, I’m going to shamelessly plagiarise his code below…

Thanks Gunnar! Continue reading “Inconvenient GetCustomProperty and SetCustomProperty”

Inconvenient GetCustomProperty and SetCustomProperty

Registering EventHandlers against ContentTypes

In SharePoint, Event Handlers (or Event Receivers – whichever terminology, a child of SPItemEventReceiver) can be registered against lists/libraries. You can do this through an SPWeb (site) scoped feature, declaratively or programmatically with an SPEventReceiverDefinition.

Unfortunately, you can’t declaratively register event receivers at the SPSite (Site collection) level – which would be fantastic – just turn on the feature and across all your site collection lists/libraries of a give type would get additional event receivers. Personally, I think this may be a bug; I don’t see why this shouldn’t work at the SPSite level.

Anyway, there is still another option – we could register our event against a particular Content Type. This is a less often used approach, which raises two questions – how do you do it, and what happens to child Content Types? Continue reading “Registering EventHandlers against ContentTypes”

Registering EventHandlers against ContentTypes

Bloody Wikis in SharePoint 2007

The other day I blogged about how weird ‘Blog Posts’ are. Well, I’ve also been looking at Wiki pages…

So, first off, as a reminder to myself, Wiki libraries are defined in the ‘WebPageLibrary’ feature. Took a while to track that down.

Second off, calling the SPListItem.Title for a Wiki pages causes an ArgumentException. (Waldek Mastykarz has written about this). Kind of makes sense – the wiki item doesn’t have a title – but I’d prefer it returned the filename (without extension) instead. That would seem a more useful compromise.

Bloody Wikis in SharePoint 2007

Weird ContentType of Blog Posts

Okay, this is weird.

I’m trying to do something with various types of item, including Blog Posts, in SharePoint. Naturally, I’m getting the SPListItem for them, and then the SPListItem.ContentType, so I can check what kind of item is it. The weird thing is, if I try to get a Blog Post, the SPListItem.ContentType is NULL. Continue reading “Weird ContentType of Blog Posts”

Weird ContentType of Blog Posts

Themes in SharePoint 2010

So, followers of this blog will know that I seem to get quite a lot of branding tasks, and that I don’t much like themes, preferring to use either the AlternateCssUrl and Features instead. Features are great – you can deploy the CSS/image files you need, set master pages (and handle Meeting Workspaces), themes, AlternateCssUrls. They can also add HTTP Modules for branding Application Pages.

Themes, on the other hand, are fiddly to install automatically, don’t work on the DatePicker, and are individual to each site once applied. To pick up changes to a global theme, you’d have to apply a different theme and then reapply the desired theme – for every site.

Well, that was with SharePoint 2007. SharePoint 2010 is a bit different, as I got to find out on a Combined Knowledge course in January (and this is the first time I’ve managed to write about it!) Continue reading “Themes in SharePoint 2010”

Themes in SharePoint 2010

Hide a custom field from the Document Information Panel

So, I’ve been working with a custom field type recently. It’s quite a complicated one – I’ll not go into details – but we did hit a problem with it. When a Word document was opened it would try to display our field in the Document Information Panel, which isn’t really possible, and caused Word to die in a horrible fashion. I forget the exact error we were getting, but it was something to do with the XSN being invalid.

What we really needed was a way to set that the property wasn’t to be shown in the Document Information Panel. However, there is no easy way of doing this with a purely programmatically created column. There are properties on the SPField object that can be accessed programmatically, and the CAML for a FieldRef can set ShowInFileDlg – but there isn’t an obvious way to set this value from C# code.

Naturally, that’s what we wanted to do. Well, there is a combination approach – the SPField.SchemaXml property allows us to get/set the CAML that defines the field.

So, I came up with this static function:

static void SetShowInFileDlg(SPField f, bool value)
        {
            XmlDocument fieldSchemaXml = new XmlDocument();
            fieldSchemaXml.LoadXml(f.SchemaXml);
            XmlAttribute attr = fieldSchemaXml.CreateAttribute("ShowInFileDlg");
            attr.Value = value.ToString().ToUpper();
            XmlNode fieldXmlNode = fieldSchemaXml.SelectSingleNode("Field");
            XmlAttributeCollection fieldAttributes = fieldXmlNode.Attributes;
            fieldAttributes.Append(attr);

            f.SchemaXml = fieldXmlNode.OuterXml;
            f.Update(true);
        }

I’m not sure what happens if you’re trying to update an already widely used column – will it update all content types that that column – but this worked for us.

Hide a custom field from the Document Information Panel

Date Formats in XSL with ddwrt

Previously I’ve blogged about using ddwrt to format dates and datetimes. Well, today, I found myself trying to figure it out again, so here is a reminder. Remember, one of the big advantages of this (in the UK at least, where we are UTC time half the year) is that the DateFormat function accounts for daylight savings (i.e. the difference between GMT and BST)

Add this to the xsl:stylesheet tag at the top:

xmlns:ddwrt="http://schemas.microsoft.com/WebParts/v2/DataView/runtime"

Then you can use something like the following (where item_date is an XSL variable with our date in it):

<xsl:value-of select="ddwrt:FormatDate(string($item_date), 2057, 15)" />

Here the FormatDate function is taking the string of the date, formating it for Great Britain’s locale (2057), and specifying an output format (15). Output formats vary by locale, and not all seem to be valid. I found that when I tried a format of ‘2’, for example, that I got an XSL error.

This is a particularly useful with the Content Query Web Part and the RSS Feed Web Part

Date Formats in XSL with ddwrt

Curious case of Microsoft.Office.Server.ServerContext.Current

So, this is the weirdest bug I’ve seen in quite some time. I’d inherited some code, which includes a settings page in the _layouts directory. It’s a pretty normal page – nothing particularly bad about it, and it seemed to work nicely. Then I received a call about an error with it:

Now, here is the weird thing. When I started to examine it, I tried to replicate the problem. And I realised that the page worked when I accessed it from the server, but threw an ArgumentNullException when I accessed it from a client.

Yes, you read that right. What machine you browsed to the page on mattered. The browsers were the same. The code worked when viewed on the server, and failed when viewed from the client. When I eventually fixed it, I swapped between the broken and fixed code a few times to prove it – this really was the behaviour! Continue reading “Curious case of Microsoft.Office.Server.ServerContext.Current”

Curious case of Microsoft.Office.Server.ServerContext.Current