I am currently working on a SharePoint online project. I am facing a strange issue. My code generates 6 documents in 6 different document libraries along with other metadata. When I save data to a List, the event receiver fires and creates all the 6 documents. But sometimes it stops creating the 6 documents and left with 1 or 2 documents. Sometimes documents has been created but without any metadata. The same code is working fine in my on-premises environment, but it sometimes breaks in the Office 365 environment. I also created a log list to track the issue as we cannot debug in Office 365. In the log list I found a error message saying "Thread was being aborted." Below is my code. please help it is happening only in Office 365 environment.
using Microsoft.SharePoint;
/// <summary>
/// List Item Events
/// </summary>
public class ExcelGenReceiver : SPItemEventReceiver
{
/// <summary>
/// The template URL
/// </summary>
private const string TemplateUrl = "/Quotation Analysis Electrical/Forms/Quotation Analysis Sheet ELEC_Blank.xlsm";
/// <summary>
/// The template url1
/// </summary>
private const string TemplateUrl1 = "/Quotation Analysis Mechanical/Forms/Quotation Analysis Sheet MECH_Blank.xlsm";
/// <summary>
/// The template url2
/// </summary>
private const string TemplateUrl2 = "/TenderSummaryLib/Forms/TenderSummaryBlankMaster1.xlsm";
/// <summary>
/// The RFI template URL
/// </summary>
private const string RfiTemplateUrl = "/EstimatingRFI/Forms/RFI Schedule MASTER.docx";
/// <summary>
/// The drawing template URL
/// </summary>
private const string DrawingTemplateUrl = "/Tender and Drawing Schedule/Forms/Tender Document Drawing Schedule.docx";
/// <summary>
/// The tender return template URL
/// </summary>
private const string TenderReturnTemplateUrl = "/Est_Tender_Pricing_Document/Forms/Tender Pricing Document blank.xlsm";
/// <summary>
/// The project number
/// </summary>
private string projectNumber = string.Empty;
/// <summary>
/// The project name
/// </summary>
private string projectName = string.Empty;
/// <summary>
/// The no bid
/// </summary>
private string noBid;
/// <summary>
/// The team
/// </summary>
private string team;
/// <summary>
/// The description
/// </summary>
private string description;
/// <summary>
/// The status
/// </summary>
private string status;
/// <summary>
/// The electrical
/// </summary>
private SPUser electrical;
/// <summary>
/// The mechanical
/// </summary>
private SPUser mechanical;
/// <summary>
/// The document date
/// </summary>
private DateTime? docDate;
/// <summary>
/// The tender received
/// </summary>
private DateTime? tenderReceived;
/// <summary>
/// The tender return
/// </summary>
private DateTime? tenderReturn;
/// <summary>
/// The pre construction program start date
/// </summary>
private DateTime? preConstructionProgramStart;
/// <summary>
/// The pre construction program end date
/// </summary>
private DateTime? preConstructionProgramEnd;
/// <summary>
/// The sector
/// </summary>
private string sector;
/// <summary>
/// The design build
/// </summary>
private string designBuild;
/// <summary>
/// The build type
/// </summary>
private string buildType;
/// <summary>
/// The service program start date
/// </summary>
private DateTime? serviceProgramStart;
/// <summary>
/// The service program completion date
/// </summary>
private DateTime? serviceProgramCompletion;
/// <summary>
/// The client1
/// </summary>
private string client1;
/// <summary>
/// The client2
/// </summary>
private string client2;
/// <summary>
/// The client3
/// </summary>
private string client3;
/// <summary>
/// The client4
/// </summary>
private string client4;
/// <summary>
/// The consultant
/// </summary>
private string consultant;
/// <summary>
/// An item is being added.
/// </summary>
/// <param name="properties">The Item Event properties</param>
public override void ItemAdded(SPItemEventProperties properties)
{
//this.EventFiringEnabled = false;
var web = properties.Web;
var listItem = properties.ListItem;
try
{
LogIssue(web, null, "Item Added", "List Item Id {0}", listItem.ID);
if (!this.AttemptCopyProcess(listItem))
{
LogIssue(web, null, "List Id : " + listItem.ID, "AttemptCopyProcess failed.");
}
}
catch (Exception ex)
{
LogIssue(web, ex, "List Id : " + listItem.ID, "AttemptCopyProcess failed.");
}
finally
{
//this.EventFiringEnabled = true;
LogIssue(web, null, "List Id : " + listItem.ID, "Event Receiver completed sucessfully.");
}
}
/// <summary>
/// Logs any issues found
/// </summary>
/// <param name="webContext">The web context.</param>
/// <param name="exception">The exception, if null not exception details are written</param>
/// <param name="contextId">The context identifier, a unique identifier that allows us to know where the call originated, i.e. a List and ListItem Id, or a Page Url</param>
/// <param name="comment">The comment.</param>
/// <param name="args">The arguments.</param>
private static void LogIssue(SPWeb webContext, Exception exception, string contextId, string comment, params object[] args)
{
//// if (webContext.AllProperties.ContainsKey("EnableLogging"))
//// {
var list = webContext.Lists.TryGetList("ErrorIssues");
if (list != null)
{
var item = list.AddItem();
item["Title"] = contextId;
if (exception != null)
{
item["Message"] = exception.Message;
item["InnerException"] = exception.InnerException ?? (object)string.Empty;
item["StackTrace"] = exception.StackTrace;
}
if (!string.IsNullOrEmpty(comment))
{
item["Comment"] = string.Format(comment, args);
}
item.Update();
}
//// }
}
/// <summary>
/// Assigns the field.
/// </summary>
/// <param name="listItem">The list item.</param>
/// <param name="fieldName">Name of the field.</param>
/// <param name="contextId">The context identifier.</param>
/// <returns>The fields string value if present, otherwise string.empty.</returns>
private static string AssignField(SPListItem listItem, string fieldName, string contextId)
{
var fieldValue = string.Empty;
if (listItem.Fields.ContainsField(fieldName) && listItem[fieldName] != null)
{
fieldValue = listItem[fieldName].ToString();
}
else
{
LogIssue(listItem.Web, null, contextId, string.Format("Field not available : {0}", fieldName));
}
return fieldValue;
}
/// <summary>
/// Assigns the field as a DateTime
/// </summary>
/// <param name="listItem">The list item.</param>
/// <param name="fieldName">Name of the field.</param>
/// <param name="contextId">The context identifier.</param>
/// <returns>Returns the date if found, otherwise returns DateTime.MinValue</returns>
private static DateTime? AssignDateField(SPListItem listItem, string fieldName, string contextId)
{
DateTime? fieldValue = null;
if (listItem.Fields.ContainsField(fieldName) && listItem[fieldName] != null)
{
fieldValue = Convert.ToDateTime(listItem[fieldName].ToString());
}
else
{
LogIssue(listItem.Web, null, contextId, string.Format("Field not available : {0}", fieldName));
}
return fieldValue;
}
/// <summary>
/// Creates the folder.
/// </summary>
/// <param name="listdoc">The list.</param>
/// <param name="folderName">Name of the folder.</param>
private static void CreateFolder(SPList listdoc, string folderName)
{
LogIssue(listdoc.ParentWeb, null, "List Id : " + listdoc.ID, "Creating folder {0} in {1}", folderName, listdoc.RootFolder.ServerRelativeUrl);
// Updated by Indusnet
SPListItem folder1 = listdoc.Items.Add(listdoc.RootFolder.ServerRelativeUrl, SPFileSystemObjectType.Folder);
folder1["Name"] = folderName;
folder1.Update();
listdoc.Update();
// End Updated
}
/// <summary>
/// Assigns the user field.
/// </summary>
/// <param name="listItem">The list item.</param>
/// <param name="fieldName">Name of the field.</param>
/// <param name="contextId">The context identifier.</param>
/// <returns>Returns the user if found, otherwise null.</returns>
private static SPUser AssignUserField(SPListItem listItem, string fieldName, string contextId)
{
SPUser user = null;
if (listItem.Fields.ContainsField(fieldName) && listItem[fieldName] != null)
{
var userField = (SPFieldUser)listItem.Fields.GetField(fieldName);
var fieldValue = (SPFieldUserValue)userField.GetFieldValue(listItem["electrical_proj_manager"].ToString());
user = fieldValue.User;
}
else
{
LogIssue(listItem.Web, null, contextId, string.Format("Field not available : {0}", fieldName));
}
return user;
}
/// <summary>
/// Attempts the copy process.
/// </summary>
/// <param name="listItem">The list item.</param>
/// <returns>True if it successfully processed, false otherwise.</returns>
private bool AttemptCopyProcess(SPListItem listItem)
{
if (listItem.ParentList.Title != "Enquiry_Template")
{
LogIssue(listItem.Web, null, "List Id : " + listItem.ID, "ListItem titles is not Enquiry_Template, aborting.");
return false;
}
var finalNum = "15-" + new Random().Next(0, 9999).ToString("D4");
this.Initialize(listItem, finalNum);
if (this.noBid != "Yes")
{
LogIssue(listItem.Web, null, "List Id : " + listItem.ID, "The noBid field does not equal Yes, aborting.");
return false;
}
this.CopyFiles(listItem.Web, finalNum);
this.CreateFolders(listItem.Web);
return true;
}
/// <summary>
/// Copies the files.
/// </summary>
/// <param name="web">The web.</param>
/// <param name="finalNum">The final number.</param>
private void CopyFiles(SPWeb web, string finalNum)
{
LogIssue(web, null, "Web Id : " + web.ID, "Setting the copying of files ...");
var mechanicalQuoteList = web.Lists["Quotation Analysis Mechanical"];
var electricalQuoteList = web.Lists["Quotation Analysis Electrical"];
var tenderSummarList = web.Lists["TenderSummaryLib"];
var estimatingList = web.Lists["EstimatingRFI"];
var tenderSheduleList = web.Lists["Tender and Drawing Schedule"];
var tenderPricingList = web.Lists["Est_Tender_Pricing_Document"];
var url1 = mechanicalQuoteList.RootFolder.ServerRelativeUrl;
var url = electricalQuoteList.RootFolder.ServerRelativeUrl;
var url2 = tenderSummarList.RootFolder.ServerRelativeUrl;
var urlA = estimatingList.RootFolder.ServerRelativeUrl;
var urlB = tenderSheduleList.RootFolder.ServerRelativeUrl;
var urlC = tenderPricingList.RootFolder.ServerRelativeUrl;
var foldername1 = string.Empty;
var foldername = string.Empty;
var foldername2 = string.Empty;
var foldernameA = string.Empty;
var foldernameB = string.Empty;
var foldernameC = string.Empty;
var folder1 = web.Folders[url1 + "/" + foldername1];
var folder = web.Folders[url + "/" + foldername];
var folder2 = web.Folders[url2 + "/" + foldername2];
var folderA = web.Folders[urlA + "/" + foldernameA];
var folderB = web.Folders[urlB + "/" + foldernameB];
var folderC = web.Folders[urlC + "/" + foldernameC];
if (!folder1.Exists && !folder.Exists && !folder2.Exists && !folderA.Exists && !folderB.Exists && !folderC.Exists)
{
var folders1 = web.GetFolder(url1).SubFolders;
var folders = web.GetFolder(url).SubFolders;
var folders2 = web.GetFolder(url2).SubFolders;
var foldersA = web.GetFolder(urlA).SubFolders;
var foldersB = web.GetFolder(urlB).SubFolders;
var foldersC = web.GetFolder(urlC).SubFolders;
folders1.Add(foldername1);
folders.Add(foldername);
folders2.Add(foldername2);
foldersA.Add(foldernameA);
foldersB.Add(foldernameB);
foldersC.Add(foldernameC);
}
var file1 = web.GetFile(web.Site.Url + TemplateUrl1);
var file = web.GetFile(web.Site.Url + TemplateUrl);
var file2 = web.GetFile(web.Site.Url + TemplateUrl2);
var fileA = web.GetFile(web.Site.Url + RfiTemplateUrl);
var fileB = web.GetFile(web.Site.Url + DrawingTemplateUrl);
var fileC = web.GetFile(web.Site.Url + TenderReturnTemplateUrl);
if (file1 != null && file != null && file2 != null && fileA != null && fileB != null && fileC != null)
{
var fileName = string.Format("{0}/{1}{2}", folder1.ServerRelativeUrl, this.projectName, ".xlsm");
LogIssue(web, null, "Web Id : " + web.ID, "Copying file 1 {0} to {1}...", file1.Name, fileName);
var byteArray1 = file1.OpenBinary();
var uploadedFile1 = folder1.Files.Add(fileName, byteArray1, true);
LogIssue(web, null, "Web Id : " + web.ID, "File 1 Uploaded with new ID of {0}", uploadedFile1.Item.ID);
this.EventFiringEnabled = false;
var listitem1 = uploadedFile1.Item;
listitem1["Name"] = this.projectName;
listitem1["EnquiryNo"] = finalNum;
listitem1["Project_Name"] = this.projectName;
listitem1["Tender_Received"] = this.tenderReceived;
listitem1["Tender_Return"] = this.tenderReturn;
listitem1["Quotation_Analysis_Mech_Url"] = "https://groupportal.sharepoint.com/sites/EnginSouth/Quotation%20Analysis%20Mechanical/Forms/DispForm.aspx?ID=" + listitem1.ID;
listitem1.SystemUpdate(false);
this.EventFiringEnabled = true;
LogIssue(web, null, "Web Id : " + web.ID, "Copied file 1.");
fileName = string.Format("{0}/{1}{2}", folder.ServerRelativeUrl, this.projectName, ".xlsm");
LogIssue(web, null, "Web Id : " + web.ID, "Copying file 2 {0} to {1}...", file.Name, fileName);
var byteArray = file.OpenBinary();
var uploadedFile = folder.Files.Add(fileName, byteArray, true);
LogIssue(web, null, "Web Id : " + web.ID, "File 2 Uploaded with new ID of {0}", uploadedFile.Item.ID);
this.EventFiringEnabled = false;
var listitem = uploadedFile.Item;
listitem["Name"] = this.projectName;
listitem["EnquiryNo"] = finalNum;
listitem["Project_Name"] = this.projectName;
listitem["Tender_Received"] = this.tenderReceived;
listitem["Tender_Return"] = this.tenderReturn;
listitem["Quotation_Analysis_Elec_Url"] = "https://groupportal.sharepoint.com/sites/EnginSouth/Quotation%20Analysis%20Electrical/Forms/DispForm.aspx?ID=" + listitem.ID;
listitem.SystemUpdate(false);
this.EventFiringEnabled = true;
LogIssue(web, null, "Web Id : " + web.ID, "Copied file 2.");
fileName = string.Format("{0}/{1}{2}", folderA.ServerRelativeUrl, this.projectName, ".docx");
LogIssue(web, null, "Web Id : " + web.ID, "Copying file 3 {0} to {1}...", fileA.Name, fileName);
var byteArrayA = fileA.OpenBinary();
var uploadedFileA = folderA.Files.Add(fileName, byteArrayA, true);
LogIssue(web, null, "Web Id : " + web.ID, "File 3 Uploaded with new ID of {0}", uploadedFileA.Item.ID);
this.EventFiringEnabled = false;
var listitemA = uploadedFileA.Item;
listitemA["Name"] = this.projectName;
listitemA["EnquiryNo"] = finalNum;
listitemA["Project_Name"] = this.projectName;
listitemA["Date"] = this.docDate;
listitemA["Description"] = this.description;
listitemA["ProjectNo"] = this.projectNumber;
listitemA["RFIUrl"] = "https://groupportal.sharepoint.com/sites/EnginSouth/EstimatingRFI/Forms/DispForm.aspx?ID=" + listitemA.ID;
listitemA.SystemUpdate(false);
this.EventFiringEnabled = true;
LogIssue(web, null, "Web Id : " + web.ID, "Copied file 3.");
fileName = string.Format("{0}/{1}{2}", folderB.ServerRelativeUrl, this.projectName, ".docx");
LogIssue(web, null, "Web Id : " + web.ID, "Copying file 4 {0} to {1}...", fileB.Name, fileName);
var byteArrayB = fileB.OpenBinary();
var uploadedFileB = folderB.Files.Add(fileName, byteArrayB, true);
LogIssue(web, null, "Web Id : " + web.ID, "File 4 Uploaded with new ID of {0}", uploadedFileB.Item.ID);
this.EventFiringEnabled = false;
var listitemB = uploadedFileB.Item;
listitemB["Name"] = this.projectName;
listitemB["EnquiryNo"] = finalNum;
listitemB["Project_Name"] = this.projectName;
listitemB["Date"] = this.docDate;
listitemB["Description"] = this.description;
listitemB["ProjectNo"] = this.projectNumber;
listitemB["DrawingURL"] = "https://groupportal.sharepoint.com/sites/EnginSouth/Tender%20and%20Drawing%20Schedule/Forms/DispForm.aspx?ID=" + listitemB.ID;
listitemB.SystemUpdate(false);
this.EventFiringEnabled = true;
LogIssue(web, null, "Web Id : " + web.ID, "Copied file 4.");
fileName = string.Format("{0}/{1}{2}", folderC.ServerRelativeUrl, this.projectName, ".xlsm");
LogIssue(web, null, "Web Id : " + web.ID, "Copying file 5 {0} to {1}...", fileC.Name, fileName);
var byteArrayC = fileC.OpenBinary();
var uploadedFileC = folderC.Files.Add(fileName, byteArrayC, true);
LogIssue(web, null, "Web Id : " + web.ID, "File 5 Uploaded with new ID of {0}", uploadedFileC.Item.ID);
this.EventFiringEnabled = false;
var listitemC = uploadedFileC.Item;
listitemC["Name"] = this.projectName;
listitemC["EnquiryNo"] = finalNum;
listitemC["Project_Name"] = this.projectName;
listitemC["Date"] = this.docDate;
listitemC["Description"] = this.description;
listitemC["ProjectNo"] = this.projectNumber;
listitemC["PricingURL"] = "https://groupportal.sharepoint.com/sites/EnginSouth/Est_Tender_Pricing_Document/Forms/DispForm.aspx?ID=" + listitemC.ID;
listitemC.SystemUpdate(false);
this.EventFiringEnabled = true;
LogIssue(web, null, "Web Id : " + web.ID, "Copied file 5.");
fileName = string.Format("{0}/{1}{2}", folder2.ServerRelativeUrl, this.projectName, ".xlsm");
LogIssue(web, null, "Web Id : " + web.ID, "Copying file 5 {0} to {1}...", file2.Name, fileName);
var byteArray2 = file2.OpenBinary();
var uploadedFile2 = folder2.Files.Add(fileName, byteArray2, true);
LogIssue(web, null, "Web Id : " + web.ID, "File 6 Uploaded with new ID of {0}", uploadedFile2.Item.ID);
this.EventFiringEnabled = false;
var listitem2 = uploadedFile2.Item;
listitem2["Name"] = this.projectName;
listitem2["EnquiryNo"] = finalNum;
listitem2["Project_Name"] = this.projectName;
listitem2["Date"] = this.docDate;
listitem2["Team"] = this.team;
listitem2["Estimator_Electrical"] = this.electrical;
listitem2["Estimator_Mechanical"] = this.mechanical;
listitem2["Status"] = this.status;
listitem2["Tender_Received"] = this.tenderReceived;
listitem2["Tender_Return"] = this.tenderReturn;
listitem2["Sector"] = this.sector;
listitem2["Design_Build"] = this.designBuild;
listitem2["Build_Type"] = this.buildType;
listitem2["Service_Prog_Start"] = this.serviceProgramStart;
listitem2["Service_Prog_Completion"] = this.serviceProgramCompletion;
listitem2["Client_1"] = this.client1;
listitem2["Client_2"] = this.client2;
listitem2["Client_3"] = this.client3;
listitem2["Client_4"] = this.client4;
listitem2["Consultant"] = this.consultant;
listitem2["Pre-construction_Prog_Start"] = this.preConstructionProgramStart;
listitem2["Pre-construction_Prog_End"] = this.preConstructionProgramEnd;
listitem2["Tender_Summary_Url"] = "https://groupportal.sharepoint.com/sites/EnginSouth/TenderSummaryLib/Forms/DispForm.aspx?ID=" + listitem2.ID;
listitem2.SystemUpdate(false);
this.EventFiringEnabled = true;
LogIssue(web, null, "Web Id : " + web.ID, "Copied file 6.");
}
}
/// <summary>
/// Creates the folders.
/// </summary>
/// <param name="web">The web.</param>
private void CreateFolders(SPWeb web)
{
var projectListId = web.Lists.Add(this.projectName.Replace(' ', '_'), string.Empty, SPListTemplateType.DocumentLibrary);
var projectList = web.Lists[projectListId];
projectList.OnQuickLaunch = true; // The document library will appear in Quick Launch bar.
CreateFolder(projectList, "1.Tender Documents");
CreateFolder(projectList, "2. Electrical");
CreateFolder(projectList, "3. Mechanical");
CreateFolder(projectList, "4. Correspondance");
CreateFolder(projectList, "5. Settlement Meeting Docs");
CreateFolder(projectList, "6. Tender Return Docs");
CreateFolder(projectList, "7. Tender Handover");
projectList.Update();
}
/// <summary>
/// Initializes the specified list item.
/// </summary>
/// <param name="listItem">The list item.</param>
/// <param name="finalNum">The final number.</param>
private void Initialize(SPListItem listItem, string finalNum)
{
var contextId = string.Format("List:{0}, Id:{1}", listItem.ParentList.Title, listItem.ID);
this.noBid = AssignField(listItem, "Bid", contextId);
this.projectName = AssignField(listItem, "Project_Name", contextId);
var teamlookup = AssignField(listItem, "Team", contextId);
var lookupParts = teamlookup.Split(new[] { ";#" }, StringSplitOptions.None);
this.team = lookupParts[1];
this.description = AssignField(listItem, "Description", contextId);
this.status = AssignField(listItem, "enquiry_status", contextId);
this.electrical = AssignUserField(listItem, "electrical_proj_manager", contextId);
this.mechanical = AssignUserField(listItem, "mechanical_proj_manager", contextId);
this.docDate = AssignDateField(listItem, "Date", contextId);
this.tenderReceived = AssignDateField(listItem, "Tender_Received", contextId);
this.tenderReturn = AssignDateField(listItem, "Tender_Return", contextId);
this.preConstructionProgramStart = AssignDateField(listItem, "Pre-construction_Prog_Start", contextId);
this.preConstructionProgramEnd = AssignDateField(listItem, "Pre-construction_Prog_End", contextId);
this.sector = AssignField(listItem, "Sector", contextId);
this.designBuild = AssignField(listItem, "Design_Build", contextId);
this.buildType = AssignField(listItem, "Build_Type", contextId);
this.serviceProgramStart = AssignDateField(listItem, "Service_Prog_Start", contextId);
this.serviceProgramCompletion = AssignDateField(listItem, "Service_Prog_Completion", contextId);
this.client1 = AssignField(listItem, "Client_1", contextId);
this.client2 = AssignField(listItem, "Client_2", contextId);
this.client3 = AssignField(listItem, "Client_3", contextId);
this.client4 = AssignField(listItem, "Client_4", contextId);
this.consultant = AssignField(listItem, "Consultant", contextId);
if (this.status == "Won")
{
this.projectNumber = string.Format("15-{0}-{1}", this.team, new Random().Next(0, 9999).ToString("D4"));
}
if (this.status == "Active" || this.status == "Closed")
{
this.projectNumber = "No Project No";
}
listItem["ProjectNo"] = this.projectNumber;
listItem["EnquiryNo"] = finalNum;
listItem.Web.AllowUnsafeUpdates = true;
listItem.SystemUpdate(false);
}
}


