Next generation's garbage RSS 2.0
# Thursday, June 19, 2008
SharePoint has a great API for most things, but some of things seem a bit lacking.

I recently had a need to auto-create folders inside a document library. Basically, like mkdir with command extensions does on the command line. If directory x exists, but x\y doesn't, mkdir x\y\z will mkdir x\y and mkdir x\y\z.

After some struggling, here's what I ended up with:

    Public Shared Sub CreateDocLibFolders(ByVal url As String)
        Using site As New SPSite(url)
            Using web As SPWeb = site.OpenWeb()
                If url.StartsWith(web.Url) Then
                    Dim folder As SPFolder = web.RootFolder
                    For Each segment As String In url.Substring(web.Url.Length + 1).Split("/")
                        Dim nextfolder As SPFolder = web.GetFolder(folder.Url & IIf(folder.Url.Length > 0, "/", "") & segment)
                        If Not nextfolder.Exists Then
                            folder = folder.SubFolders.Add(nextfolder.Name)
                        Else
                            folder = nextfolder
                        End If
                    Next
                End If
            End Using
        End Using
    End Sub


Okay, I know it doesn't look like much, but that code represents some hard won knowledge. The main thing was dealing with folders that had spaces in them. Before, I was System.Web.HttpUtility.UrlDecode()ing them, but my use of .Name on a .Exists=false proved to be much more elegant. Even though I'm doing a GetFolder on a escaped url, the .Name property returns a nice, suitable for passing into SubFolders.Add(), de%20ed name. But why use this ugly indirect path string building technique? Well, I could not find an exception-free way of doing existence testing of a folder other than web.GetFolder() which, of course, needs a web relative url -- this lead to the more clunky looking GetFolder expression.
RaiseEvent OnReligiousArgument
For the two people that read this blog (me and uh, that might be an exagerated figure) the reason my snippets have been in VB.NET lately is because I think VB.NET is underloved in the SharePoint community. VSEWSS, for example, is a C# only club. Heck with that. It doesn't provide enough juice to justify the opaqueness of its wsp builder. VB.NET has some nice features and I like taking advantage of them -- I know both cold and I make no apologies for choosing VB.NET. If you are one of those C# 1337ists... run the benchmarks and tell me its so much better. Tell me what it does so much better that it makes up for the utter lack of exception filters, XML literals (VB9), pleasant event raising, beyond 1980s-era switch/select case, optional parameters, automatic by-reference parameters for callers, array resizing, and procedure scoped static vars. I'm not saying C# is worse -- it's like the difference between ibuprofen and acetaminophen. Minor advantages in some edge cases both ways but they all fix most headaches.

I've seen some comparisons between the two languages before on the net, but none seemed entirely complete. If I ever am put in jail with nothing but a toilet and a laptop for a few years, perhaps I'd blog /the/ definitive list.

For those of you thinking of writing in your reasons why C# is soooo superior to VB.NET, please refer to the Logical Fallacy article on Wikipedia before embarrassing yourself. Reasons like "real programmers use semicolons" or "only a moron would use a language with the word 'basic' in the name" will be ridiculed mercilessly. There are some valid arguments for C# and one could make an equally compelling valid case for it over VB.NET.

Thursday, June 19, 2008 2:20:09 AM (US Mountain Standard Time, UTC-07:00)  #    Comments [1] -
.NET Internals | SharePoint
# Thursday, June 12, 2008

SharePoint advertises the fact that you can access files on a document library via WebDAV. This is done via \\{server}\{site}\{doclibname}\ and you can easily get to it with the list menu under "Actions", "Open with Windows Explorer". A lesser known fact is that you can also use WebDAV to access the attachments collection of a list with attachments enabled. This is done via \\{server}\{site}\Lists\{listname}\Attachments\{listitemid}\

You should be aware that the WebDAV folder for the list item will not exist until a file has been added to the attachment collection. If you need it to always exist, you can make an ItemAdded event handler that simply adds a file and deletes it, like this:

Public Overrides Sub ItemAdded(ByVal properties As Microsoft.SharePoint.SPItemEventProperties)
   Const tempFileName As String = "deleteme.txt"
   If item.Attachments.Count = 0 Then
      Try
         Me
.DisableEventFiring()
         item.Attachments.AddNow(tempFileName, System.Text.Encoding.ASCII.GetBytes("This is a temporary file. If you find it, please delete it."))
         item.Attachments.DeleteNow(tempFileName)
         ' Here we also save a WebDAV hyperlink
         Dim u As New Uri(item.Attachments.UrlPrefix)
         item("AttachmentsLink") = String.Format("file://{0}{1}, Attachments", u.Host, u.AbsolutePath))
         item.Update()
      Finally
         Me.EnableEventFiring()
      End Try
   End If
