简体   繁体   English

在SharePoint文档库中生成唯一的随机字符串

[英]Generating unique random string in SharePoint document library

I'm working on customizing a SharePoint document library called "Quality Documents" so that when new docs are added to the library, a random and unique number is generated and applied to a field named "Document Number". 我正在自定义名为“质量文档”的SharePoint文档库,以便在将新文档添加到库中时,将生成一个随机且唯一的编号并将其应用于名为“文档编号”的字段。 I coded the feature below, but it's not working. 我对下面的功能进行了编码,但无法正常工作。 Can anyone see what might be the problem? 谁能看到问题所在? Nothing happens, no errors nothing, the page just works fine, but no Document Number gets generated. 没有任何反应,没有错误,页面工作正常,但是没有文档编号生成。 Any suggestions? 有什么建议么?

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

namespace QualityDocHandler
{
    class DocumentHandler : SPItemEventReceiver
    {
    /// <summary>
    /// Generates a random string with the given length
    /// </summary>
    /// <param name="size">Size of the string</param>
    /// <returns>Random string</returns>

    private string RandomString(int size)
    {
        StringBuilder builder = new StringBuilder();
        Random random = new Random();
        char ch;
        for (int i = 0; i < size; i++)
        {
            ch = Convert.ToChar(Convert.ToInt32(Math.Floor(26 * random.NextDouble() + 65)));
            builder.Append(ch);
        }
        return builder.ToString();
    }

    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 1st 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))
            {
                SPList oList = oWeb.Lists["Quality Documents"];

                //create query
                SPQuery oQuery = new SPQuery();

                //configure the query  //
                oQuery.Query = "<Where><Eq><FieldRef Name='Document_x0020_Number' /><Value Type='Text'>" + docNum + "</Value></Eq></Where>";

                //get the collection of items in the list
                SPListItemCollection oItems = oList.GetItems(oQuery);

                if (oItems.Count > 0)
                {
                    newRnd = 0;
                }
                else
                {
                    newRnd = 1;
                }
            }
            return docNum;
        }
        while (newRnd < 1);

    }

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

    public override void ItemAdding(SPItemEventProperties properties)
    {

        string documentNum = createDocNum(properties);
        using (SPWeb oWeb = new SPSite(properties.SiteId).OpenWeb(properties.RelativeWebUrl))
        {
            SPListItem listItem = properties.ListItem;
            properties.AfterProperties["Document_x0020_Number"] = documentNum;
            listItem.Update();
            oWeb.Update();
        }
        base.ItemAdding(properties);

    }

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

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

}

} }

A few things: 一些东西:

  • You don't need to get a reference to listItem and use listItem.Update(). 您不需要获取对listItem的引用并使用listItem.Update()。 Just setting the AfterProperties should be enough. 只需设置AfterProperties就足够了。

  • Prevent the same event from firing multiple times by wrapping your ItemAdding method code with: 通过使用以下代码包装您的ItemAdding方法代码,防止多次触发同一事件:

this.DisableEventFiring();
try
{
    // ...
}
finally
{
    this.EnableEventFiring();
}
  • Run SPDisposeCheck over your code. 对您的代码运行SPDisposeCheck You might have a memory leak on the SPSite object with new SPSite().OpenWeb() . 使用new SPSite().OpenWeb()可能会在SPSite对象上发生内存泄漏。

  • Have a read of Workarounds for ItemAdding/ItemAdded Event Handlers . 阅读ItemAdding / ItemAdded事件处理程序变通办法 I've never had to do this but using the display name instead of internal name may fix the problem. 我从来不需要这样做,但是使用显示名称而不是内部名称可以解决此问题。

  • In case of desperation, use ItemAdded() instead. 如果感到绝望,请改用ItemAdded()。 Get a full reference to the original item and update that. 获取原始项目的完整参考并进行更新。

listItem.Update(); listItem.Update(); probably throws a NullReferenceException, you can see the error message in the SharePoint log (or by attaching to w3wp), but errors from event receivers will not show up to the end user. 可能引发NullReferenceException,您可以在SharePoint日志中看到错误消息(或通过附加到w3wp),但是来自事件接收器的错误不会显示给最终用户。 They just cancel the event. 他们只是取消活动。

Besides, you don't have to call Update on the list item or the web in ItemAdding. 此外,您不必在ItemAdding的列表项或Web上调用Update。 And when you're creating a SPWeb for the current web in an event receiver you could use SPItemEventProperties.OpenWeb() instead. 而且,当您在事件接收器中为当前网站创建SPWeb时,可以改用SPItemEventProperties.OpenWeb()。 It saves you the "new SPSite()" call, which you actually forget to dispose in the above code. 它为您节省了“ new SPSite()”调用,您实际上忘记了将其放置在上述代码中。 This could lead to problems if you're having a medium to high load on your site. 如果您的站点负载中等到高,这可能会导致问题。 SPDisposeCheck is a good tool which could be used to find such issues. SPDisposeCheck是一个很好的工具,可以用来发现此类问题。

I was able to get this working. 我能够使它工作。 Here's the finished code: 这是完成的代码:

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

namespace QualityDocHandler
{
    class DocumentHandler : SPItemEventReceiver
    {
        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='Document_x0020_Number' /><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["Document Number"] = properties.AfterProperties["Document Number"];
            properties.ListItem.SystemUpdate();
            this.EnableEventFiring();
        }

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

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

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

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM