In setting up a Records Center I was trying out the Content Organizer and Drop Off Library. I configured a Send To location and an Organizer Rule to get my document to my new Record Library. It worked great! However, since this was just a test to make sure everything mapped over correctly, I wanted to delete the test document and I got this error:
This item cannot be deleted, moved, or renamed because it is either on hold or is a record which blocks deletion.
Uh… so how do I undeclare it? The answer is that with record libraries, all documents are not only automatically declared records, manual declaration/undeclaration is disabled by default. This all makes sense considering this is in the Record Center and it is a Record Library. But to delete your document, you will have to disable these settings (Temporarily).
1. Turn off Automatic Record Declaration
Go to your Library Settings for your Record Library. Under Permissions and Management choose Record declaration settings:
Uncheck the box in the Automatic Declaration section then press OK:
2. Enable Manual Declaration of Records
Go back into the Record declaration settings since the Manaual Record Declaration Availablity section will now be enabled. Choose Always allow the manual declaration of records:
3. Undeclare the Document as a Record
Go back to the Library and choose the document you want to delete. In the drop down menu, choose Compliance Details:
In order to remove the document, it can’t be a record nor be part of any holds. In the compliance details popup remove the document from hold (if necessary) and click the Undeclare record link. In the confirmation dialog choose OK to undeclare.
4. Delete the Document
Kill that sucker.
5. Put Everything Back in Place
Those settings were on the library for a good reason. Once you’ve finished your testing or no longer need to delete any individual records, you should go back to your library settings and reenable the default settings (Follow these steps backward).
If for some reason, you want to delete the Record Library itself. You will need to remove every record from the library following the above steps and then run the “Hold Processing and Reporting” job in Central Admin. This let’s SharePoint know there are no records in there and the standard deletion link will appear in the Library Settings.
We are utilizing our search functionality much more in SharePoint and one of the more annoying things we found was how PDF files are treated by default. In the search results, the link goes to the DispForm.aspx for the item rather than directly to the item.
The obvious fix is to install an iFilter. Unfortunately, this isn’t always an option. For us, the performance and crawl delay issues didn’t make up for the benefit of having these documents indexed. Fortunately, I came across this answer by daver306 on SharePoint SE that didn’t get a lot of attention but worked perfectly for me.
I wanted to write it up with some added detail and share my experiences. Not only does this allow you to link directly to your PDFs within the search without the use of XSL and allows KnowledgeLake queries to open PDFs directly within the KnowledgeLake Viewer, it’s actually pretty simple to do.
1. Add PDF as a File Type
Within Central Admin, go to your Search Administration (Manage Service Applications > Search Service). From there click on the File Types link under Crawling on the left:
If pdf is not listed, click the New File Type button and type pdf (no period needed) in the File extension box and click OK:
2. Restart the Search Service
This is a very important step. I originally tried to skip it to spare myself some hassle and ended up having to repeat the crawl below. You will need to go to each server running the SharePoint Server Search service and stop it. You can do this through the command line or the Services panel under Administrative Tools:
Once off on all boxes, just go back through and start it again.
3. Reset Your Index
Back on the Search Administration page within Central Administration you will want to click on the Index Reset link under Crawling on the menu on the left:
Press the Reset Now button. Remember that this should be done at a time when your environment is not under heavy use or when search won’t be needed since search results will not be available until after a full crawl completes.
4. Perform a Full Crawl
If you have a pretty standard search setup, then you probably only have one content source. If not, then you already know how to start the full crawls for each of them. If you’ve just got the one, then from the Search Administration page within Central Administration click on the Content Sources link under Crawling on the menu on the left. Hover over your content source and choose Start Full Crawl in the dropdown menu:
After the crawl completes (This could be hours depending on the size of your farm), things should be working as expected. No more DispForm.aspx links in your search results!
While testing our new master page that replaces the minimal.master I noticed that depending on your permission level, things were rendering differently. If you had full permissions then things looked great, but if you were a visitor with read-only permissions things were a little off.
Taking a look at the actual page source we found that the stylesheet links in the header section looked different. With Full permissions the link to corev4.css existed, but didn’t for anyone else. Obviously permission to the corev4.css file wasn’t the issue since this was working fine on all other sites regardless of user permissions.
Some quick searching and experimentation revealed that the corev4.css link was only added to the page when the Site Actions menu was set to render. For the standard minimal.master file this is fine, but if you are depending on any of the corev4.css styles, you’ve got a problem. Fortunately, the solution is simple.
In your custom minimal.master master page find this section in the head element:
That’ll do it. The corev4.css will load regardless of the presence of the Site Actions menu and there aren’t any conflicts since SharePoint ensures it isn’t registered twice.
By default, every file you deploy using a sandboxed solution is left checked out. This can lead to problems depending on the type of site you are deploying to and/or the permissions of your end users.
This post focuses on Branding solutions, but anytime you are deploying a sandboxed solution these techniques should help you. This is especially important for Master Pages since these often need an approved/published version in order to be visible to anyone but the site administrators.
I found an interesting approach by Waldek Mastykarz where he suggests using a “Stamp” (Feature ID property) on each file and using that to find and check in each file. This was very cool, but requires you to modify the Elements.xml entry for each file to ensure that property is added and he also never addressed Master Pages which can be a bit of a special case.
For my needs, I generally take a simpler approach of just deploying my resources to one root folder and creating sub folders as needed. This makes it easier to find stuff, but it also means I don’t need to track each file individually. Obviously if you are doing something a little more extensive then you may need to take a hybrid approach of using the featureid property and/or just tracking the various folders you are deploying too. But for a simple branding solution you really just need to:
Apply your branding to each site
Publish and Approve each resource file
Publish and Approve each Master Page
All of this can be done in the FeatureActivating event with a simpler helper method:
Public Overrides Sub FeatureActivated(ByVal properties As SPFeatureReceiverProperties)
Dim siteCollection As SPSite = CType(properties.Feature.Parent, SPSite)
If siteCollection IsNot Nothing Then
Dim topSite As SPWeb = siteCollection.RootWeb
'Calculate relative path to site from Web Application root
Dim WebAppRelativePath As String = topSite.ServerRelativeUrl
If Not WebAppRelativePath.EndsWith("/") Then WebAppRelativePath &= "/"
'Enumerate through each site and apply branding
For Each site As SPWeb In siteCollection.AllWebs
If Not site.MasterUrl.EndsWith("minimal.master") Then
site.MasterUrl = WebAppRelativePath & "_catalogs/masterpage/BSmain.master"
Else
site.MasterUrl = WebAppRelativePath & "_catalogs/masterpage/BSminimal.master"
End If
If Not site.CustomMasterUrl.EndsWith("minimal.master") Then
site.CustomMasterUrl = WebAppRelativePath & "_catalogs/masterpage/BSmain.master"
Else
site.CustomMasterUrl = WebAppRelativePath & "_catalogs/masterpage/BSminimal.master"
End If
site.AlternateCssUrl = WebAppRelativePath & "Style%20Library/BSResources/BS.css"
site.SiteLogoUrl = WebAppRelativePath & "Style%20Library/BSResources/Images/BSlogo.png"
site.UIVersion = 4
site.Update()
Next
'Publish and Approve each file
Dim styleLibrary As SPList = topSite.Lists.TryGetList("Style Library")
If styleLibrary IsNot Nothing Then
Dim folders As SPListItemCollection = styleLibrary.Folders
Dim item As SPListItem = DirectCast((From i In folders Where DirectCast(i, SPListItem).Url = "Style Library/BSResources" Select i).FirstOrDefault(), SPListItem)
ApproveAndPublish(item.Folder, styleLibrary.EnableModeration)
End If
'Publish and Approve the Master Pages
Dim mpGallery As SPList = siteCollection.GetCatalog(SPListTemplateType.MasterPageCatalog)
If mpGallery IsNot Nothing Then
Dim mpages As SPListItemCollection = mpGallery.GetItems(New SPQuery With {.Query = "<Where><Or><Eq><FieldRef Name='FileLeafRef' /><Value Type='Text'>RegalIC.master</Value></Eq><Eq><FieldRef Name='FileLeafRef' /><Value Type='Text'>RegalICminimal.master</Value></Eq></Or></Where>"})
If mpages IsNot Nothing Then
For Each i As SPListItem In mpages
If Not i.File.CheckOutType = SPFile.SPCheckOutType.None Then
i.File.CheckIn("Feature Activation", SPCheckinType.MajorCheckIn)
If mpGallery.EnableModeration Then
i.File.Approve("Feature Activation")
End If
End If
Next
End If
End If
End If
End Sub
Private Sub ApproveAndPublish(folder As SPFolder, Approve As Boolean)
If folder Is Nothing Then Return
For Each subfolder As SPFolder In folder.SubFolders
ApproveAndPublish(subfolder, Approve)
Next
For Each file As SPFile In folder.Files
If Not file.CheckOutType = SPFile.SPCheckOutType.None Then
file.CheckIn("Feature Activation", SPCheckinType.MajorCheckIn)
If Approve Then
file.Approve("Feature Activation")
End If
End If
Next
End Sub
1. Apply your branding to each site
After gathering basic information about where the feature is being deployed and getting the correct reference URLs, we begin looping through every site in the sitecollection and setting the master page, sitelogo, and CSS settings to use our custom branding beginning in line 11.
The only thing different than the approach described in the Microsoft article, Deploying Branding Solutions for SharePoint 2010 Sites Using Sandboxed Solutions is that I am checking if the current master page is the minimal.master and if so, using my BSminimal.master file instead. This allows me to have both master pages deployed correctly, but it also allows me to restore these settings more accurately in the deactivating event (See my previous post).
2. Publish and Approve each resource file
To keep things simple, I keep all of my resource files in a single root folder within the Style Library. This makes looping through each subfolder and resource very simple to ensure that each one gets checked in and/or approved as necessary.
Lines 29-34 get a reference to the resource folder within the Style Library and pass that information over to a helper method called ApproveAndPublish. This method takes an SPFolder reference and a boolean indicating if approval is necessary or not. For the initial call, the folder is our resource folder and the approval setting comes directly from the Style Library and is found in the EnableModeration property of the SPList object.
The ApproveAndPublish method (Lines 55-68) is a recursive function that loops through every subfolder and checks in every file found. If Approval is required, it also marks them as approved.
This means you don’t have to track each file (either through stamping or keeping a list). This really cuts down on all the plumbing that is often necessary when working on a SharePoint solution.
3. Publish and Approve each Master Page
Unfortunately, Master Pages aren’t usually deployed to a sub folder and so the above technique for approval and check in has to be tweaked slightly. Lines 37-50 take care of this. Basically, we get a reference to the Master Page Catalog and use some basic CAML to isolate our master pages and then loop through them to check them in and/or activate them if required.
That’s all that’s required. You now have your files successfully deployed and ready to be used. Be sure to check out my previous post Branding Solution Cleanup. In that post I describe how to remove all of your solution files when your solution gets deactivated.
I found various solutions for removing your files ranging from individual file lists to marking every file with your feature ID, but for a simple Branding project all you really need to do is:
Remove usage of your Master Pages from every site referencing them
Remove your files from the Style Library
Remove your Master Page files from the Master Page Catalog
The first two can be done in the FeatureDeactivating event handler and the third can be done in the FeatureUninstalling event handler. For those that just want the code, here it is:
Public Overrides Sub FeatureDeactivating(ByVal properties As SPFeatureReceiverProperties)
Dim siteCollection As SPSite = CType(properties.Feature.Parent, SPSite)
If siteCollection IsNot Nothing Then
Dim topSite As SPWeb = siteCollection.RootWeb
'Calculate relative path to site from Web Application root
Dim WebAppRelativePath As String = topSite.ServerRelativeUrl
If Not WebAppRelativePath.EndsWith("/") Then WebAppRelativePath &= "/"
'Enumerate through each site and remove branding
For Each site As SPWeb In siteCollection.AllWebs
If Not site.MasterUrl.EndsWith("minimal.master") Then
site.MasterUrl = WebAppRelativePath & "_catalogs/masterpage/v4.master"
Else
site.MasterUrl = WebAppRelativePath & "_catalogs/masterpage/minimal.master"
End If
If Not site.CustomMasterUrl.EndsWith("minimal.master") Then
site.CustomMasterUrl = WebAppRelativePath & "_catalogs/masterpage/v4.master"
Else
site.CustomMasterUrl = WebAppRelativePath & "_catalogs/masterpage/minimal.master"
End If
site.AlternateCssUrl = String.Empty
site.SiteLogoUrl = String.Empty
site.Update()
Next
'Kill Style Library Folder
Dim styleLibrary As SPList = topSite.Lists.TryGetList("Style Library")
If styleLibrary IsNot Nothing Then
Dim folders As SPListItemCollection = styleLibrary.Folders
Dim item As SPListItem = DirectCast((From i In folders Where DirectCast(i, SPListItem).Url = "Style Library/BSResources" Select i).FirstOrDefault(), SPListItem)
item.Delete()
End If
End If
End Sub
Public Overrides Sub FeatureUninstalling(ByVal properties As SPFeatureReceiverProperties)
Dim siteCollection As SPSite = properties.UserCodeSite
If siteCollection IsNot Nothing Then
'Kill Master Pages
Dim mpGallery As SPList = siteCollection.GetCatalog(SPListTemplateType.MasterPageCatalog)
If mpGallery IsNot Nothing Then
Dim mpages As SPListItemCollection = mpGallery.GetItems(New SPQuery With {.Query = "<Where><Or><Eq><FieldRef Name='FileLeafRef' /><Value Type='Text'>BSmain.master</Value></Eq><Eq><FieldRef Name='FileLeafRef' /><Value Type='Text'>BSminimal.master</Value></Eq></Or></Where>"})
If mpages IsNot Nothing Then
For i As Integer = mpages.Count - 1 To 0 Step -1
mpages(i).Delete()
Next
End If
End If
End If
End Sub
Wow code! Alright Scriptkitties, copy away! Everyone else, here’s what we’re doing and why:
1. Remove usage of your Master Pages from every site referencing them
After gathering basic information about where the feature was deployed and figuring out the correct reference URLs, we begin looping through every site in the sitecollection and resetting the master page to the defaults beginning in line 11.
We are just undoing what was done in the FeatureActivating event. The only thing of note is that I hate when a Branding solution replaces every MasterPage with theirs and then just blindly restores v4.master. Mostly this is fine, but if one of your subsites is an Enterprise Search site or anything else using the minimal.master you’ve just wrecked it. Obviously if you know you aren’t using minimal.master then you can simplify this section. Also, I always name my minimal.master replacement in the form [Something]minimal.master to ensure this works out.
2. Remove your files from the Style Library
To keep things simple, I keep all of my resource files in a single root folder within the Style Library. Obviously I have subfolders to organize images, fonts, etc. but all of those are within my one folder. This makes finding stuff much easier, but more than that it makes removing the files super easy – Just delete that folder.
Lines 27-33 do just that. After getting a reference to the Style Library (Every sitecollection in SharePoint 2010 has one of these), grab the folder (just replace the “Style Library/BSResources” string in line 31 with your folder path) and delete.
3. Remove your Master Page files from the Master Page Catalog
There are lots of guides for deleting deployed master pages and I didn’t find any that worked. Basically every time I tried to delete a master page from within the FeatureDeactivating event I got an error about them still being used. I’m sure there’s a good reason for this (feel free to let me know in the comments), but it doesn’t really matter because as long as you followed step 1 above, it’ll work in the FeatureUninstalling event.
We simply grab a reference to the sitecollection’s Master Page Gallery and use some simple CAML to grab references to our Master Pages. Then we walk through them and delete them.
That’s it, you now have a self-cleaning solution and you are a responsible member of the SharePoint community.
When you edit pages and/or master pages in SharePoint either for branding or some other project you will eventually come across the need to link to some resource file whether it’s an image, icon, CSS, etc. When this came up for me, I realized I had no idea how to do this properly.
Sure you can hardcode a link, but if this is part of a solution (especially a sandboxed solution) then this quickly becomes an unusable option. You can use the dots to do relative links, but again this can easily break on system pages or when you need to reference site collection level items from any sub site regardless of level.
Fortunately, some quick searching found the solution I needed. I came across Bugra Postaci’s blog post on the subject and that got me going. Be sure to check it out for some background, but the basic idea is to use the SPUrlExpressionBuilder class to generate relative links. Unfortunately, this class is part of the publishing namespace and so is only available in SharePoint Server (2010) and MOSS (2007).
He gives an example of linking to an image within the Style Library of the site collection using the following code directly within the master page:
The key thing to note is the inline use of the $SPUrl command. The example shows this within an asp:Image control but this can be done in a standard tag as well (img, link, etc.).
After seeing that, I really wanted to know what other magic tokens you can use, but the Microsoft Documentaiton on the class doesn’t even show the inline $SPUrl syntax, let alone list any of the usable tokens! Doing a quick search will find you an assortment of undocumented tokens. However this can be misleading as the tokens listed in {} braces are generally only for custom actions and not for inline links (you can find examples of those lists here and here).
Here is what I’ve found by actually looking at the code using Reflector:
I was setting up a Report Server for our SharePoint 2010 Farm this morning and I ran into a show stopper. After installing SharePoint 2010 on the new server and getting it ready, I ran the SharePoint Products Configuration Wizard only to get to the PassPhrase step and be told I was entering the incorrect passphrase.
I have it written down from the original setup and I was positive it was correct, but no matter what I tried I couldn’t get it accepted. So I did a quick look-up on how to recover it. Turns out you can’t. Fortunately, you can change it without knowing the old one or requiring any downtime for your farm.
I was recently helping a user with their SharePoint site on their machine and I noticed some weirdness with the ribbon display. The Tab names were all truncated and too small and their User Name (Menu) was not showing in the upper right corner. Obviously, this concerned me.
Some quick searching didn’t turn up anything and I couldn’t reproduce it on my end. Then 2 days later I was helping someone else and they had the same display problems. Checked their version of IE and they were exactly the same (8.0.6001.18702CO)! But I believe the problem can happen with any version of IE 8.
With this new information did another quick search and found this quick article from Microsoft: http://support.microsoft.com/kb/2062185 where they indicate the Zoom feature is causing the problem.
Sure enough, adjusting the zoom back to 100% fixed the display issue. Strangely, IE 8 seemed to be handling zoom levels in increments of 10 just fine (110%, 120%, etc.) but custom zoom levels (like 128%) freaked it out.
This is problematic because it looks like a problem with the site and adjusting your zoom level is as easy as holding the CTRL key while using the middle mouse scroll. I found that I couldn’t reproduce the problem with IE 9. Until we can get everyone upgraded (a major process around here), it’s just a matter of education among our support staff and end users.
A common requirement/feature of sites is to have a Frequently Asked Questions (FAQ) section. This is a quick and easy way to provide help to end users. A FAQ is nothing more than a series of questions with their answers.
This can be implemented in a variety of ways but the standard way is to have the question above the answer all on a single page. This isn’t always the best way, but it’s certainly the most common and recognizable way.
Fortunately SharePoint makes this really easy using a custom list and only takes about 5 minutes to setup. This can be done in SharePoint 2007 or 2010 in both MOSS/Server and WSS/Foundation. Here’s the steps:
Create a custom list. Name it FAQ or something.
Edit the Title column and rename it Question.
Add a new Column of type Multi-Line Text and name it Answer
Modify the default view to only show those 2 columns and set the style to Newsletter.
That’s it! You end up with something like this:
FAQ in SharePoint 2007
FAQ in SharePoint 2010
You can then place this on a page using a ListView Web Part or just link directly to the main view. WOWEE!
Want to get fancy? Add another column called Order of type Number and use it to set custom ordering values and just sort by that column in your view.
We recently upgraded to SharePoint 2010. Things went relatively smoothly, but we began to experience problems with some of our Office users. I looked everywhere but I couldn’t find anything that described our problem perfectly or that provided a solution. So here is the guide I wish we’d had before we called Microsoft Support.
Symptoms:
Windows 7/Vista machines had missing/broken links to the sites within the SharePoint Sites library on their machine. These were all users with MySites most of whom had had no problem opening and saving documents directly within Office to SharePoint 2007. This was affecting both Office 2007 and Office 2010 users.
The Save/Open dialog showing a normal SharePoint Sites Library
Sometimes there was a MySite link, sometimes just a Member Sites folder, sometimes neither and sometimes various levels of Member Sites with the wrong type of Icon (Not like shown above). Some users could connect fine although it was very slow, others would have some very strange issues.
In addition to constantly asking for authentication or telling them access was denied to their own MySite, there were users who seemed to be saving their documents nowhere. Checking the Upload Center would show they did save them but not as expected.
For instance, one guy added his personal documents library to Office using the Connect To Office button on the SharePoint Ribbon. Trying to save a word document he double clicked on this link within the SharePoint Sites Library and everything saved. Further investigation with SharePoint Designer showed that their was a word document at his MySite root named PersonalDocuments.aspx.doc!
Obviously these links were broken. Sometimes they were gone from one day to the next and this was causing a lot of frustration. We tried messing with the registry entries, checking our version of Office, verifying access was setup correctly and finally gave up and called Microsoft Support.
Our Environment:
We had had a SharePoint 2007 farm using Windows Authentication. We built a new SharePoint 2010 farm and used the Database Attach upgrade approach. The new farm was built to use Kerberos authentication. When everything was good to go we switched the DNS entries to the new farm and voila, everything worked! (Obviously excluding the weird Office problems).
Our clients are mostly XP machines running Office 2007 – these had no issue. The Windows 7 clients running both Office 2007 and Office 2010 began experiencing the problems even though everything worked fine with SharePoint 2007.
Our DNS entry for SharePoint was set to the FQDN (ie sharepoint.something.something). Although alternate access mapping was setup for just the sharepoint portion, the FQDN is the only public url. This turned out to be the problem.
In summary, the Web Client service uses Windows HTTP Services (WinHTTP) to do network operations behind the scenes (including requesting the list of Member Sites and MySite urls to update your SharePoint Sites Library). WinHTTP only sends user credentials in response to requests that occur on a local intranet site.
So just add your site to the Trusted Sites list and you’re done! Just kidding, that’s far too easy! WinHTTP does NOT use the security zone settings in Internet Explorer to determine if it should send the credentials. Instead it uses some pretty basic logic:
Are there any periods in the server’s name? Nope: must be local – send them credentials! Yes: Eeeek! Evil Internet, no credentials for you!
So if you happen to be using a FQDN or anything else with periods in the address, unless you’ve setup a local (no perioded(?)) proxy, no authentication is gonna happen which is pretty problematic for nearly every use case in SharePoint.
A hotfix is available for Vista and was included in Windows 7. But the hotfix doesn’t fix the logic nor does it start using the security zone definitions from your internet options. It provides a registry configuration of trusted sites (see solution below).
Testing the Problem:
Office only requests this list of sites/libraries once every 24 hours or so based on a registry key. However, following the steps below you can get it to make the request(s) again. In order to watch them, download and install Fiddler. You should be able to see all the requests as it makes them.
Close all Office programs (including Outlook)
Using RegEdit, delete the LinkPublishingTimestamp registry key.
Vista and Above:
HKEY_CURRENT_USER\Software\AppDataLow\Microsoft\Office\14.0\Common\Portal\LinkPublishingTimestampWindows