0

This is the first time I add a listener (or eventReceiver) to a sharepoint list and I see some really strange behavior though I think the code is OK.

As you see in my code, I want to add a custom ID to each item: it consists of current date plus a unique auto increment number that starts from 1 in each day. I mean IDs in each day start from 'date'-1 and goes on one by one. strange behavior includes:

1-Sometimes the code that counts the number of list's items, returns 1 while there are hundreds of records in the list

2-Sometimes the code that should return the last record of the list(before currently adding item) , returns an older record (maybe 2 or 3 items before the last one)

After reply of 'BlueBird' I changed my code. I've commented out previous code. But both of those errors yet exist.

To track what happens in the code, I've added a log method. I've added the resulting log file too:

My code is

public override void ItemAdded(SPItemEventProperties properties)
    {
        GenerateID(properties);
    }


private void GenerateID(SPItemEventProperties properties)
    {
        SPListItem order = properties.ListItem;
        string dateColumnName = "order-date";
        string orderDate = Convert.ToDateTime(order[dateColumnName]).ToString("yyyy-MM-dd");

        int newID = 0;
        //SPListItemCollection allItems = properties.List.Items;//THIS WAS MY PREVIOUS CODE
        SPListItemCollection allItems = getListItems(properties);

        if (allItems.Count <= 1)//**THIS IS WHERE ERROR 1 OCCURS**
        {
            newID = 1;
            log("Item Count is:" + allItems.Count);
        }
        else
        {
            //**BELOW LINE IS WHERE ERROR 2 OCCURS**
            string lastDate = Convert.ToDateTime(allItems[1][dateColumnName]).ToShortDateString();
            string currentDate = Convert.ToDateTime(order[dateColumnName]).ToShortDateString();
            int lastID = 0;
            try
            {
                lastID = Convert.ToInt32(allItems[1]["reqNo"]);
                log("lastId is " + lastID);
            }
            catch (Exception ex) //There's no previous record
            { 
                log(ex.ToString()); 
            }

            if (lastDate.Equals(currentDate))
            {
                newID = lastID + 1;
                log("last date was equal to current date");
            }
            else
            {
                newID = 1;
                log("last date:" + lastDate + "\t ,current date:" + currentDate);
            }
        }
        order["request-ID"] = orderDate + "-" + newID;
        order["reqNo"] = newID;
        order.Update();
 }

private static SPListItemCollection getListItems(SPItemEventProperties properties)
    {
        SPQuery q = new SPQuery();
        q.Query = "<OrderBy><FieldRef Name='ID' Ascending='False'/></OrderBy>";
        q.RowLimit = 2;//the first item is the newly added one. so I need 2 items
        SPListItemCollection allItems = properties.List.GetItems(q);
        return allItems;
    }



 private void log(string str)
    {
        string log = Environment.NewLine + DateTime.Now + ":\t" + str;
        System.IO.File.AppendAllText(@"errorLog.txt", log);
    }

And my log file content is :

10/09/2013 10:51:42 A.M.:   lastId is 3
10/09/2013 02:49:35 P.M.:   lastId is 0
10/09/2013 03:04:47 P.M.:   lastId is 1
10/09/2013 03:04:47 P.M.:   last date was equal to current date
10/09/2013 04:06:59 P.M.:   lastId is 1
10/09/2013 04:06:59 P.M.:   last date:10/08/2013     ,current date:10/09/2013
10/10/2013 11:08:55 A.M.:   Item Count is:1
10/10/2013 11:23:17 A.M.:   lastId is 2
10/10/2013 11:23:17 A.M.:   last date:10/09/2013     ,current date:10/10/2013
10/10/2013 11:50:31 A.M.:   lastId is 1
10/10/2013 11:50:31 A.M.:   last date:10/09/2013     ,current date:10/10/2013
10/10/2013 12:01:57 P.M.:   Item Count is:1
10/10/2013 01:19:35 P.M.:   lastId is 1
10/10/2013 01:19:35 P.M.:   last date was equal to current date
10/10/2013 02:09:49 P.M.:   lastId is 0
10/10/2013 02:09:49 P.M.:   last date:10/06/2013     ,current date:10/10/2013
10/10/2013 02:12:15 P.M.:   lastId is 1
10/10/2013 02:12:15 P.M.:   last date was equal to current date
10/10/2013 02:21:47 P.M.:   lastId is 2
10/10/2013 02:21:47 P.M.:   last date was equal to current date
  • 3
    you might want to explain problem in your words as well, instead of making people read your code and figure it out themselves :) – Muhammad Raja Oct 10 '13 at 15:36
  • 1
    Seems like you need to work with your logic as you shouldn't count number of list items to get next ID as what if any item is deleted mean while... , check this link out for now sharepoint.stackexchange.com/questions/32448/… – Muhammad Raja Oct 10 '13 at 15:45
  • @MuhammadRaja: I should count items of the list, because when the list is empty, my customID should start from 1. thanks for the link. I edited the post. – mohsenov Oct 11 '13 at 8:02
