Automatically Refresh A SharePoint 2010 Calendar View

For some reason (at least to my knowledge) SharePoint 2010 does not provide a function to automatically refresh a SharePoint calendar view’s items at a given interval. The lack of this feature means a full page refresh is required any time a user wishes to check for any updates. While this might be suitable for infrequently updated calendars, for calendars that get frequently updated this is not desirable.

Fortunately, SharePoint does include a JavaScript library that provides methods for updating calendar views asynchronously. The particular library of interest is:

SP.UI.ApplicationPages.CalendarInstanceRepository

This repository contains a pointer to all of the calendar instances on the current page. If there is only one instance on the page, or you’re only interested in the first instance, there is a helper method firstInstance() to retrieve that calendar. Otherwise, you can find the collection of calendars as properties on the $o_0 property. You can turn this into a list using the following code:

Using The Calendar Repositories

Now that we have access to the calendar(s) we need to use them. One way of doing this is to create a hidden content editor web part that uses the following script to call refreshItems() every 10 seconds. First, create a new file RefreshCalendar.html and publish it somewhere on your SharePoint site.

Next, add a content editor web part to the same page as the calendar view you wish to update automatically; setting the content link to the location of the RefreshCalendar.html page, and setting the Chrome Type to none to remove any headers, borders, e.t.c. (i.e. make the content editor web part invisible to the user).

Automatically Refresh a Sharepoint Calendar View Content Editor

Now, when a user goes to the calendar view, the items are automatically updated every 10 seconds. Because the call is asynchronous the user will not be impacted when an update occurs, even if they are adding, or editing, a calendar item.

Impersonating Any User On SharePoint

When a SharePoint web part, or similar custom code, is running on SharePoint the active SPContext will either be impersonating the current user’s account or the guest account (if enabled). This means that all of SharePoint’s security is maintained when accessing lists, items, etc. However; there may be some instances when you want the custom code to be able to access items (or lists, etc.) which the current user does not have access to without actually giving the user direct access to these particular items. Fortunately, this is a pretty easy task to achieve and can be accomplished in a number of ways.

Method 1. Using elevated security

This method takes advantage of the Microsoft.SharePoint.SPSecurity static helper methods, in particular, the RunWithElevatedPrivileges method. The objective of this method is to execute code with full control regardless of the users delegated roles. Example:

SPSecurity.RunWithElevatedPrivileges(() => {
    // Code running with full control
});

The most important thing to note here is that any SharePoint context objects that have already been instantiated outside of the elevated security blocks do not have full control, even if referenced from within the elevated security blocks. This means that you can not simply call SPSecurity.RunWithElevatedPrivileges(() => SPContext.Current.ListItem.Delete()); and expect it to work if the current user does not have permission to the delete the current list item; instead, you must instantiate a new SPSite object within the elevated security blocks and then delete the list item. For example:

SPSecurity.RunWithElevatedPrivileges(() =>
{
    using (SPSite site = new SPSite(SPContext.Current.Site.ID))
    {
        using (SPWeb web = site.OpenWeb(SPContext.Current.Web.ID))
        {
            SPList list = web.Lists[SPContext.Current.List.ID];
            SPListItem item = list.Items[SPContext.Current.ListItem.UniqueId];
 
            item.Delete();
        }
    }
});

Now when the above code runs, it should not have any problems deleting the current list item, even if the current user does not have permission to delete the item.

Method 2. Impersonating another user

This is another simple method which involves instantiating a new SPSite object running under a different context to that of the invoking users’ context. To achieve this, when we are instantiating the new SPSite object, we simply pass in the SPUserToken of the user we wish to impersonate. For example, we could run under the system account:

using (SPSite site = new SPSite(SPContext.Current.Site.ID, SPContext.Current.Site.SystemAccount.UserToken))
{
    // code here
}

The thing to note with this method is that the user being impersonated needs to have permission to perform the actions specified.

