I am new to SharePoint, sorry if answer to my question is obvious.
I want to forbid deleting some tasks for users.
I can use event receiver for my purpose:
public override void ItemDeleting(SPItemEventProperties properties)
{
if (...)
{
properties.ErrorMessage = "The task can not be deleted";
properties.Cancel = true;
}
}
But I can't pass data for checking if I can delete the task.
I've tryed to use
properties.ListItem.Properties["ForbidDeleting"].ToString().Equals("true")
in the receiver's condition but is there any posibility to pass such propterty in the CreateTask invoking method? I've tryed using ExtendedProperties for it, but this approach doesn't work.
....
task.ExtendedProperties["ForbidDeleting"] = "true"
I can create my class for keeping task Guids and it ForbidDeleting property, but I think it is not a solution but workaround.
Could you help me please? How can I set some task properties (in the CreateTask invoking method) and get it in the event receiver. Is there any built in way to do it?
Thank you in advance.
PS: Sorry for my writing. English is not my native language.
You can override another method in your event receiver: ItemAdding. You would set a field that you could use later in the deletion condition:
public override void ItemAdding(SPItemEventProperties properties)
{
// Decide if this task should be deletable.
properties.AfterProperties["ForbidDeleting"] = true;
}
You have to make sure that the boolean ForbidDeleting field exists in the task list; either by using your template to create it or by using a list event receiver to do the same or by doing it manually before you add the first task.
If you want to set the ForbidDeleting flag first after the task (list item) is really (successfully) created you could override ItemAdded but then update the list item explicitly after the change.
--- Ferda
I've found a solution. I have to use code like this in the Event Receiver to retreive extended properties:
Hashtable extendedProperties = SPWorkflowTask.GetExtendedPropertiesAsHashtable(taskItem);
var value = extendedProperties[key].ToString();
Thanks to Alexander: https://sharepoint.stackexchange.com/questions/32341/how-to-selectively-forbid-deleting-of-tasks-in-sharepoint-2010
Related
Is it possible to create a code refactoring for ReSharper like the one that checks a parameter for null.
This will generate the following guard check if we apply that to the method below
public void Method(string value)
{
if (value == null) throw new ArgumentNullException(nameof(value));
}
Is it possible to create a refactoring like "Check string parameter for not null or white space" that will be suggested on string parameters only?
public void Method(string value)
{
if (string.IsNullOrWhiteSpace(value)) throw new ArgumentNullException(nameof(value));
}
That is possible using context action. I don't know with what exact version this was introduced, but at least with 2016.1 it should be there.
Besides that, you can use live templates for some needs. They have some limitations though. If you reach them, you can create a custom plugin that implements a context action for instance.
I have generated ServiceContext for my CRM organization. I'm able to connect to CRM properly. Since I have all my context configuration in app.config file, I wonder is it possible to get IOrganizationService from already instantiated OrganizationServiceContext?
When I need to access the service reference from multiple places, I usually do it in two steps. First of all I try to see if it's possible to pass it down to the called methods (I'm assuming that you have something like the following).
using (IOrganizationService service
= (IOrganizationService) new OrganizationServiceProxy(...))
{
DoSomething();
DoSomething(service);
}
private void DoSomething(IOrganizationService service) { ... }
When it fails (due to technical setup or just plain dumbness), I set up a private property and in the constructor (or at least the first calling method) assign it a value for future access like this.
class MyClass
{
private IOrganization _service;
private IOrganization _Service
{
get
{
if(_service == null)
_service = (IOrganizationService) new OrganizationServiceProxy(...);
return _service;
}
}
...
}
And if you have a lot of code that operates on the server, you might want to move all that stuff to a separate class and have the calls made to it (with the property setup discussed above).
I'm not fully sure if I got your question correctly so be nice if I'm missing your point.
Disclaimer (fully editable/removable)
I've done my homework but to the best of my recognition, I can't see the very thing I'd like to know (which is a bit surprising, so I'm sure that a kind soul will flag me as a duplicate - please accept my apology in advance, haha).
Background and anticipated issue
When I start Outlook, I'm performing an update from CRM Dynamics, which takes a while. So, I decided to put the update in a thread. It works as supposed to but there's a button on the ribbon allowing a user to manually call for an update. Anticipating a frantic user, I realize that someone will click the button before the original update is finished and all kinds of excrement may hit the gas redistributive device.
Suggested solution
In order to avoid that, I've put a private property as follows.
private bool KeepYourPantsOn { get; set; }
As long as the said property is true (which it is set to right before I start the updating thread), all the frantic clicking will be either ignored or treated by a calm and informative
MessageBox.Show("Yes, yes... Updating still... Keep your pants on.");
but as soon as the thread is done, I'd like the property to flip over to false enabling the user to manually update Outlook.
Implementation problem
My hick-up is that I haven't found any OnFinished, WhenDone etc. method to call in order to switch the value of KeepYourPantsOn. Moreover, I haven't really seen any suggested solution on how to resolve that (or, rather - I haven't perceived any solution - I might have seen one without realizing that was it, due to ignorance within the area of threaded programming).
You should be able to just set the bool to false as the last line in your thread (or as the last line before looping back to wait on something, if your thread does that).
Note #Tudor comment regarding volatile - just to be sure, do it.
You can create a backing store for your property to hold the value and use a lock whenever you set or get the value to ensure that no concurrency issue arises.
After that, when you start processing on a separate thread, set the value to true and before exiting the method set the value to false.
On user click just check the value of KeepYourPantsOn property and display the message if it is still true.
class YourClass
{
private static readonly object _syncRoot = new object();
private bool _keepYourPantsOn;
public bool KeepYourPantsOn
{
get
{
lock(_syncRoot)
{
return _keepYourPantsOn;
}
}
set
{
lock(_syncRoot)
{
_keepYourPantsOn = value;
}
}
}
private ThreadMethod()
{
KeepYourPantsOn = true; //signal that the update process is starting...
// perform your logic
KeepYourPantsOn = false; //signal that the update process is finished
}
public ManualUpdate()
{
if(KeepYourPantsOn)
MessageBox.Show("Yes, yes... Updating still... Keep your pants on.");
else
Update();
}
}
I have an application that has a class named: UploadItem. The application creates uploading tasks based on information it has, for example, an upload needs to be created to upload a file to sitex.com with this the application creates a new UploadItem and adds that to an ObservableCollection, the collection is bound to a listview.
Now comes the part that I cannot solve.. I decided to change the structure so that people can create their own plugins that can upload a file, the problem lies with the fact that the UploadItem class has properties such as:
string _PercentagedDone;
public string PercentageDone
{
get { return _PercentagedDone; }
set { _PercentagedDone = value + "%"; NotifyPropertyChanged("PercentageDone"); }
}
But the plugin controls on how a file is uploaded, so how would the plugin edit the PercentageDone property that is located in the UploadItem class? If there is no way to do such a thing, then is there another way to achieve the same, i.e. showing the progress on the main GUI?
You'll want to define an interface for the plugins. Something like:
public interface IUploadPlugin
{
Task<bool> Upload(IEnumerable<Stream> files);
int Progress { get; }
}
The plugins then need to implement this interface and export themselves:
[Export(typeof(IUploadPlugin))]
public class MyUploader : IUploadPlugin, INotifyPropertyChanged
{
// ...
}
Notice that this plugin implements INotifyPropertyChanged. This is an easy way to handle updating the progress. Fire PropertyChanged on the Progress property and then databind your ProgressBar control in the main view to this property. Make sure that you fire PropertyChanged on the UI thread.
Another option would be to fire a custom event when the property changes. You could handle this event in the main view logic and update the progress.
Notice that I'm using Task for the return. This allows the caller to wait until the upload task finishes. You could use a callback instead, but with the CTP of the next version of .NET, using Task<> will allow you to use the await keyword for your async programming. Check it out here and here.
What im wondering how to do is when someone edits a list item and it goes through my event code that is fired when a change is made and save is hit, i dont want anyone to be able to edit that list item itself while its still processnig that request. So i was wondering if while in that event i can disable the individual item from being edited by someone else untill it is done doing what it is doing.
Not sure if I understand exactly what you are want.
Try adding a field, hidden if you like, to the list or content type to use as a flag. When you enter your event code, make sure you check the flag first and if not set, set it and do your stuff. After you have done your stuff, unset the flag.
Here is some code to illustrate. Note that I have used a column named "updating". You can use the properties of the SPListItem as well if you do not care to add a column.
Oh, and don't forget to call DisableEventFiring before you to SPListItem.Update and then EnableEventFiring() afterwards. For get this and you will have a very nasty infinite loop on your hands.
.b
public override void ItemAdding(SPItemEventProperties properties)
{
if (properties.ListItem["updating"].ToString() == "updating")
{
properties.Cancel = true;
properties.ErrorMessage = "Item is currently updating, please try again later";
}
else
{
properties.ListItem["updating"] = "updating";
this.DisableEventFiring();
properties.ListItem.Update();
this.EnableEventFiring();
// do your stuff
properties.ListItem["updating"] = "";
this.DisableEventFiring();
properties.ListItem.Update();
this.EnableEventFiring();
}
}
I have no doubt that Bjørns solution will work but you have to be very carefull when implementing it.
Pls. remember at your updating method should include a "finally" that resets the flag, no matter which exception gets thrown, other wise your list will be locked down for ever :-(