I am listening on a particular SPWeb using an SPWebEventReceiver that is successfully firing on the WebMoved event. When the web is moved I update a list with the new location/title.
What I would like to be able to do is listen for when the Web is renamed . Do I do this by attaching an item listener and waiting for an ItemUpdated event? If so I would appreciate a little snippet of code! Thanks!
It looks like this is a bug with the SharePoint OM. The event receiver is clearly supposed to fire when the name of a web is changed, but it does not. It only fires when the Web's URL is changed.
Steve,
As far as I can see, SPWebEventReceiver only exposes the following events on an SPWeb (http://msdn.microsoft.com/en-us/library/microsoft.sharepoint.spwebeventreceiver_members.aspx)
SiteDeleted
SiteDeleting
WebDeleted
WedDeleting
WebMoved
WebMoving
ItemAdded is defined in SPItemEventReceiver which is applicable to SPListItem objects.
The Title property of an SPWeb is stored in a property bag (http://msdn.microsoft.com/en-us/library/microsoft.sharepoint.spweb.properties.aspx).
It doesn't appear like you can tap into any events when .Update() is called on the property bag, e.g. when Title is updated.
I would say that a rename of the Web name should trigger WebMoved.
Site title rename triggers no action.
Question: What changes do you want tot tap in? Because any metadata for instance could be stored in lists inside, which supports lots of events.
I don't believe it is a bug, I believe it is simply a misinterpretation of the documentation. As you have stated, the documentation indicates that the WebMoving and WebMoved events are triggered by the site's url being modified or being renamed:
from MSDN Doc: "Synchronous Before event that occurs before an existing Web site has been renamed or moved to a different parent object."
However, what gets changed in the UI is NOT the "name" of the site, but the site's title. The SPWeb object does have a "Name" property that is accessible through the Object Model, and updating that Name property and calling SPWeb.Update() does in fact trigger the WebMoved event. The trouble is that this property is not exposed through the web-based settings page for the site, only the "Title" field is exposed, and this field change does not trigger the event. While this seems a bit counter-intuitive and even misleading, if you read the documentation literally, it is behaving exactly as documented.
Related
I'm working on a SharePoint publishing site and I want to "log" all the changes made by users in a SharePoint list.
Some searches on the web guided me to the EventReceiver.
But my EventReceiver must be generic and attached to all lists in the site collection. The "log list" has several columns like the name of the list in which the event occurred, the name of the modified item, its old value and its new value.
Can someone guides me on how to achieve this?
There's already a provided answer for you on StackOverflow, hurrayy!!
It sounds possible. Create a class that inherits from SPItemEventReceiver and override ItemUpdating. You can use the following code to get the list:
using (SPWeb web = properties.OpenWeb())
{
SPList list = web.Lists[properties.ListId];
}
You can then use list to grab the list's title and URL. Next, compare each DictionaryEntry entry in properties.AfterProperties to the corresponding value in properties.ListItem to get your differences. Then save it to your log list. The trick would be automatically attaching your Event Receiver to each newly created list. Perhaps a timer job would work.
That said...
Before trying any of that, go to your site collection's Site Settings. Under Site Collection Administration, click Site collection audit settings. Under Specify the Document and Item events to audit, check Editing items. Only go with a custom solution if that does not give you what you need.
Would Version history not achieve the same functionality?
You can see what fields were changed by who and when. Though you would have to look at a list by list basis.
You can also access the version history information via the object model if you want to generate reports web part.
Otherwise using Janis Veinbergs link on how to attach a event handler to all lists and Rich Bennema method of getting the values from the updated item in a generic way, though I would use ItemUpdated as you don’t want to change the data that was updated only copy it to another location so there is no need to catch the data before it is submitted to the SharePoint database
I am writing a web part against a list. The first thing I do in the web part is verify that my custom event receivers are registered on the list. If they are not, I register the programmatically.
I have noticed that if I try to register an event that is already registered, I get no errors and no “Extra” events are registered.
My question is: Would it be more efficient to just register the events each time the web part loads rather than iterating through each event in the event receiver list and doing compares to see if each of my event receivers are there?
Edit
About the Property bag suggestions. After thinking a bit more about it, this will not be a feasable solution. The reason that I am "verifying" that the receivers are there is because we have 3rd party webparts that are attached to the same list. These have, in the past, actually unregistered our custom receivers. Setting a flag in the property bag will just let me know that I have verified once, but won't tell me if they get removed by another.
The code that SharePoint uses to update an event receiver collection is obfuscated, so there's no way to know for sure. I would guess that the first step is a check similar to what you are doing manually. I'm inclined to go with what's easiest until you identify that performance is an issue, in which case I would set a flag on the list's RootFolder's property bag.
I unsure if this is best approach. I have seen a code that does something similar to your requirement. What it does is that once the EventHandler are added they stored a flag in the SPWeb Property Bag. Next time you just check the Property bag for the flag if it is there dont register the eventhandler . Refer this link for more information about the property bag. Final note you might need more permission to set the property bag value to SPWeb
I'm trying to find how a field's value has changed in an ItemUpdating event receiver. The particular field's display name and internal name is Regions.
As soon as ItemUpdating is hit, the value of the Regions field is identical for the following:
properties.AfterProperties["Regions"]
properties.BeforeProperties["Regions"]
properties.ListItem["Regions"].ToString()
I would expect the latter two to contain the old value but surely AfterProperties should be set correctly.
Does anyone know how I can obtain the changed value?
Update: The event handler is attached to a MOSS 2007 publishing Pages list.
I've had a lot of trouble with event handlers on publishing pages libraries. Think it comes from their being other event handlers on there already for publishing. I had better success with updating, can you change to that or do you need the sync event to block the change ?
Are you trying this in a List or Document Library ?
It will work Only on the Doc Lib Please refer to these
MSDN and another on same subject
I'm aware of the event receivers on a list for items added etc. However, I have not found a way to fire code upon the creation of a list.
What I'm trying to do is associate a workflow with a list when the list is created (by the user through the UI).
Anyone any ideas?
thanks.
There are a couple of routes you can take...
You can write your own list definition where you have defined the workflow association - That way all lists created based on your list definition, will contain your workflow on default.
Or... depending on your workflow... write an EventReceiver your attach to all lists of the type you wish to attach your workflow to (can easily be achieved tru a feature) and have your event receiver associate the workflow when the first item is added.
or you can associate the workflow to the contenttype used in the list (your own contenttype you attach to your own list definition or a default SharePoint contenttype)
I don't know the rest of your solution, so it's defficult for me to suggest the best solution for you.
What I (almost) always do, is write my own list definition - That way I can avoid problems like this, now or in the future.
With SharePoint 2010 it is now possible to hook into the list creation event by overriding the ListAdded event in the SPListEventReceiver class.
I usually deploy an extra view page which is set to the default view. When the user creates the list he will be sent to the viewpage which contains the setup in code behind. The view page then calls a method ive created, which changes the default view, removes the setup view and change any navigation node pointing to the setup view.
There is probably no perfect answer to this question because there is no list added event receiver (if memory serves me correct).
I don't know if this is the case, but if you really just needed to register an itemadded (or updated, deleted, etc.) event to any new list, I believe you can register the those events at the site (SPWeb) level and they will fire on any new lists created.
Which is the best way to display a custom form for each new document being added to a specific document library?
I want the user to have some control over some actions that adding the document will cause - specifically, tasks created for users in a Task List, which the contributing user will have to OK before committing.
Is the best way to do this via a Workflow or an event handler?
Regards
Moo
For SharePoint server 2007:
A combination of a specialised content type and an event handler will give you the most control of the process (easier to debug too). A workflow is best for "easy" actions and is harder to make complex actions happen.
A workflow allows for more flexibility in assigning the workflow to different libraries by site admins.
Roll your content type and event handler into a feature that can be deployed. Assigning the content type to a list will allow you to take any data created by the standard form (remember you can create custom fields for really complex/custom data entry) and take any action required, including creating tasks based on the item.
Thanks for the answer, thats the route I was investigating but unfortunately I haven't found a way to make it work for Document Libraries - only Lists.
The problem I have come across is that aving a SPUtility.Redirect in the ItemAdded, ItemAdding, ItemCheckingIn or ItemCheckedIn event on the document library doesn't do anything at all, because there is no page related to the events - its all backend code being fired that is not linked to a web context, because its not the webpage doing the heavy lifting at that point but the Office integration.
All of the examples I have come across seem to rely on the fact that the EditForm.aspx or NewForm.aspx page is being displayed at the time the event is fired, which of course is not the case here.
This also leads to the problem that I cannot extend the EditForm.aspx or the CheckIn.aspx page to do what I want either, because Office 2007 circumvents both of these.
So, the only option left open to me at the moment is doing it through a workflow :/
Any further tips would be fantastic.
I may not understand your question, but is this close to what you're trying to do?
http://msdn.microsoft.com/en-us/library/ms550037.aspx
If not, in what way does this come up short?
A new "Content Type" with its New Form url set to the appropriate value should do the trick.
Unfortunately you may not be able to achieve what you are trying to with an Event Handler or a Workflow. You would ideally want the form to show up as soon as the user adds a new item to the library and a custom content type will do the trick.
Create a new Content Type. (Derive it from the existing Content Type)
Remove the default content type from the doc library.
Using the Object Model to set the New Form url to an aspx page or an Infopath form you've created.
Kind regards,