End Sub

In the code above, I also set a hyperlink field so the user has easy access to the WebDAV view of the list item. I simply added a hyperlink column called "AttachmentsLink" to the list.

If you are having trouble using the WebDAV access, be sure that your WebClient service is enabled and started, which is NOT the default on Windows Server 2003.

There is a series of ItemAttachment events available and as I mentioned before, the documentation for them is not very good. Hint: properties.AfterUrl will indicate the added file. .BeforeUrl will indicate the file being deleted.

BUG: The thing to watch out for is that when using WebDAV, the ItemAttachment events don't fire, but instead, an item event fires with .AfterUrl or .BeforeUrl set, which it wouldn't ordinarily -- you can use this fact to choose to reroute Item events to the appropriate ItemAttachment events in your event code. It would be nice if you could poke in the proper properties.EventType, but it's read-only so you need to make sure that any part of your ItemAttachment event code can handle that.

Public Overrides Sub Item{Whatever}(ByVal properties As Microsoft.SharePoint.SPItemEventProperties)
   ' Reroute for WebDAV event bug
   If properties.AfterUrl IsNot Nothing AndAlso properties.AfterUrl <> "" Then ItemAttachmentAdding(properties) : Exit Sub 'or ..Added( if -ed event.
   If properties.BeforeUrl IsNot Nothing AndAlso properties.BeforeUrl <> "" Then ItemAttachmentDeleting(properties) : Exit Sub 'or ..Deleted( if -ed event

   ' Normal event code follows

End Sub

Thursday, June 12, 2008 4:50:50 PM (US Mountain Standard Time, UTC-07:00)  #    Comments [0] -
SharePoint
# Thursday, June 05, 2008

It's not at all clear from the documentation nor is it logically located in the object model, but when you get a SharePoint attachment event (like ItemAttachmentAdding, ItemAttachmentAdded, ItemAttachmentDeleting, ItemAttachmentDeleted) you get the properties.Attachment collection, but the affected attachment is indicated by the properties.AfterUrl property which gives a web.Url relative url to the attachment being evented on.

Thursday, June 05, 2008 4:09:49 PM (US Mountain Standard Time, UTC-07:00)  #    Comments [0] -
SharePoint
# Friday, May 16, 2008

Not actually supported. You really need to -o backup your SC before you do it. If you didn't, try at least to backup your 12.0/Secure key in regedit and copy the \Windows\SysMSI\*\*.cer. The content is PKI protected. I've dorked up a WSS3 install royally this way.

Friday, May 16, 2008 12:11:30 AM (US Mountain Standard Time, UTC-07:00)  #    Comments [0] -
SharePoint
# Friday, May 02, 2008

I just noticed that you can use a regular SharePoint calculated field to create a calculated Url or email address. If the result of your calculated field contains text that looks like a url or an email address, SharePoint will render it as such, <a> wrapping it. This is the same behavior as regular text fields. Nifty.

Friday, May 02, 2008 11:28:38 AM (US Mountain Standard Time, UTC-07:00)  #    Comments [0] -
SharePoint
# Thursday, April 24, 2008

When running the install for VSeWSSv11.exe, do you get:

<lame>
"This product can only be installed if Windows SharePoint Services 3.0 has been installed first."
</lame>

Seriously? So this means I can use Windows XP or Vista to develop WSS stuff? Boo. The download page does say it requires Windows Server 2003 or 2008. Boo, I say.

Merge this .reg

Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Shared Tools\Web Server Extensions\12.0]
"SharePoint"="Installed"

and try again. Yay! Of course to really work on SharePoint stuff you'll also need various dlls like Microsoft.SharePoint.dll.

gacutil -i Microsoft.SharePoint.dll
gacutil -i Microsoft.SharePoint.Security.dll

Ah... much better. But it is still pretty weak. I prefer to use plain projects and use a custom build action to cab it up.

Thursday, April 24, 2008 1:37:01 PM (US Mountain Standard Time, UTC-07:00)  #    Comments [0] -
SharePoint
# Wednesday, January 23, 2008

In SharePoint, you can create custom properties for User Profiles. Additionally, you can have search index those, but be aware that a search crawl must occur after you add the user profile property for search to even be aware of it. This explains why after adding a custom property in User Profiles, you cannot see it in search's metadata property mapping.

