Take the 2-minute tour ×
SharePoint Stack Exchange is a question and answer site for SharePoint enthusiasts. It's 100% free, no registration required.

I'm trying to add a webpart to a publishing page after the page is created, so I've created an Event Receiver, the problem is, if I make the Event Receiver Synchronous (As it should be) the code executes successfully but the webparts are not added to the page, the only way I have found that works is making the event receiver async and do a Thread.Sleep before making the changes.

This is the code:

public override void ItemAdded(SPItemEventProperties properties){
base.ItemAdded(properties);

try
{
    this.EventFiringEnabled = false;//Disable any other events while our event is beeing executed

    //Thread.Sleep(2000);

    var fileUrl = properties.ListItem.File.Url;
    var webUrl = properties.Web.Url;

    SPSecurity.RunWithElevatedPrivileges(delegate()
    {
        using (var site = new SPSite(webUrl))
        {
            using (var web = site.OpenWeb())
            {
                bool unsafeUpdates = web.AllowUnsafeUpdates;
                web.AllowUnsafeUpdates = true;

                var file = web.GetFile(fileUrl);
                var wpManager = file.GetLimitedWebPartManager(PersonalizationScope.Shared);

                if (wpManager.WebParts.Count == 0)
                {
                    var idx = 0;

                    ...add webparts

                    file.Update(); //I've also tried with web.Update()
                }

                web.AllowUnsafeUpdates = unsafeUpdates;
            }
        }
    });
}
catch (Exception ex)
{
    //Exception occurred
    properties.Cancel = true;//We cancel the event
    properties.Status = SPEventReceiverStatus.CancelWithError;//Set appropriate status
    properties.ErrorMessage = ex.Message;//Set the error message
}
finally
{
    this.EventFiringEnabled = true;//Regardless if the exception occurred or not, we have to enable earlier disabled events
}

}

Is there something wrong? how can I make the event receiver to work synchronously?

share|improve this question
    
Are the fileUrl and webUrl variables populating correctly? Does it get to the .Update() at all? A bit of debugging would help a lot here. Maybe SP Diagnostics and write out custom ULS lines. SPDiagnosticsService.WriteTrace(0, Category, TraceSeverity.Unexpected, Message); –  Hugh Wood Nov 22 '12 at 17:30
    
Yes, fileUrl and webUrl are correctly, as I said, the code is executing as expected, no exception, the Update() is working, but when I open the page in sharepoint, it's empty. –  Escobar5 Nov 22 '12 at 20:13
    
I ended up doing it in the ItemUpdated handler, it fires after ItemAdded and there it works, I just need to do some checks to see if its being fired the first time. –  Escobar5 Nov 22 '12 at 20:14
add comment

1 Answer 1

up vote 0 down vote accepted

OP: "how can I make the event receiver to work synchronously?"

All of the "...-ed" event receivers are defined asynchronously, and all of the "...-ing" event receivers are defined synchronously. This is by design.

See Event Handlers - Part 1: Everything you need to know about Microsoft Office SharePoint Server (MOSS) Event Handlers by Brian Wilson

The before events are synchronous to allow you to pause the flow of code execution. This is so you can grab a hold of the object and make changes before the code continues on to the original command (add the item, update the item, add the web, etc.).

Once the object exists, the after events allow you to change the data that is present asynchronously. These events are defined asynchronously so that the normal execution of code within SharePoint can continue while the work in your event receiver occurs on a different thread. These events can be asynchronous without a problem since the "action" working on the object has already completed and we aren't trying to affect the properties of the object while the new or edited data is en route to SharePoint.

Edit:

You may be able to define an asynchronous event synchronously by defining the receiver's Synchronization property in your elements.xml:

<Receivers>
    <Receiver>
         ...
         <Synchronization>Synchronous</Synchronization>
    </Receiver>
</Receivers>

I haven't tried to override the default receiver behavior in this manner, but found this as a proposed solution on Getting BeforeProperties and AfterProperties in Event Receivers

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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