Search code examples
sharepointsharepoint-2010

How to synchronize two lists in two different SPSites using Event Receivers?


I have two sites with the same list name and same columns. Now I want to create item updated event receiver wherein when a user update any list item in list 1, it should get updated in list 2. User can create a new item in both the lists.

using (SPSite site = new SPSite("url"))
                using (SPWeb webWList = site.OpenWeb())
                {
                    SPList targetList = web.Lists["listTitle"];
                     string ID = properties.ListItem[""].ToString();
                    string internalColNAme = properties.ListItem.Fields["ColNAme"].InternalName.ToString();


                    SPQuery query = new SPQuery();
                    query.Query = "<Query><Where><Eq><FieldRef Name=''/><Value Type='Number'>" + properties.ListItemId + "</Value></Eq></Where></Query>";

                    SPListItemCollection items = targetList.GetItems(query);

                    SPListItem item = items[0];

                    item["ColName"] = properties.ListItem[""];
                    item.Update();           
                }
            });

The event receiver is working fine, but its updating the wrong item.


Solution

  • Maybe you want to have a look at this tutorial.

    In the ItemAdded Event get the list from the other SPSite and add the item there using the SPList.AddItem() method. To ensure enough access rights run it with elevated privileges.

    Some sample code for within the ItemAdded Method

    SPSecurity.RunWithElevatedPrivileges(delegate()
    {
        using(SPSite siteWhereNewItemWillBeAdded = new SPSite("url of web with list 2"))
        using(SPWeb webWithList = siteWhereNewItemWillBeAdded.OpenWeb())
        {
            SPList targetList = webWithList.Lists["listTitle"];
            SPListItem newItem = targetList.AddItem();
            //Set properties of item
            newItem["column of list 2"] = properties.ListItem["column of list 1"]
            newItem.Update();
        }
    });
    

    Replace the strings with the described content and add more of the set properties line if you have more columns/fields to copy into the item from list 2.

    The Update requirement is a different story you would need to save wich item in list 1 belongs to which item in list 2. Otherwise you wont be able to tell wich item to update unless you have some field that is unique and equal in both tables.

    To achive that you could add a custom column to list2. Lets say the custom column is named "list1Item".

    In the ItemUpdated Event you would have then:

    SPSecurity.RunWithElevatedPrivileges(delegate()
    {
        using(SPSite siteWhereNewItemWillBeAdded = new SPSite("url of web with list 2"))
        using(SPWeb webWithList = siteWhereNewItemWillBeAdded.OpenWeb())
        {
            SPList targetList = webWithList.Lists["listTitle"];
            var list2Items = targetList.Items;
            var syncedItem = from SPListItem item in list2Items 
                             where Convert.ToString(item["list1Item"]).Equals(properties.ListItem.ID.ToString()) 
                             select item;
            //Set properties of item
            syncedItem["column of list 2"] = properties.ListItem["column of list 1"]
            syncedItem.Update();
        }
    });
    

    To map the items add this line to the ItemAdded Event where you set the column values.

    newItem["list1Item"] = properties.ListItem.ID;
    

    UPDATE: To match question update

    Is this the complete code within the SPSecurity context of the Item Updated Event? What are you using these variables for?

    string ID = properties.ListItem["Zone"].ToString();
    string internalColNAme = properties.ListItem.Fields["ColNAme"].InternalName.ToString();
    

    From my current understanding you're trying to write the content of the item in list1 in the column "Zone" to the item in list2 column "ColName". The items are matched using the "Mapping" column in list2. Does your ItemAdded Method contain any version of the following line?

    newItem["Mapping"] = properties.ListItemId;
    

    You said that its updating the wrong item. Do you have more than 1 item with the same "Mapping" content in list2? Your code will only update the first one found by the query.