Item deleting event doesn't get fired when an item in a document library is deleted using retention policy - sharepoint-2010

I have designed a custom retention policy through which items of my document library gets hard deleted after a certain amount of days.
After these items are deleted from the document library, I have to update another list as these item status as archived.
But the item deleting event receiver doesn't get fired.
Event Reciever code
public override void ItemDeleting(SPItemEventProperties properties)
{
try
{
base.ItemDeleting(properties);
SPWeb oWeb = properties.Web;
SPListItem spLI = properties.ListItem;
SPList oList = oWeb.GetList("mylist");
string fileName = spLI.Name;
string userID = string.Empty;
if (oList != null)
{
SPQuery query = new SPQuery();
query.Query = "<Where><And><Eq><FieldRef Name=\"ReportName\" /><Value Type=\"Text\">" + fileName + "</Value></Eq><Eq><FieldRef Name=\"ReportStatus\" /><Value Type=\"Text\">COMPLETED</Value></Eq></And></Where>";
query.ViewFields = "<FieldRef Name=\"UserID\" /><FieldRef Name=\"ReportStatus\" /><FieldRef Name=\"ReportName\" />";
query.RowLimit = Constants.CAML_QUERY_ROW_LIMIT;
query.ViewAttributes = Constants.CAML_QUERY_VIEW_ATTRIBUTES_ALL;
SPListItemCollection allfiles = reportInfoList.GetItems(query);
if (allfiles != null)
{
if (allfiles.Count > 0)
{
foreach (SPListItem spReportInfoItem in allfiles)
{
userID = spReportInfoItem["UserID"].ToString();
spReportInfoItem["Status] = "Archived";
spReportInfoItem.SystemUpdate();
}
}
}
}
}
catch (Exception expException)
{
throw expException;
}
}

After a lot of google I figured out that a SystemUpdate() which does not fire events.
And the retention policy deletes from the list is a SystemUpdate() hence my event receiver doesn't get fired.
So I changed my code accordingly.

Related

Flag / Unflag email sending in CRM 2011

In CRM 2011, I want to attach Contacts to Quote, no problems for that.
When I save the quote, for each Contact I want to send a email for reminder purpose. (With a plugin)
How It's possible to flag this and give the ability to CRM user to unflag this from the quote form with a checkbox.
The final purpose, It's to give the ability to CRM user to send a new email reminder to one or multiple contacts attached in the quote.
Can you help me ?
You will need to have a ribbon button that will call a JavaScript method in one of the web-resources.
In the CommandDefinition of you RibbonDiff XML you will need to send a parameter to the JS method which will contain all the IDs of selected records in the subgrid.
<CommandDefinitions>
<CommandDefinition Id="xyz.Button.SendEmail.command">
<EnableRules>
</EnableRules>
<DisplayRules>
</DisplayRules>
<Actions>
<JavaScriptFunction Library="$webresource:Test.Js" FunctionName="SendEmail">
<CrmParameter Value="SelectedControlAllItemIds" />
</JavaScriptFunction>
</Actions>
</CommandDefinition>
and then the JS method would be something like below wherein you will need to parse all the IDs and then process your logic
function SendEmail(selectedIds) {
if (selectedIds != null && selectedIds != “”) {
var strIds = selectedIds.toString();
var arrIds = strIds.split(“, ”);
for (var indxIds = 0; indxIds < arrIds.length; indxIds++) {
//The logic that you want to process on each record will come here.
}
} else {
alert(“No records selected !! !”);
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Crm;
using Microsoft.Xrm.Sdk;
using System.ServiceModel;
using Microsoft.Xrm.Sdk.Query;
using Microsoft.Crm.Sdk.Messages;
using System.Text.RegularExpressions;
using System.Xml.Linq;
namespace SendEmail
{
public class Email : IPlugin
{
public void Execute(IServiceProvider serviceprovider)
{
IPluginExecutionContext context = (IPluginExecutionContext)serviceprovider.GetService(typeof(IPluginExecutionContext));
if (!(context.InputParameters.Contains("Target") && context.InputParameters["Target"] is Entity))
return;
//entity
Entity ent = (Entity)context.InputParameters["Target"];
if (ent.LogicalName != "entityName")//EntityName
throw new InvalidPluginExecutionException("Not a Service Request record! ");
//service
IOrganizationServiceFactory serviceFactory = (IOrganizationServiceFactory)serviceprovider.GetService(typeof(IOrganizationServiceFactory));
IOrganizationService _service = serviceFactory.CreateOrganizationService(context.UserId);
string Email="";
if (ent.Contains("emailidfiled"))
Email = (string)ent["emailidfiled"];
#region email template
QueryExpression query = new QueryExpression()
{
EntityName = "template",
Criteria = new FilterExpression(LogicalOperator.And),
ColumnSet = new ColumnSet(true)
};
query.Criteria.AddCondition("title", ConditionOperator.Equal, "templateName");
EntityCollection _coll = _service.RetrieveMultiple(query);
if (_coll.Entities.Count == 0)
throw new InvalidPluginExecutionException("Unable to find the template!");
if (_coll.Entities.Count > 1)
throw new InvalidPluginExecutionException("More than one template found!");
var subjectTemplate = "";
if (_coll[0].Contains("subject"))
{
subjectTemplate = GetDataFromXml(_coll[0]["subject"].ToString(), "match");
}
var bodyTemplate = "";
if (_coll[0].Contains("body"))
{
bodyTemplate = GetDataFromXml(_coll[0]["body"].ToString(), "match");
}
#endregion
#region email prep
Entity email = new Entity("email");
Entity entTo = new Entity("activityparty");
entTo["addressused"] =Email;
Entity entFrom = new Entity("activityparty");
entFrom["partyid"] = "admin#admin.com";
email["to"] = new Entity[] { entTo };
email["from"] = new Entity[] { entFrom };
email["regardingobjectid"] = new EntityReference(ent.LogicalName, ent.Id);
email["subject"] = subjectTemplate;
email["description"] = bodyTemplate;
#endregion
#region email creation & sending
try
{
var emailid = _service.Create(email);
SendEmailRequest req = new SendEmailRequest();
req.EmailId = emailid;
req.IssueSend = true;
GetTrackingTokenEmailRequest wod_GetTrackingTokenEmailRequest = new GetTrackingTokenEmailRequest();
GetTrackingTokenEmailResponse wod_GetTrackingTokenEmailResponse = (GetTrackingTokenEmailResponse)
_service.Execute(wod_GetTrackingTokenEmailRequest);
req.TrackingToken = wod_GetTrackingTokenEmailResponse.TrackingToken;
_service.Execute(req);
}
catch (Exception ex)
{
throw new InvalidPluginExecutionException("Email can't be saved / sent." + Environment.NewLine + "Details: " + ex.Message);
}
#endregion
}
private static string GetDataFromXml(string value, string attributeName)
{
if (string.IsNullOrEmpty(value))
{
return string.Empty;
}
XDocument document = XDocument.Parse(value);
// get the Element with the attribute name specified
XElement element = document.Descendants().Where(ele => ele.Attributes().Any(attr => attr.Name == attributeName)).FirstOrDefault();
return element == null ? string.Empty : element.Value;
}
}
}

SharePoint issue with Eventhandler

PROBLEM: I have a list and if I create a new Item I would like to do the following:
Create a new AutoIncrement Number in Column [AutoGeneratedID]
Use [Titel] and [AutoGeneratedID] to create a HyperLink in the List and a new subsite
The problem is i cant get the [AutogeneratedID] filled with a value because it is an itemadded event but if i try to put the code together in an ItemAdding event, i get a problem as described in the following link:
http://www.sharepoint-tips.com/2006/09/synchronous-add-list-event-itemadding.html
using System;
using System.Security.Permissions;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Security;
using Microsoft.SharePoint.Utilities;
using Microsoft.SharePoint.Workflow;
using System.Diagnostics;
namespace KuC_Solution.EventReceiver1
{
/// <summary>
/// List Item Events
/// </summary>
public class EventReceiver1 : SPItemEventReceiver
{
/// <summary>
/// An item was added.
/// </summary>
public override void ItemAdded(SPItemEventProperties properties)
{
base.ItemAdded(properties);
// -----------------------------------------------------------
try
{
this.EventFiringEnabled = false;
// Column name AutoGeneratedID
string columnName = "AutoGeneratedID";
SPSecurity.RunWithElevatedPrivileges(delegate()
{
using (SPWeb web = properties.OpenWeb())
{
web.AllowUnsafeUpdates = true;
//get the current list
SPList list = web.Lists[properties.ListId];
int highestValue = 0;
foreach (SPListItem item in list.Items)
{
if (item[columnName] != null && item[columnName].ToString().Trim() != "")
{
string value = item[columnName].ToString();
try
{
int currValue = int.Parse(value);
if (currValue > highestValue)
highestValue = currValue;
}
catch (Exception ex)
{
Trace.WriteLine(ex.Message);
}
}
}
SPListItem currItem = list.Items.GetItemById(properties.ListItem.ID);
currItem[columnName] = (highestValue + 1).ToString();
currItem.SystemUpdate(false);
web.AllowUnsafeUpdates = false;
}
});
this.EventFiringEnabled = true;
}
catch (Exception ex)
{
Trace.WriteLine(ex.Message);
}
// -----------------------------------------------------------
}
/// <summary>
/// An item is being added.
/// </summary>
public override void ItemAdding(SPItemEventProperties properties)
{
base.ItemAdding(properties);
//-------------------------------------------------------------
// Get the web where the event was raised
SPWeb spCurrentSite = properties.OpenWeb();
//Get the name of the list where the event was raised
String curListName = properties.ListTitle;
//If the list is our list named SubSites the create a new subsite directly below the current site
if (curListName == "TESTautoNumber")
{
//Get the SPListItem object that raised the event
SPListItem curItem = properties.ListItem;
//Get the Title field from this item. This will be the name of our new subsite
String curItemSiteName2 = properties.AfterProperties["Title"].ToString();
//String curItemSiteName3 = properties.AfterProperties["ID"].ToString();
String mia = properties.AfterProperties["AutoGeneratedID"].ToString();
String curItemSiteName = curItemSiteName2 + mia;
//Get the Description field from this item. This will be the description for our new subsite
//String curItemDescription = properties.AfterProperties["Projekt-ID"].ToString();
string curItemDescription = "CREWPOINT";
//String testme = "1";
//Update the SiteUrl field of the item, this is the URL of our new subsite
properties.AfterProperties["tLINK"] = spCurrentSite.Url + "/" + curItemSiteName;
//Create the subsite based on the template from the Solution Gallery
SPWeb newSite = spCurrentSite.Webs.Add(curItemSiteName, curItemSiteName, curItemDescription, Convert.ToUInt16(1033), "{4ADAD620-701D-401E-8DBA-B4772818E270}#myTemplate2012", false, false);
//Set the new subsite to inherit it's top navigation from the parent site, Usefalse if you do not want this.
newSite.Navigation.UseShared = true;
newSite.Close();
}
//---------------------------------------------------------------
}
}
}

Sharepoint 2010 EventReceiver for SPFolder adding

I have a document library in which we have added a custom folder content type in order to keep the Folder Owner in a custom field.
Now I am asked to set the default value of the "Add new" form to the Parent Folder Owner. I have tried this code below but the event fires after saving the new Folder. Could anyone pls help me? How can I set this default value before opening the form?
public override void ItemAdding(SPItemEventProperties properties)
{
SPSecurity.RunWithElevatedPrivileges(delegate()
{
try
{
this.EventFiringEnabled = false;
base.ItemAdding(properties);
if (properties.List.RootFolder.Name == "Documents")
{
SPWeb web = properties.List.ParentWeb;
SPList List = properties.List;
SPField fld = List.Fields["Folder Owner"];
SPUser usr = web.CurrentUser;
SPFieldUserValue curUser = new SPFieldUserValue();
curUser.LookupId = usr.ID;
SPFolder parentFolder = web.GetFolder(properties.AfterUrl.Substring(0,properties.AfterUrl.LastIndexOf("/")));
if (parentFolder.Item["Folder Owner"] == null)
{
fld.DefaultValue = curUser.ToString();
}
else
{
fld.DefaultValue = parentFolder.Item["Folder Owner"].ToString();
}
fld.Update();
List.Update();
}
}
catch (Exception)
{
}
finally
{
this.EventFiringEnabled = true;
}
});
}

Create multiple sharepoint list items based multiple uploaded files SP2010

I would like to create sharepoint list items based on selected multiple files from local drive. After uploading selected multiple files list should contains new list items (title is file name) with attachments (one attachment/uploaded file).
Ok I extended my custom webpart (with dynatree) on that list using http://www.plupload.com/ and creating page for saving attachments.
public partial class ImportMultipleFilesAsListItems : LayoutsPageBase
{
protected void Page_Load(object sender, EventArgs e)
{
//request form parameters comes from plupload
int parentFolderKey = int.Parse(Request.Form["key"]);
var file = Request.Files[0];
SPList list = SPContext.Current.Web.GetList(Request.Form["listUrl"]);
SPListItem folderItem = list.GetItemById(parentFolderKey);
if (folderItem != null)
{
string parentFolder = null;
if (folderItem.Folder != null)
{
parentFolder = folderItem.Folder.Url;
}
else
{
int slashIndx = folderItem.Url.LastIndexOf('/');
parentFolder = folderItem.Url.Substring(0, slashIndx);
}
SPListItem childFile = list.AddItem(parentFolder, SPFileSystemObjectType.File);
childFile["Title"] = file.FileName;
childFile["IsFolder"] = 0;
childFile["DocParentId"] = parentFolderKey;
childFile.UpdateOverwriteVersion();
byte[] data = new byte[file.ContentLength];
file.InputStream.Read(data, 0, file.ContentLength);
childFile.Attachments.AddNow(file.FileName, data);
}
}
}
$(function () {
var listInfo = new Object();
listInfo.key = null;
listInfo.listUrl = ctx.listUrlDir;
listInfo.__REQUESTDIGEST = $('#__REQUESTDIGEST').val();
$("#uploader").pluploadQueue({
// General settings
runtimes: 'browserplus,html5,html4',
url: $('#uploadMultipleFilesUrl').val(),
max_file_size: '50mb',
chunk_size: '1mb',
multipart_params: listInfo,
rename: true
});
// Client side form validation
$('form').submit(function (e) {
var uploader = $('#uploader').pluploadQueue();
// Files in queue upload them first
if (uploader.files.length > 0) {
// When all files are uploaded submit form
uploader.bind('StateChanged', function () {
if (uploader.files.length === (uploader.total.uploaded + uploader.total.failed)) {
$('form')[0].submit();
}
});
uploader.start();
} else {
alert('You must queue at least one file.');
}
return false;
});
$("#uploader").hide();
});

How to programmatically set the task outcome (task response) of a Nintex Flexi Task?

Is there any way of set a Nintex Flexi task completion through Sharepoint's web services? We have tried updating the "WorkflowOutcome", "ApproverComments" and "Status" fields without success (actually the comments and status are successfully updated, however I can find no way of updating the WorkflowOutcome system field).
I can't use the Nintex Web service (ProcessTaskResponse) because it needs the task's assigned user's credentials (login, password, domain).
The Asp.net page doesn't have that information, it has only the Sharepoint Administrator credentials.
One way is to delegate the task to the admin first, and then call ProcessTaskResponse, but it isn't efficient and is prone to errors.
In my tests so far, any update (UpdateListItems) to the WorkflowOutcome field automatically set the Status field to "Completed" and the PercentComplete field to "1" (100%), ending the task (and continuing the flow), but with the wrong answer: always "Reject", no matter what I try to set it to.
Did you try this code: (try-cacth block with redirection does the trick)
\\set to actual outcome id here, for ex. from OutComePanel control
taskItem[Nintex.Workflow.Common.NWSharePointObjects.FieldDecision] = 0;
taskItem[Nintex.Workflow.Common.NWSharePointObjects.FieldComments] = " Some Comments";
taskItem.Update();
try
{
Nintex.Workflow.Utility.RedirectOrCloseDialog(HttpContext.Current, Web.Url);
}
catch
{
}
?
Here are my code to change outcome of nintex flexi task. My problem is permission. I had passed admin token to site. It's solve the problem.
var siteUrl = "...";
using (var tempSite = new SPSite(siteUrl))
{
var sysToken = tempSite.SystemAccount.UserToken;
using (var site = new SPSite(siteUrl, sysToken))
{
var web = site.OpenWeb();
...
var cancelled = "Cancelled";
task.Web.AllowUnsafeUpdates = true;
Hashtable ht = new Hashtable();
ht[SPBuiltInFieldId.TaskStatus] = SPResource.GetString(new CultureInfo((int)task.Web.Language, false), Strings.WorkflowStatusCompleted, new object[0]);
ht["Completed"] = true;
ht["PercentComplete"] = 1;
ht["Status"] = "Completed";
ht["WorkflowOutcome"] = cancelled;
ht["Decision"] = CommonHelper.GetFlexiTaskOutcomeId(task, cancelled);
ht["ApproverComments"] = "cancelled";
CommonHelper.AlterTask((task as SPListItem), ht, true, 5, 100);
task.Web.AllowUnsafeUpdates = false;
}
}
}
}
}
}
public static string GetFlexiTaskOutcomeId(Microsoft.SharePoint.Workflow.SPWorkflowTask task, string outcome)
{
if (task["MultiOutcomeTaskInfo"] == null)
{
return string.Empty;
}
string xmlOutcome = HttpUtility.HtmlDecode(task["MultiOutcomeTaskInfo"].ToString());
if (string.IsNullOrEmpty(xmlOutcome))
{
return string.Empty;
}
XmlDocument doc = new XmlDocument();
doc.LoadXml(xmlOutcome);
var node = doc.SelectSingleNode(string.Format("/MultiOutcomeResponseInfo/AvailableOutcomes/ConfiguredOutcome[#Name='{0}']", outcome));
return node.Attributes["Id"].Value;
}
public static bool AlterTask(SPListItem task, Hashtable htData, bool fSynchronous, int attempts, int milisecondsTimeout)
{
if ((int)task[SPBuiltInFieldId.WorkflowVersion] != 1)
{
SPList parentList = task.ParentList.ParentWeb.Lists[new Guid(task[SPBuiltInFieldId.WorkflowListId].ToString())];
SPListItem parentItem = parentList.Items.GetItemById((int)task[SPBuiltInFieldId.WorkflowItemId]);
for (int i = 0; i < attempts; i++)
{
SPWorkflow workflow = parentItem.Workflows[new Guid(task[SPBuiltInFieldId.WorkflowInstanceID].ToString())];
if (!workflow.IsLocked)
{
task[SPBuiltInFieldId.WorkflowVersion] = 1;
task.SystemUpdate();
break;
}
if (i != attempts - 1)
{
Thread.Sleep(milisecondsTimeout);
}
}
}
var result = SPWorkflowTask.AlterTask(task, htData, fSynchronous);
return result;
}