Reputation: 594
I am trying to programmatically create a Calendar List in SharePoint 2010 whenever a particular list is created using a Sandbox Solution. I have implemented a ListAdded ListEventReceiver in order to run the code to generate the calendar.
public class GenerateCalendar : SPListEventReceiver
{
public override void ListAdded(SPListEventProperties properties)
{
base.ListAdded(properties);
// Exit out if this is not a MyList type
if(!IsMyList(properties))
return;
string calendarTitle = properties.List.Title + " Calendar";
SPWeb spWeb = properties.Web;
SPListTemplateType type = new SPListTemplateType();
type = SPListTemplateType.Events;
// Execution breaks here:
Guid listGuid = spWeb.Lists.Add(calendarTitle, "Associated Calendar", type);
SPList newList = spWeb.Lists[listGuid];
newList.OnQuickLaunch = properties.List.OnQuickLaunch;
newList.Update();
}
}
When I call spWeb.Lists.Add(...), I get an SPException (The sandboxed code execution requested was refused because the Sandboxed Code Host Service was too busy to handle the request.)
From the MSDN documentation, I can see that that the SPListCollection.Add method is available in Sandboxed Solutions (https://msdn.microsoft.com/en-us/library/office/ms413986(v=office.14).aspx). Is there a restriction against creating a list in this event receiver like this? Does anyone know why this doesn't work?
Edited to add the generated Feature.xml and Elements.xml files
Feature.xml:
<?xml version="1.0" encoding="utf-8"?>
<Feature xmlns="http://schemas.microsoft.com/sharepoint/"
Title="Calendar Generator"
Description="Generates a calendar"
Id="dfe3388c-c063-4873-a41b-5c066907c510"
Scope="Web">
<ElementManifests>
<ElementManifest Location="GenerateCalendar\Elements.xml" />
</ElementManifests>
</Feature>
Elements.xml
<?xml version="1.0" encoding="utf-8"?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
<Receivers >
<Receiver>
<Name>GenerateCalendarListAdding</Name>
<Type>ListAdding</Type>
<Assembly>MyListGenerator, Version=1.0.0.0, Culture=neutral, PublicKeyToken=5cff2198a602ec41</Assembly>
<Class>MyListGenerator.Event_Receivers.GenerateCalendar.GenerateCalendar</Class>
<SequenceNumber>10000</SequenceNumber>
</Receiver>
<Receiver>
<Name>GenerateCalendarListDeleting</Name>
<Assembly>MyListGenerator, Version=1.0.0.0, Culture=neutral, PublicKeyToken=5cff2198a602ec41</Assembly>
<Class>MyListGenerator.Event_Receivers.GenerateCalendar.GenerateCalendar</Class>
<SequenceNumber>10000</SequenceNumber>
</Receiver>
<Receiver>
<Name>GenerateCalendarListAdded</Name>
<Type>ListAdded</Type>
<Assembly>MyListGenerator, Version=1.0.0.0, Culture=neutral, PublicKeyToken=5cff2198a602ec41</Assembly>
<Class>MyListGenerator.Event_Receivers.GenerateCalendar.GenerateCalendar</Class>
<SequenceNumber>10000</SequenceNumber>
</Receiver>
</Receivers>
</Elements>
Upvotes: 0
Views: 1950
Reputation: 594
I found the answer. Apparently creating a list within this event receiver was causing a recursive call to the event receiver, even though I had a check in place to exit out on non-MyList template-based lists. The solution was to simply add EventFiringEnabled = false
.
...
SPWeb spWeb = properties.Web;
SPListTemplateType type = new SPListTemplateType();
type = SPListTemplateType.Events;
EventFiringEnabled = false; // Disable event firing and create the list
Guid listGuid = spWeb.Lists.Add(calendarTitle, "Associated Calendar", type);
SPList newList = spWeb.Lists[listGuid];
newList.OnQuickLaunch = properties.List.OnQuickLaunch;
newList.Update();
EventFiringEnabled = true; // Re-enable event firing
...
Upvotes: 1
Reputation: 7049
You can create event receivers that derive from SPListEventReceiver
in a sandboxed solution. However, the event receiver must be registered declaratively in your feature elements file; it cannot be registered using the object model (such as via a feature receiver).
Most likely you are running into a restriction on the amount of resource points your sandboxed solution is permitted to consume, although you may also be running into the absolute limit of resources that can be consumed per request.
Additionally, if your environment runs particularly slowly, the user code service will recycle if its time limit (30 seconds by default) is exceeded during a single request.
For more information, refer to the "Understanding Solution Monitoring" section of this Sandboxed Solutions documentation from Microsoft: https://msdn.microsoft.com/en-us/library/ff798382.aspx
Relevant excerpts follow.
Resource Points:
If the solutions in a site collection exceed the daily resource point allocation for that site collection, SharePoint will take every sandboxed solution in the site collection offline for the rest of the day.
Resource points are calculated according to 14 different measurements known as resource measures, including CPU execution time, memory consumption, and unhandled exceptions.
...
SharePoint counts the most expensive resource measure toward the total for the solution, instead of the sum of all measures.
Absolute Limits:
To prevent rogue sandboxed solutions from causing instability SharePoint also monitors individual sandboxed solutions per request. Each of the 14 resource measures includes an AbsoluteLimit property that defines a hard limit of the resources that a sandboxed solution can consume in a single request. If an absolute limit is exceeded, SharePoint terminates the request by stopping and restarting the Sandbox worker process. For example, the CPU execution time resource measure has a default absolute limit of 60 seconds. If a single request takes more than 60 seconds to execute, the user code service will stop and restart the sandbox worker process that is executing the request.
WorkerProcessExecutionTimeout:
In addition, the user code service includes a property named WorkerProcessExecutionTimeout with a default value of 30 seconds. If this time limit is exceeded during a single request, the user code service will recycle the application domain in question and the request will return an error.
Upvotes: 0