1

I am trying to generate Random string and storing it to column when new document is inserted in document library.

I am using SPItemEventListener to handle this event. Here Is my code.

using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.SharePoint;
using Microsoft.Office.Server;
using Microsoft.Office.Server.UserProfiles;

namespace SharePointProject1.EventReceiver1
{
    /// <summary>
    /// List Item Events
    /// </summary>
    public class EventReceiver1 : SPItemEventReceiver
    {
        /// <summary>
        /// An item is being added.
        /// </summary>
        /// 
        private readonly Random _rng = new Random();
        private const string _chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
        private string RandomString(int size)
        {
            char[] buffer = new char[size];
            for (int i = 0; i < size; i++)
            {
                buffer[i] = _chars[_rng.Next(_chars.Length)];
            }
            return new string(buffer);
        }
        private string createDocNum(SPItemEventProperties properties)
        {
            int newRnd = 0;

            do
            {
                // set static department
                string dept = "QUA";

                // set date without separators
                string dateString = DateTime.Today.ToString("ddMMyyyy");

                // get 1st random string 
                string Rand1 = RandomString(4);

                // get 2nd random string 
                string Rand2 = RandomString(4);

                // creat full document number
                string docNum = dept + "-" + dateString + "-" + Rand1 + "-" + Rand2;

                using (SPWeb oWeb = new SPSite(properties.SiteId).OpenWeb(properties.RelativeWebUrl))
                {
                    SPSiteDataQuery q = new SPSiteDataQuery();
                    q.Lists = "<Lists BaseType='1'/>";
                    q.Query = "<Where><Eq><FieldRef Name='DocumentNumber' /><Value Type='Text'>" + docNum + "</Value></Eq></Where>";
                    q.Webs = "<Webs Scope='SiteCollection' />";
                    q.RowLimit = 1;

                    System.Data.DataTable spSiteDataQueryResults = oWeb.GetSiteData(q);

                    if (spSiteDataQueryResults.Rows.Count > 0)
                    {
                        newRnd = 0;
                    }
                    else
                    {
                        newRnd = 1;
                    }
                }

                return docNum;
            }
            while (newRnd < 1);
        }

        public override void ItemAdded(SPItemEventProperties properties)
        {
            this.DisableEventFiring();
            properties.ListItem["DocumentNumber"] = properties.AfterProperties["DocumentNumber"];
            properties.ListItem.SystemUpdate();
            this.EnableEventFiring();
        }

        private void EnableEventFiring()
        {

        }

        private void DisableEventFiring()
        {

        }

        public override void ItemAdding(SPItemEventProperties properties)
        {
            string documentNum = createDocNum(properties);

            this.DisableEventFiring();
            properties.AfterProperties["DocumentNumber"] = documentNum;
            this.EnableEventFiring();
        }

        public override void ItemUpdated(SPItemEventProperties properties)
        {
            base.ItemUpdated(properties);
        }

        public override void ItemUpdating(SPItemEventProperties properties)
        {
            base.ItemUpdating(properties);
        }
    }
}

When I am adding the document I am getting following error in logviewer

UserAgent not available, file operations may not be optimized
Sandboxed code solution has leaked these IDisposable objects

My Document Library look like this: enter image description here

Reference : https://stackoverflow.com/questions/1109703/generating-unique-random-string-in-sharepoint-document-library

  • can you debug the code and tell which line throws this error? – love thakker Mar 11 '16 at 7:03
  • Why don't you want to use the in-built Document ID functionality? – Paul Strupeikis Mar 11 '16 at 10:51
  • This is the requirement of the client. He has specific format for the document id. – Ubiquitous Developers Mar 11 '16 at 11:01
2

Unfortunately the sample you referenced has quite a few issues with it. First of all, this line needs to be changed

using (SPWeb oWeb = new SPSite(properties.SiteId).OpenWeb(properties.RelativeWebUrl))

because you also need to be wrapping your new SPSite in a using statement like so

using(SPSite oSite = new SPSite(properties.SiteId)){

    using(SPSweb oWeb = oSite.OpenWeb(properties.RelativeWebUrl)){

        //do stuff here
    }

}

This is outlined in the following reference on disposable SP objects

https://msdn.microsoft.com/en-us/library/aa973248(v=office.12).aspx

Secondly, you do not need to do both the ItemAdding and ItemAdded events. Just setting after properties in the item adding event will be enough.

Thirdly, the this.EnableEventFiring and this.DisableEventFiring methods are obsolete and under some circumstances you would use the newer alternative of

public override void ItemAdding(SPItemEventProperties properties)
    {
        string documentNum = createDocNum(properties);

        bool isEventFiringEnabled = this.EventFiringEnabled;
        this.EventFiringEnabled = false;
        properties.AfterProperties["DocumentNumber"] = documentNum;
        this.EventFiringEnabled = isEventFiringEnabled;
    }

However these aren't really needed here since you are only setting the after properties, which won't fire off another event.

Finally, and this I guess is more of a personal preference, but I would not do this in the item adding event, but rather the item added event. The reason being is that item adding is synchronous, and you are doing a site data query which in relative terms is an expensive operation. It would probably be better to generate the number in the item added event which runs asynchronously. For example

public override void ItemAdded(SPItemEventProperties properties)
    {

        string documentNum = createDocNum(properties);

        bool isEventFiringEnabled = this.EventFiringEnabled;
        this.EventFiringEnabled = false;

        properties.ListItem["DocumentNumber"] = documentNum;
        properties.ListItem.SystemUpdate();

        this.EventFiringEnabled = isEventFiringEnabled;

    }
  • I have removed my all the code. just keep ItemAdded function. Now no more error. but getting Document Number blank – Ubiquitous Developers Mar 11 '16 at 9:24
  • Can you confirm that your event is actually firing? What I mean is do you know for sure that your event receiver is hooked up to the document library correctly? – Paul Lucas Mar 11 '16 at 9:30
  • I should also point out that because the event handler is async, the number might take a second or so to show up. If you refresh your view and everything is working, the is the number still not there? – Paul Lucas Mar 11 '16 at 9:41
  • Ok let me try this – Ubiquitous Developers Mar 11 '16 at 9:49
1

For your requirement, you only need ItemAdded event. Here is code sample that can fulfill your Requirements:

public override void ItemAdded(SPItemEventProperties properties)
        {
            //base.ItemAdded(properties);

            try
             {
                base.EventFiringEnabled = false;
        string documentNum = createDocNum(properties);
                properties.ListItem["DocumentNumber"] = documentNum;
                properties.ListItem.SystemUpdate();
                base.EventFiringEnabled = true;
              }
             catch (Exception ex)
              {
                throw ex;
              }

        }

For your other problems related event receiver click Here for sample.

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.