1

I have an event receiver triggered on ItemUpdating that may take some time to run. The code is as follows:

using (SPLongOperation longOperation = new SPLongOperation())
{
    //Custom Messages on the Spinning Wheel Screen
    longOperation.LeadingHTML = "Enumerating ...";
    longOperation.TrailingHTML = "Please wait while the related items are checked.";

    //Start the long operation
    longOperation.Begin();

    foreach (SPListItem someItem in items)
    {

        strNCStatus = ncItem["Status"].ToString();

        if (strStatus != "Closed")
        {
            properties.ErrorMessage = "The Status Of The Item Cannot Be Changed To Closed Because There Are Open Related Items.";
            properties.Status = SPEventReceiverStatus.CancelWithError;
            properties.Cancel = true;
        }
    }

    //End the long operation
    string redirectURL = SPContext.Current.Web.Url;
    longOperation.End(redirectURL);
}

You will notice from the code that SPLongOperation(this.Page) is not calling the this.Page part.

I want the processing page to display while this operation takes place in the ItemUpdating.

I don't have a reference to this.Page because my code is running on ItemUpdating event receiver.

Is it valid to use SPLongOperation within ItemUpdating and if so how can I use SPLongOperation without using this.Page as the parameter?

2

Event Receivers are Asynchronous and they are getting executed in a separate thread.

To make your requirement work, the first thing you need to do it make the event Synchronous. For that you can use the Sysnchronization property of the Receiver Definition

 ReceiverDefinition.Synchronization=SPEventReceiverSynchronization.Synchronous;

Now the ItemUpdating will get executed by the same UI thread.

Next issue is how to get the HTTPContext object. Solution is to get if from the constructor

SPContext spContext;
HttpContext httpContext;

public ReceiverClass () {
    spContext = SPContext.Current;
    httpContext = HttpContext.Current;
}

public override void ItemUpdating(SPItemEventProperties properties) {
    base.ItemUpdating(properties);
    httpContext.Response.Redirect(spContext.Web.ServerRelativeUrl + "/_layouts/longoperationpage.aspx");
}

Now in longoperationpage.aspx you should do

using (var longRunning = new SPLongOperation(Page))
{
   longRunning.Begin();
   // do your long running operation here 
   longRunning.End(null, SPRedirectFlags.Default, Context, null, "window.frameElement.commonModalDialogClose(1, null);");
}
  • I don't have a longoperationpage.aspx or access to its code. – motionpotion Jan 23 '15 at 16:11
  • 1
    Just for the record Before events are synchronous by default so no need to modify ItemUpdating. Only after events are asynchronous by default. – Naim Murati Jan 23 '15 at 16:19
  • So does this mean that it is not possible to give feedback to the user in the situation I've described? – motionpotion Jan 23 '15 at 16:43
  • The layout aspx file you should create and then move your long operations to that. – Amal Hashim Jan 23 '15 at 16:56
  • Seems like a very awkward workaround for something that should be simple - i.e. displaying feedback to the user during an item update that may take a while. – motionpotion Jan 24 '15 at 17:40
0

Basically, you can't do that as SP Context is not available in Event Receivers and vice versa. The SPLongOperation wouldn't know when the event receiver has finished it's work.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.