The UserToken is available from SPUser objects. So before creating the new SPSite object, you would need to find the user object for the user you wish to impersonate, or otherwise, have some way of reference the user’s token.

InfoPath Roles And Views

One useful feature of InfoPath is its built in support for user Roles. While it is not an overly powerful (and it should not be used for security purposes as all data can be viewed and edited in XML format via notepad or a similar) it can be handy for automatically switching views based on AD users or groups.

To add a role simply go to Tools -> User Roles (alt + t + e) and click Add (alt + a). You can then specify which users, groups or user names from the form should belong to the new role.

One thing to note is that when you are designing an InfoPath form and click “Preview Form” it shows the form based on the default role. If you wish to preview the form under a different role you need to go to File -> Preview Form -> With User Role… (alt + f + r + r). The form will then be launched in preview mode under the select role.

There is also the option to set a role as either the default role or the initiator role (only one role can occupy either or both of these options). The default setting specifies that this role is the default role for all users, should they not meet the requirements of another role. The initiator setting is the role assigned to a user when they open the InfoPath form for the first time.

Another point of interest is that roles are assessed on a top-down approach, however, you can not change the ordering of roles from within the InfoPath IDE. In order to change the ordering of roles, should you be required to, you must open the manifest.xsf and manually reorder the <xsf:role /> elements.

Creating A Simple SharePoint Workflow In SharePoint Designer

This one is a quick and easy one but is the basis for creating some very useful workflows in for use in SharePoint lists. Firstly you will need a SharePoint website and a copy of SharePoint Designer (a 60-day trial version is available from Microsoft) and a list in SharePoint which you can apply the workflow to – for this example, I am using a fairly simple Travel Requisition list which is a document library which contains InfoPath documents.

To create the workflow open SharePoint Designer and connect to your SharePoint website. Once connected, go to File -> New and select the SharePoint Content tab and select Workflow (blank workflow). You should now be presented with a form similar to the following. Here you can specify a name for your workflow (each workflow in a site must have a unique name) which list the workflow is attached (associated) to and when the workflow should be triggered. In this case, we want to trigger the workflow whenever a list item is added or updated.

Continue reading “Creating A Simple SharePoint Workflow In SharePoint Designer”

FIX: Access is Denied 0×80070005

Recently I came across the problem where I was occasionally receiving an ‘Access is Denied 0×80070005′ error in the test environment for an ASP.NET application I was developing. After narrowing it down I discovered the error was only ever occurring when a call to the database was being made within the bounds of a TransactionScope(). After a quick search, I discovered a thread on the asp.net forums where someone else was having this issue as the MSDTC was not configured correctly.

Applying the same information from the aforementioned thread I soon discovered that the test vs development environments were showing similar results to that mentioned in the thread. In the end, the following solution resolved the problem.

Use sc sdshow msdtc on the server to display the current configuration, which should be similar to:

D:(A;;CCLCSWRPLOCRRC;;;S-1–2-0)(A;;CCLCSWRPWPDTLOCRRC;;;SY)(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;BA)(A;;CCLCSWLOCRRC;;;IU)(A;;CCLCSWLOCRRC;;;SU)(A;;CR;;;AU)(A;;CCLCSWRPWPDTLOCRRC;;;PU)(A;;CCLCSWRPLORC;;;NS)S:(AU;FA;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;WD)

Using sc sdset msdtc change the section in red to read as (A;;CCLCSWRPRC;;;WD) e.g:

D:(A;;CCLCSWRPLOCRRC;;;S-1–2-0)(A;;CCLCSWRPWPDTLOCRRC;;;SY)(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;BA)(A;;CCLCSWLOCRRC;;;AU)(A;;CCLCSWRPWPDTLOCRRC;;;PU)(A;;CCLCSWRPRC;;;WD)(A;;CCLCSWRPLORC;;;NS)S:(AU;FA;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;WD)