The requirement
Recently a simple requirement came up: “Redirect the user to the view-form of an item after he creates a new item”. Sounds simple, right? …
The default behavior of SharePoint is to redirect the user to the url defined by the Source
-parameter. If this parameter is not given the default view (mostly AllItems.aspx
) will be used.
The result
The implementation of the requirement can be seen in this short screencast. After the user creates a new item he will be redirected to review the item-properties.
The way it should be
Not amazed by the pictures you just saw? One would think its easy to achieve this behavior. Simply add an EventReceiver to the desired list and listen to the ItemAdded
-event and redirect the user…
In theory this is should work. The problem is that there is no HttpContext.Current
available inside the ItemAdded
-method.
The HttpContext
The only way to get the current HttpContext
is within the constructor of your custom EventReceiver
during a asynchronous event synchronous event (ItemAdding, ItemUpdating
) as shown in the following pseudo code.
public class CustomEventReceiver : SPItemEventReceiver { private HttpContext _currentContext = null; public CustomEventReceiver () : base () { if (null != HttpContext.Current) { _currentContext = HttpContext.Current } } public override void ItemAdding (SPItemEventProperties properties) { // Here one can use _currentContext and redirect ... } } |
But now another problem arises. If you redirect the current thread is aborted and the item is never added to the list/library
// Will abort the thread _currentContext.Redirect("http://somewhere/to/go"); // Will NOT abort the thread but the redirection is ignored _currentContext.Redirect("http://somewhere/to/go", false); // What a mess! |
The magic
The only possible solution is to “manually” add the item so the redirection works as shown in the next code-block. The manual addition of the new item is necessary because the properties.ListItemId
within ItemAdding
is 0. But we need this ID to build the destination url in the form e.g. http://hostname/web/listname/DispForm.aspx?ID=22
public class CustomEventReceiver : SPItemEventReceiver { // Code omitted ... see above public override void ItemAdding (SPItemEventProperties properties) { // Get a "reference" to the list SPSite siteColl = new SPSite (properties.SiteId); SPWeb site = siteColl.OpenWeb (properties.RelativeWebUrl) SPList list = site.Lists[properties.ListId]; // Add the item and fill it with the values from properties DisableEventFiring (); SPListItem itemToAdd = list.Items.Add (); // ... EnableEventFiring (); // Cleanup site.Dispose (); siteColl.Dispose (); // Redirect SPUtility.Redirect (targetUrlOfNewItem, SPRedirectFlags.Default, _currentContext); } } |
Hint: Because the form used to display an item can change you should retrieve it via the SPList.Forms[PAGETYPE.PAGE_DISPLAYFORM]
-property.
Conclusion
The HttpContext.Current
is only available within the constructor of your event receiver when handling synchronous events like ItemAdding, ItemUpdating
.