3

I am working on an Event Receiver inside my sharepoint 2013. the event receiver will get fired when an item is Added and it is scoped at the Web level. but i am not sure if there are any differences between using :-

public override void ItemAdded(SPItemEventProperties properties)
 {
    base.ItemAdded(properties);
    SPSecurity.RunWithElevatedPrivileges(delegate()
    {
using (SPSite site = new SPSite(properties.Web.Site.ID))
        {

            using (SPWeb spCurrentSite = site.OpenWeb(properties.Web.ID))
            {

Or using

public override void ItemAdded(SPItemEventProperties properties)
  {
        base.ItemAdded(properties);
        SPSecurity.RunWithElevatedPrivileges(delegate()
        {
using (SPSite site = new SPSite(properties.siteID))
        {

            string currenweburl = properties.RelativeWebUrl;

            using (SPWeb spCurrentSite = site.OpenWeb(currentweburl))
            {

where on the first method i am using new SPSite(properties.Web.Site.ID) & site.OpenWeb(properties.Web.ID). while on the second i am using new SPSite(properties.siteID) & site.OpenWeb(currentweburl) ?? or they are the same ?

EDIT

here is my full event receiver code, which mainly will fire when an item is added to a list. where the event receiver will create a sub-site :-

using System;
using System.Security.Permissions;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Utilities;
using Microsoft.SharePoint.Workflow;

    namespace CreateSubSiteforProjects.EventReceiver1
    {
        /// <summary>
        /// List Item Events
        /// </summary>
        public class EventReceiver1 : SPItemEventReceiver
        {
            /// <summary>
            /// An item is being added.
            /// </summary>

            public override void ItemAdded(SPItemEventProperties properties)
            {
                   base.ItemAdded(properties);
        SPSecurity.RunWithElevatedPrivileges(delegate()
        {
            using (SPSite site = new SPSite(properties.SiteId))
            {
                string currentweburl = properties.WebUrl;

                using (SPWeb spCurrentSite = site.OpenWeb(currenweburl))
                {

                    // Get the web where the event was raised

                    //SPWeb  = new ;//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.ToLower() == "projects123")
                    {

                        //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;



                        // Get the rootweb where we will find the available templates

                        SPWeb rootWeb = spCurrentSite.Site.RootWeb;

                        //Get all the webtemplates available on this site collection

                        SPWebTemplateCollection webTemplates = rootWeb.GetAvailableWebTemplates(1033);

                        SPWebTemplate webTemplate = null;

                        String webTemplateName = "NewProject"; //this is the name of the template we will use

                        String webTemplateSearchName = "";


                        //Get the template based on name. In this example 'ProjectTemplate'

                        //Loop through the available templates
                        for (int i = 0; i < webTemplates.Count; i++)
                        {

                            webTemplateSearchName = webTemplates[i].Name.ToString();

                            //Compare to see if this is the 'ProjectTemplate' template
                            if (webTemplateSearchName.Contains(webTemplateName))
                            {
                                //when we have found the matching template,set webTemplate to the foundt template and exit the if loop
                                webTemplate = webTemplates[webTemplateSearchName];

                                break;

                            }

                        }

                        //Create the subsite based on the template from the Solution Gallery

                       SPWeb newSite = spCurrentSite.Webs.Add(curItemSiteName, curItemSiteName, "123", Convert.ToUInt16(1033), webTemplate, false, false);

                        //Set the new subsite to inherit it's top navigation from the parent site, Use false if you do not want this.

                        newSite.Navigation.UseShared = true;
                        string masterPage = "TDMCustom.master";
                        var masterUri = new Uri(rootWeb.Url + "/_catalogs/masterpage/" + masterPage);

                        newSite.MasterUrl = masterUri.AbsolutePath;

                        newSite.CustomMasterUrl = masterUri.AbsolutePath;
                        newSite.Update();
                        newSite.Close();





                    }
                }
            }
        });

            }


        }
    }

2 Answers 2

2

You can simply use SPItemEventProperties.Web in this context (remember do not dispose it).

SPWeb web = properties.Web;
9
  • can you explain what do you mean by "remember do not dispose it" ??? and what do you mean by i can simply use "_SPItemEventProperties.Web _"?? Sorry i did not get your reply correctly ?
    – John John
    Commented Dec 5, 2016 at 18:54
  • 1
    If You want to get SPWeb object of parent web of the list associated with the event, You can use SPWeb w = properties.Web. If You use this code, You should not call w.Dispose() or wrap it with using(..){}
    – Gennady G
    Commented Dec 6, 2016 at 10:02
  • 1
    Something like this. Google "sharepoint disposable objects" msdn.microsoft.com/ru-ru/library/…
    – Gennady G
    Commented Dec 6, 2016 at 12:54
  • 1
    >>So you mean if i use properties.Web, then i should not manually dispose it and i should not wrap it inside using statement ? - Yes, exactly :) You should only dispose objects that You created. In case of properties.Web You don't create it.
    – Gennady G
    Commented Dec 6, 2016 at 15:33
  • 1
    No. I meant do not wrap it like this: using( SPWeb web = properties.Web ){}
    – Gennady G
    Commented Dec 7, 2016 at 11:03
2

Conceptually, they are the same.

First, lets consider the SPSite initialization.

properties.siteID

and

properties.Web.Site.ID 

will just result in the same site collection ID, so either case new SPSite(siteCollectionID) will return an equivalent new instance (note: avoiding here any reference to SPRequest internal caching mechanisms for sake of simplicity).

The same could be said for

SPWeb spCurrentSite = site.OpenWeb(currentweburl)

and

SPWeb spCurrentSite = site.OpenWeb(properties.Web.ID)

Both will return a reference to an equivalent new SPWeb instance - both instance will represent the same web site. The only difference is that in one case you identify the web site by its relative url, in the other by its ID - since both can be used to unequivocally identify the site, it should be clear that the final result is the same. I suspect that the version using the ID may be a little more efficient while performing the lookup but that is just a supposition not backed up by any real test.

As a side notice, remember that in both cases you are creating new instances and because of that you are responsible of their disposal either by wrapping the instance creation in an using statement which will handle the cleanup for you or by disposing the object explicitly (most of the time you will use the "using" statement, the only time I had to go for a manual dispose was due to some specific and pretty odd requirement I had at the time involving code generation and anonymous methods...).

Since you are also using SPSecurity.RunWithElevatedPrivileges I would like to point out in order to avoid confusion that RunWithElevatedPrivileges does require that you recreate the SPSite and SPWeb instances in the elevate context (like you are already doing ). Only new instances gets the benefits of the elevated context so in your case using properties.Web as a replacement for SPWeb spCurrentSite = site.OpenWeb(currenweburl) isn't probably going to work since the properties.Webinstence has been created outside the elevation context and therefore won't run with elevated privileges. You probably already know that but I wanted to point it out since the original question was somehow unclear and other answers suggested to just use the other properties.Web instance instead.

Also worth to point out since you asked it in a comment is that while you are responsible to dispose every SPSite or SPWeb instance you created, you should normally never dispose any instance you got from the SharePoint execution context. This includes:

  • thing like SPContext.Current.Web

  • instances you can get from methods parameters - for example properties.Web inside event receiver handlers

In both cases the instance you will get is the same SharePoint will use to perform its other inner workings, so by disposing them you will put yourself on the line for bugs, performance problems and other unwanted results. As a reference, have a look at this question too : Dispose of SPItemEventProperties at the end of an event receiver?

9
  • thanks for your detailed reply. i have edited my original question and i provided the full event receiver code.but i have these questions. first question , you mentioned i am responsible to dispose the SPSite & SPWeb but i am defining them inside a using statements which will do the dispose for me is this correct? second question now i am using RunWithElevatedPrivileges because my event receiver will create a new subsite , and i want users with contribute permission who create an item and cause the event receiver to fire to be able to create a sub-site ..
    – John John
    Commented Dec 5, 2016 at 22:50
  • but i did not understand what do you exactly mean by "does require that you recreate the SPSite and SPWeb instances in the elevate context like you are doing"?? .third question . i did not understand your point on this "disposing it may even create some problems if you are unlucky" why disposing the properties.Web might create problems ?? can you please advice on these 3 questions??thnx
    – John John
    Commented Dec 5, 2016 at 22:51
  • 1
    let's see- I will also update the main post but here are your sub-answers. 1) yes, the "Using" statement will handle the dispose for you 2) I mean that only instances of SPSite and SPWeb created inside the RunWithElevatedPrivileges handler will run with elevated privileges. If you had used an external instance - for example the one from properties.Web that wouldn't be elevated. As for your third question 3) every time you use a SPWeb or SPSite instance you didn't create you shouldn't dispose it because some other functionality may still need it. Commented Dec 6, 2016 at 19:21
  • 1
    See the edits for further details. Commented Dec 6, 2016 at 19:21
  • your reply and edit is very beneficial thanks a lot. so can i summarize my current situation . now since i need to run my code with RunWithElevatedPrivileges then i need to create new instances of SPSite and SPWeb. and i am responsible of disposing them. now since i am wrapping them inside using blocks so this will make sure that those objects are disposed for me. second question, but for the new sub-site which i am creating inside the event receiver i should manually dispose it as i am doing now newSite.Update(); newSite.Close();??.
    – John John
    Commented Dec 7, 2016 at 0:48

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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