Sharepoint: Create a subweb from an item event handler - sharepoint

I have a "project list" (title, lead, members, site-URL) that is supposed to refer to team sites under the site that has the project list. So I added an SPItemEventReceiverto my feature in a sandbox solution to do that.
In ItemAdding(properties), I invoke the following:
string projectName = properties.AfterProperties["Title"].ToString();
SPWeb currentWeb = properties.Web;
SPWeb subweb = currentWeb.Webs.Add(projectName, projectName,
"Project site for " + projectName, (uint) currentWeb.Locale.LCID,
Microsoft.SharePoint.SPWebTemplate.WebTemplateSTS, true, false);
But when debugging, the call to Add throws an SPException wrapping a COMException for a HResult code of FAILED with the message The sandboxed code execution request was refused because the Sandboxed Code Host Service was too busy to handle the request.
Is there something wrong with the parameters, or should I delegate the actual creation to a workflow instead?

Following try with this:
public override void ItemAdding(SPItemEventProperties properties)
{
base.ItemAdding(properties);
// Get the web where the event was raised
SPWeb spCurrentSite = properties.OpenWeb();
//Get the name of the list where the event was raised
String curListName = properties.ListTitle;
//If the list is our list named SubSites the create a new subsite directly below the current site
if (curListName == "SubSites")
{
//Get the SPListItem object that raised the event
SPListItem curItem = properties.ListItem;
//Get the Title field from this item. This will be the name of our new subsite
String curItemSiteName = properties.AfterProperties["Title"].ToString();
//Get the Description field from this item. This will be the description for our new subsite
string curItemDescription = properties.AfterProperties["Description"].ToString();
//Update the SiteUrl field of the item, this is the URL of our new subsite
properties.AfterProperties["SiteUrl"] = spCurrentSite.Url + "/" + curItemSiteName;
//Create the subsite based on the template from the Solution Gallery
SPWeb newSite = spCurrentSite.Webs.Add(curItemSiteName, curItemSiteName, curItemDescription, Convert.ToUInt16(1033), "{8FCAD92C-EF01-4127-A0B6-23008C67BA26}#1TestProject", false, false);
//Set the new subsite to inherit it's top navigation from the parent site, Usefalse if you do not want this.
newSite.Navigation.UseShared = true;
newSite.Close();
}
}

Seems to be some deadlock situation; I solved my particular case by using the post-event ItemAdded instead (changing from setting values in AfterProperties to updating the ListItem instead). There, for some reason, the call to Webs.Add() completes normally...

Related

Document library field wont update field value

on ItemAdded on a field,
public override void ItemAdded(SPItemEventProperties properties)
{
this.EventFiringEnabled = false;
using (SPWeb web = new SPSite(properties.WebUrl).OpenWeb())
{
SPList list = web.Lists[properties.ListId];
SPListItem item = list.GetItemById(properties.ListItemId);
var test = item["MyField"] = "";
item.SystemUpdate(false);
}
this.EventFiringEnabled = true;
}
}
}
when adding a dokument directly to my library its clear the field, men when i publish the document and then try to unpublish and then i select Remove this document but create a draft of the document, on this event it wont clear my field, i get the value and everything but in the en it still has the old value?
I've not checked this for sure but I think I remember when dealing with event receivers in document libraries it's a little funny. I believe the itemAdded event fires when you upload the document, you then continue to fill out your metadata for that document and when you click save the itemupdating and itemupdated event is fired. If you debug you will see this I think.
I believe you want to change to ItemUpdated
Cheers
Truez

How to update field value in current item via event receiver?

