3

I am working on SharePoint 2013 team site collection, and I have the following architecture -

  1. A team site collection which contain 15 sub sites. Each subsite represents one of our customers.
  2. On each subsite I have an issue tracking list.
  3. All the issue tracking lists inside the subsite share the same permission and the same content type.
  4. But on each subsite’s tracking list, the “assigned to” column (at the list level) is linked to a unique user group representing the customer’s client account managers. Group name is "Customer name client managers"

Now I have the following requirements:-

  1. If the user how adds an issue tracking list item is defined inside the related “Customer name client managers” group, then to set a column named “Important” to Yes.
  2. To test this I wrote an event receiver , and I set it as follow:-

    • I specify the site url to be equal to a subsite url.
    • Specific to have a farm solution
    • The event receiver type is “List item events”
    • Which will trigger when an item was created .
  3. Now the above worked well on the intended subsite. But i will be facing these limitations:-

I will have to apply 11++ different event receivers representing 11 different sub-sites, since I have deploy the event receiver to the related sub-site url.

Also inside the event receiver I have explicitly defined the related group name "CustomerA" in the below code. So my question is if there is a way to improve my approach to allow reusing the same event receiver among all the sub-sites. For example to apply the event receiver to the site content type instead to the subsite, and inside the event receiver to dynamically select the related group name based on the current subsite? Where I can name the group to be equal to the subsite name,, In this case I will have a single event receiver which should work on all the subsites ??

here is the code for the event receiver:-

 public override void ItemAdded(SPItemEventProperties properties)
            {
                base.ItemAdded(properties);
                bool findany = false;
                using (SPSite site = new SPSite(properties.SiteId))
                {
                    using (SPWeb web = properties.OpenWeb())
                    {
                        try
                    {

                        SPListItem currentItem = properties.ListItem;
                        SPUser user = properties.Web.CurrentUser; 

                        SPGroup group = web.SiteGroups["CustomerA"];
                        foreach (var user2 in group.Users)
                        {
                            if (user2.ToString() == user.ToString())
                            {
                                currentItem["Important"] = "Yes";
                                currentItem.SystemUpdate();
                                findany = true;
                                break;
                            }

                        }
                        if (!findany)
                        {
                            currentItem["Important"] = "No";                            
                            currentItem.SystemUpdate();
                        }

                    }
                    catch (Exception ex)
                    {
                        throw ex;
                    }
                }
            }  
        }

2 Answers 2

1

If I understood the need, I think you can do the following:

  • Associating the event receiver to the content type (below I'll show you how)
  • Get a reference to the subsite using SPWeb web = properties.OpenWeb();
  • Perhaps you create a list in the root site to store the relationship between the group name and the subsite

Example of how to associate the event to a content type

public static void addEventContentType(string clase, SPContentType tipoContenido, string ensamblado, SPEventReceiverType eventReceiverType, SPEventReceiverSynchronization sincro)
{
 SPEventReceiverDefinition eventReceiver = tipoContenido.EventReceivers.Add();
 eventReceiver.Synchronization = sincro;
 eventReceiver.Type = eventReceiverType;
 eventReceiver.Assembly = ensamblado;
 eventReceiver.Class = clase;
 eventReceiver.HostType = SPEventHostType.ContentType;
 eventReceiver.Update();
}

Sample use:

public static void asociarEventosGovernance(SPSite sitio)
{
 SPWeb mi_web = sitio.RootWeb;
 string ensambladoGovernance = typeof(EventReceiverGovernance).Assembly.FullName;
 string claseGovernance = typeof(EventReceiverGovernance).FullName;
 SPContentType tipoContenidoGovernance = mi_web.ContentTypes["Governance"];
 Internal.addEventContentType(claseGovernance, tipoContenidoGovernance, ensambladoGovernance, SPEventReceiverType.ItemAdded, SPEventReceiverSynchronization.Synchronous);
}

If you need more information, please let me know.

17
  • thanks for the reply. now when i create the event receiver using visual studio what will be the setting to associate it to the content type, baring in mind that i already have created the content type using the UI ? second point addign a list to store the relation is fine,, but why not to rely on the subsite name and the related group name to dynamically build the relation ?
    – John John
    Commented Oct 6, 2016 at 13:02
  • 1
    I seem to make the group name is similar to the name of the site is prone to errors, because anyone could change the site name. I'm not saying it's wrong, just has some risk. With regard to creating the type of content from the UI no problem. I added an example in response. Commented Oct 6, 2016 at 13:58
  • 1
    You have a class for the event reciever for instance "public class EventReceiverGovernance : SPItemEventReceiver" and you could put the code to make the association where you want. Commented Oct 6, 2016 at 14:25
  • 1
    Is not correct. You have to create a class for the event handler. Then in another class you use the code that I showed you to associate the event. The latter code is executed once in life to associate the event. It may be in a feature or elsewhere (an application page) Commented Oct 6, 2016 at 14:53
  • 1
    Can you explain briefly what should you do your event handler? Functionally speaking ... Commented Oct 6, 2016 at 16:58
1

You can create a List called "Parameters" in every site where you can set those particular options (it can be a SiteGroup Name, a Content Type Name, an URL, a ListName, etc.)
The structure can be something like:
Parameter List Structure

You can set every parameter you need to be different in each site/subsite Setting Parameters

Of course, you need to code your event receiver to read values from this list everytime you want, you can use the snippet below:

            SPQuery query = new SPQuery();
            query.RowLimit = 1;
            query.Query =
                    @"
                <Where>
                    <Eq>
                        <FieldRef Name='" + __column + "' /> " +
                            "<Value Type='" + list.Fields.GetFieldByInternalName(__column).Type + "'>" + __value + "</Value>" +
                        @"
                    </Eq>
                </Where>";             
            SPListItemCollection listItems = list.GetItems(query);

Where list is your "Parameters" collection, this may not be efficient but you can tune it a little by setting the RowLimit = 1 in the query.

Hope to help.

7
  • so this covers the event receiver cdoe,, but what about the setting should i assign the event receiver to the content type? or to the site collection ??
    – John John
    Commented Oct 6, 2016 at 13:34
  • can you please adivce which setting i need to use when i create the event receiver inside VS to associate it with the content type ?
    – John John
    Commented Oct 6, 2016 at 13:45
  • 1
    To be honest I really don't know, because some time ago I tried to associate event receivers to specific content types but I was unable to achieve it, so we swap the approach (time is always scarce). Instead, I use the parameters to check inside my code for the Content Type's Name or the ContentTypeId, and then "do something". Commented Oct 6, 2016 at 13:52
  • so when i define the site url for the event receiver i should specify the url of the site collection and not the url of the sub site as i am currently doing is this correct?so the event receiver will mainly fire when any item got created inside the site collection.. but i need to add a check that the actual modifications will not happen to the item unless is it under the related content type is this correct ?
    – John John
    Commented Oct 6, 2016 at 14:02
  • 1
    The event receiver must be deployed to a web app, so every site under that will trigger the event receiver. You can check for the content type in your itemadding event. Commented Oct 6, 2016 at 16:32

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.