0

Try this... Haven't tested it but it should get you on the right track...

    private void GenerateID(SPItemEventProperties properties)
    {
        SPListItem order = properties.ListItem;
        string dateColumnName = "order-date";
        string orderDate = Convert.ToDateTime(order[dateColumnName]).ToString("yyyy-MM-dd");

        int newID = 0;
        //Use CAML query to get most recent item...
        SPQuery q = new SPQuery();
        //q.Query = "<OrderBy><FieldRef Name='ID' Ascending='False' /></OrderBy>";
        q.Query = "<OrderBy><FieldRef Name='Created' Ascending='False' /></OrderBy>";

        q.ViewFields = string.Concat(
                               "<FieldRef Name='reqNo' />",
                               "<FieldRef Name='"+dateColumnName+"' />");

        q.ViewFieldsOnly = true;
        q.RowLimit = 1;
        SPListItemCollection col = properties.List.GetItems(q);

        if (col.Count > 0)
        {
            //Previous List Item Exists...
            string lastDate = Convert.ToDateTime(col[0][dateColumnName]).ToShortDateString();
            string currentDate = Convert.ToDateTime(order[dateColumnName]).ToShortDateString();
            if (lastDate.Equals(currentDate))
            {
                //Same Day...Increment ID
                int lastID = Convert.ToInt16(col[0]["reqNo"]);
                newID = lastID + 1;

            }
            else
            {
                //New Day... Start Fresh
                newID = 1;                    
            }               

        }
        else
        {
            //First List Item...
            newID = 1;
        }           

        order["request-ID"] = orderDate + "-" + newID;
        order["reqNo"] = newID;
        order.Update();
    }

Edit: I am not sure, but you may have to alter the query based on when the event reciever is being triggered. I think this would work on ItemAdding.

  • Thank you for your patience with my bad post. I added your suggestions to the code. It is working when I test it by my user. But I should wait to see how does it work under real circumstances. Because my previous code was working fine with my own tests but when exposed to users it started those hide-and-seek games. – mohsenov Oct 11 '13 at 7:57
  • By the way, what was the problem with my code? why those 2 errors occurred? – mohsenov Oct 11 '13 at 7:59
  • It seems to me that you wouldn't want to set newid=1 if it is <= 1 but just <1. If there is already an item, you don't want to set it to 1 I would think. Also, I dont think that allItems.Count - 2 is a reliable way of getting the most recent document. Which brings up another point that you may want to sort the query by the Created field and not the ID. I will update the code. – BlueBird Oct 11 '13 at 12:40
  • Nope! Unfortunately this code has the same problems either. I've edited my code and you can see that I didn't specified the fields to retrieve from list, because it didn't work for me. May you check what's the problem? – mohsenov Oct 13 '13 at 5:27
  • What are the errors you are getting? – BlueBird Oct 14 '13 at 14:28
0

I think I found the problem.

Each of my users, just see their own requests. So when they add a new item, my code just works with items created by that user, and not all users.

Most probably this was the reason of those strange behaviors.

This is the thread which led me to this answer:

http://social.msdn.microsoft.com/Forums/sharepoint/en-US/7e039ec7-b895-4e74-8d2e-44cff2234ec2/propertieslistitemscount-returns-wrong-number?forum=sharepointdevelopmentprevious

To make my code work with all items of the list (regardless of the user who added the item), I used SPSecurity.RunWithElevatedPrivileges:

SPSecurity.RunWithElevatedPrivileges(delegate()
{
     GenerateID(properties);
});

Again thanks to that thread and 'Christopher Clement' who helped me.

  • Please post your working code for others to reference. – BlueBird Oct 15 '13 at 19:47

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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