EDIT: I've realized that my approach in the second code block was unnecessary. I could accomplish the same thing by doing the following in ItemUpdated:
SPListItem thisItem = properties.ListItem;
thisItem.File.CheckOut();
thisItem["Facility Number"] = "12345";
thisItem.Update();
thisItem.File.CheckIn("force check in");
Unfortunately, I'm still getting the same error message when "thisItem.Update();" is executed: he sandboxed code execution request was refused because the Sandboxed Code Host Service was too busy to handle the request
I actually was receiving the error above when deploying my sandbox solution originally and used this link (http://blogs.msdn.com/b/sharepointdev/archive/2011/02/08/error-the-sandboxed-code-execution-request-was-refused-because-the-sandboxed-code-host-service-was-too-busy-to-handle-the-request.aspx) to fix it.
I am trying to write a C# event receiver that changes the value of a field when a document is added/changed in a library. I have tried using the following code:
public override void ItemUpdating(SPItemEventProperties properties)
{
base.ItemUpdating(properties);
string fieldInternalName = properties.List.Fields["Facility Number"].InternalName;
properties.AfterProperties[fieldInternalName] = "12345";
}
Unfortunately, this is only working for certain fields. For example, if I replaced "Facility Number" with "Source", the code will execute properly. This may be the fact that we are using a third party software (called KnowledgeLake) that replaces the default edit form in SharePoint with a Silverlight form. Anyway, because I was having challenges with the code above (again, because I think the Silverlight form may be overriding the field after the ItemUpdating event fires), I have tried the following code:
public override void ItemUpdated(SPItemEventProperties properties)
{
base.ItemUpdated(properties);
//get the current item
SPListItem thisItem = properties.ListItem;
string fieldName = "Facility Number";
string fieldInternalName = properties.List.Fields[fieldName].InternalName;
string fieldValue = (string)thisItem["Facility Number"];
if (!String.IsNullOrEmpty(fieldValue))
{
//properties.AfterProperties[fieldInternalName] = "123456789";
SPWeb oWebsite = properties.Web as SPWeb;
SPListItemCollection oList = oWebsite.Lists[properties.ListTitle].Items;
SPListItem newItem = oList.GetItemById(thisItem.ID);
newItem.File.CheckOut();
thisItem[fieldInternalName] = "12345";
thisItem.Update();
newItem.File.CheckIn("force");
}
}
First off, the above seems a little klunky to me as I would love to just use the AfterProperties method. Additionally, I am getting the following error when "newItem.Update()" is executed: he sandboxed code execution request was refused because the Sandboxed Code Host Service was too busy to handle the request
Am I missing something here? I would love to utilize the first code block. Any help would be appreciated.
Josh was able to answer his own question, which helped me fix my problem as well. Here is a working code snippit.
public override void ItemUpdated(SPItemEventProperties properties)
{
string internalName = properties.ListItem.Fields[columnToUpdate].InternalName;
//Turn off event firing during item update
base.EventFiringEnabled = false;
SPListItem item = properties.ListItem;
item[internalName] = newVal;
item.Update();
//Turn back on event firing
base.EventFiringEnabled = true;
base.ItemUpdated(properties);
}

Additional code required when developing custom visual web part for anonymous access?

I have a simple custom web part with three drop downs that reads from three different list. When the user tries to access this page they get prompted for password, if they don't enter any credentials they get a 401 error.
I have enabled anonymous access both in central admin and on the site itself, users can browse to the site and view it without getting prompted for password. I have made sure that anonymous user have "view" access to the lists in questions but they still can't view any page with a custom web part.
So is it a SharePoint setting or do I have to add something in my web part projects?
Thanks in advance.
Edit:
I call this method in page load and still get the same error
private void LoadImageGallery()
{
SPSecurity.RunWithElevatedPrivileges(delegate()
{
SPSite oSiteCollection = SPContext.Current.Site;
SPWebCollection collWebsites = oSiteCollection.AllWebs;
DataTable dt = new DataTable();
for (int i = 0; i < collWebsites.Count; i++)
{
using (SPWeb oWebsite = collWebsites[i])
{
if (oWebsite.Title == "People")
{
SPList peopleList = oWebsite.Lists["Pages"];
if (peopleList != null)
{
SPListItemCollection collListItems = peopleList.Items;
dt = collListItems.GetDataTable();
// Include Surname to omit default/search page
dt = collListItems.GetDataTable();
rptImageGallery.DataSource = dt;
rptImageGallery.DataBind();
}
}
}
}
});
}
I also tried with
SPSite oSiteCollection = SPContext.Current.Site;
SPWebCollection collWebsites = oSiteCollection.AllWebs;
above runwithelevated..
I set system\sharepoint to have full control in the entire site
The custom page needs to meet two requirements so that the anonymous users can access it:
it needs to inherit from the class UnsecuredLayoutsPageBase,
the property AllowAnonymousAccess needs to be overridden to return true.
For anonymous access, you have to modified your code for access List to bind drop down list as below. Add you code in SPSecurity.RunWithElevatedPrivileges Delegate method.
SPSecurity.RunWithElevatedPrivileges(delegate() {
using (SPSite site = new SPSite(web.Site.ID))
{
//ADD YOUR WEB PART Code HERE
}
});
Important: You must create SharePoint Objects in this Delegate otherwise code will not run with Admin access.

Cannot add new item to list in ItemAdded Event Receiver

Can anybody tell me why this code doesn't work?
The "adding code" itself works, but unfortunately not in an ItemAdded Event.
I need this code in the ItemAdded Event and therefor i cannot use ItemAdding.
Thanks for any help.
public override void ItemAdded(SPItemEventProperties properties)
{
SPSite site = new SPSite("http://air_sim:39167/");
SPWeb web1 = site.RootWeb;
SPList List = web1.Lists["Announcements"];
SPListItem newitem = List.Items.Add();
newitem["Title"] = "Example";
newitem.Update();
}
Did you do any steps to attach event receiver to your list?
If no, you can install a feature to manage event receivers and
verify that the event receiver is added and if not, add it manually:
http://chrissyblanco.blogspot.com/2007/08/event-receiver-management.html
Maybe exception is thrown somwere? For example, if such site or list
with such name doesn't exist, exception will be thrown. Also if you
don't initialise required fields of your item, the Update() call
will throw exception.
By the way the properties variable contains many useful properties:
SPListItem newitem = properties.List.Items.Add();
newitem["Title"] = "Example";
newitem.Update();
Do you use Sharepoint 2010 or Sharepoint2007?
Do you use VS2008 or VS2010?
If you couldn’t use debugger, use EventLog:
public override void ItemAdded(SPItemEventProperties properties)
{
EventLog.WriteEntry("DebugSharepoint", "ItemAdded fired");
try
{
SPSite site = new SPSite("http://air_sim:39167/");
SPWeb web1 = site.RootWeb;
SPList List = web1.Lists["Announcements"];
SPListItem newitem = List.Items.Add();
newitem["Title"] = "Example";
newitem.Update();
}
catch(Exception e)
{
EventLog.WriteEntry("DebugSharepoint", e.Message, EventLogEntryType.Error);
}
}
Attach a debugger.
Go to cmd and type iisapp. You would get the worker process id.
Then open your event handler project and go to the tools and attach process and set the debug point on ItemAdded as well as ItemAddding event
Try the below solutions:
Check whether the Site exists with that name.
Check whether user has the permission to insert item.
Try using AllowUnsafeUpdates:
SPSite site = new SPSite("site address");
SPWeb web1 = site.RootWeb;
SPList List = web1.Lists["Announcements"];
web1.AllowUnsafeUpdates = true;
SPListItem newitem = List.Items.Add();
newitem["Title"] = "Example";
newitem.Update();
web1.AllowUnsafeUpdates = false;

How to access the Sharepoint SPNavigationNode.QuickLaunch Property?

I have a site as follows:
--SiteA
----Subsite1
----Subsite2
Now whenever i try to access the QuickLaunch Property its always empty e.g
SPNavigation nav = spWeb.Navigation;
if (nav.QuickLaunch.Count == 0)
{
// ALWAYS TRUE
}
However if i go into the Naviation Settings (Through the UI) of SiteA and reorder any site in the list, only then will the QuickLanuch become available. (Other settings are left as default)
Can anyone explain this behaviour? I really need access to the QuickLaunch items.
Thanks
This error occurs if you access quicklaunch while site is being created.Below code causes the feature activated code to wait until the site collection has been created before executing.
using System.Threading;
public override void FeatureActivated(SPFeatureReceiverProperties properties)
{
//Queues changes until after site exists. For use in provisioning.
SPWeb web = properties.Feature.Parent as SPWeb;
ThreadPool.QueueUserWorkItem(ApplyYourChanges, web.Url);
}
private void ApplyYourChanges(object state)
{
string webUrl = state as string;
Uri uri = new Uri(webUrl);
// additional conditions here -- perhaps check if a feature was activated
while (!SPSite.Exists(uri))
{
Thread.Sleep(5000);
}
using (SPSite site = new SPSite(webUrl))
{
using (SPWeb web = site.OpenWeb())
{
//configure the quicklaunch menu
configureQuickLaunch(web);
}
}
}
public static void configureQuickLaunch(SPWeb spWeb)
{
SPNavigationNodeCollection nodeCollection = spWeb.Navigation.QuickLaunch;
SPNavigationNode heading = nodeCollection.Cast<SPNavigationNode>().FirstOrDefault(n => n.Title == headingNode);
SPNavigationNode item = heading.Children.Cast<SPNavigationNode>().FirstOrDefault(n => n.Url == url);
if(item == null)
{
item = new SPNavigationNode(nodeName, url);
item = heading.Children.AddAsLast(item);
}
}
I think, by default, the QuickLaunch uses shared navigation. In other words, the QuickLaunch for a subsite doesn't have its own collection of nodes until you do something with it. If you reorder a site, that gives it its own unique set of nodes.
If you wanted to programmatically set your QuickLaunch to have its own set of nodes programmatically, you should be able to do so this way:
SPNavigation nav = spWeb.Navigation;
nav.UseShared = false;
spWeb.Update();
I think your count should be something other than zero at that point.
I seem to remember reading somewhere that the QuickLaunch collection only stored customisations to the default ordering. Looking around, I can't find that documentation to show you, but it would explain the behavior you see if true.
So your QuickLaunch.Count == 0 is just confirming that default ordering of items is in place.
You can still add nodes, if that's at all helpful;
SPNavigationNodeCollection nodes = web.Navigation.QuickLaunch;
SPNavigationNode node = new SPNavigationNode("Node Name", "Node URL", true);
nodes.AddAsFirst(node);

Resources