Wednesday, January 23, 2008 3:07:40 PM (US Mountain Standard Time, UTC-07:00)  #    Comments [0] -
SharePoint
# Tuesday, November 20, 2007
I wanted to pass along some key new things to check out from Microsoft:
  • The big one is Visual Studio 2008. It has been released including Express Editions. You definitely want to check this out at msdn.com/express.
  • Also, for you math heads out there, check out the new Word 2007 add-in, "Microsoft Math". Get it at download.microsoft.com - search for officemath.
  • For all you who have lamented about having to fill the same forms over and over at the doctor's office, check out HealthVault (healthvault.com). It is a platform for holding personal information (like the usual stuff you fill out on those forms) and holding ongoing data (like blood glucose levels synced from compatible monitors). You can choose what data to share with whom, for example, you can share your heart rate data to your exercise group or family to show your progress.
  • For the bean counters, there's Office Accounting 2008, including an Express edition. This new version includes online banking service integration. If you're running or thinking about Intuit's Quikbooks, check this out at office.microsoft.com/accounting.
  • Search Server 2008 now includes an Express edition. This gives you web search of your web and disk content. The release candidate is available at microsoft.com/enterprisesearch
  • SQL Server 2008 November CTP - microsoft.com/sql

I normally scoff at blogs that are nothing but repeaters for Microsoft's marketing department, so I've tried to keep the descriptions unhyped. Additionally, these are all things I will be working with in the near future, so expect to see more information related to these soon.

Tuesday, November 20, 2007 12:16:01 PM (US Mountain Standard Time, UTC-07:00)  #    Comments [0] -
Office 12 | SharePoint
# Friday, November 02, 2007

Scenario: You just made a nice DVWP and you exported it and mounted it on another page and kaboom -- FAIL.

Unable to display this Web Part. To troubleshoot the problem, open this Web page in a Windows SharePoint Services-compatible HTML editor such as Microsoft Office SharePoint Designer. If the problem persists, contact your Web server administrator.

Whoops. Different site. Even though the DVWP references the list by GUID, it doesn't work cross-site. Here's how to fix that.

Leave the broken DVWP where it is. Add another DVWP on the same page, in the Data Source Library, click "Connect to another library..." and point it at the site where the data came from. You should now be able to expand the lists/libraries and insert that. Now, just grab the stuff inside <SharePointWebControls:SPDataSource> and copy that over the broken one's data source. Throw away the temporary web part and you should be good to go.

Friday, November 02, 2007 11:03:22 PM (US Mountain Standard Time, UTC-07:00)  #    Comments [0] -
SharePoint

I thought I saw Heather Solomon blog about how to do this, but I couldn't find it to reference here. Anyway, I wasn't really excited about the way she described, so I tried something else.

The problem is that SPD doesn't want you to customize a publishing page. You can detach it from the page layout, but that's kinda lame.

Try this instead:

  1. Make a copy of the page where you want a custom DVWP added.
  2. Detach the copy from the page layout
  3. Edit that page in SPD.
  4. Add and customize a DVWP.
  5. You might have to add DVWP to the webpart gallery - go to root admin, web parts, add.
  6. Now, export that DVWP which you can do from the browser.
  7. Upload it to the webpart gallery
  8. Mount it on the page you started with; the one that is still attached to the page layout.

Edit: You can short cut that a bit - after export, just go to the advanced toolpane, and import from there.

Friday, November 02, 2007 4:39:05 PM (US Mountain Standard Time, UTC-07:00)  #    Comments [0] -
SharePoint

Yes, yes, I hear you anti-table zealots, but this is cool. (I'll have to blog my thoughts about this someday, along with the other religious argument about nothing but stored procedures accessible to code.)

Scenario: You have a table that will have n columns, where n is determined at run time and you want the columns to have equal width, for example, a table that is 100px wide with 4 columns should render 25px wide columns, 5 wide, 20px.

Why is this useful? SharePoint or ASP.NET SitePath menus.

Here's how:

table tr td { width:5%; }

When the table renders and sums up the 5%s and gets only 20 or 25% total, it scales that up to be 100% and the cell width percentage scales up with it.

see it at http://hafthor.com/equalwidthtables.html

I haven't tested this non-quirks mode, but it does work in FireFox and IE7.

[Edit 2007-11-04] I have tested this in xhtml strict mode (IE7 and FireFox) - it still works.

see it at http://hafthor.com/tricks.html

[Edit 2007-11-05] Dang. FireFox doesn't render this the way I wanted when in xhtml strict mode. The issue wasn't apparent until the overall width wasn't really wide. But, I tried those pages on iPhone Safari and they looked okay.

Friday, November 02, 2007 2:30:28 PM (US Mountain Standard Time, UTC-07:00)  #    Comments [0] -
HTML | SharePoint
Archive
<November 2008>
SunMonTueWedThuFriSat
2627282930311
2345678
9101112131415
16171819202122
23242526272829
30123456
All Content © 2008, Hafthor Stefansson - Disclaimer: The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way. - Sign In