SPContext.Current.FormContext.OnSaveHandler Not Firing from Custom Field Type Control

1k views Asked by At

I am having the exact same problem described here. Unfortunately because I don't have 50 points yet I can't comment on it so I have to create a new duplicate question.

I mean it's not "100% EXACTLY" like the other guy's problem because for me the problem exists on the Edit Form and I'm using a combination of custom forms and fields. But I am adding the custom save event handler at the field level per suggestion #2 made by the guy at this site. I should also note that when I create a new Document Library without any custom forms or Content Types and just use my custom fields straight-up, the event handler also does not fire. If however I create a new regular SharePoint list and add the custom fields then the OnSaveHandler DOES fire! I So I'm not quite sure why it doesn't work in Document Libraries but it does work in lists because I was under the impression that the beauty of custom fields was that they operate independently of everything else. Meaning, even if I was doing something wonky with my Edit Form or some other control, since I am attaching my custom method to the SPContext.Current.FormContext.OnSaveHandler in the OnInit method of my custom field then that should fire no matter what! Even when the field is being loaded for the first time I actually see the event being wired up in the debugger. In debug mode I have a breakpoint next to the "if" statement below and it hits that breakpoint which means that when the FormContext.OnSaveHandler is triggered my method should fire.

protected override void OnInit(EventArgs e)
{
  base.OnInit(e);

  if ((SPContext.Current.FormContext.FormMode == SPControlMode.New) ||  (SPContext.Current.FormContext.FormMode == SPControlMode.Edit))
    SPContext.Current.FormContext.OnSaveHandler += new EventHandler(MyHandler);
}

Any thoughts? Suggestions?

Thanks!

UPDATE #1: After a little troubleshooting I was able to deduce that the EventHandler in my custom field was being fired but ONLY when used in regular lists and NOT Document Libraries! In regular SharePoint lists not only is the SPContext.Current.FormContext.OnSaveHandler being fired but the values from the custom fields are being saved as well.

As a side note, when saving the data back to my custom field that inherits from SPFieldText, the value (which is json data) displays in the list view as #VALUE!, which I think is kind of weird. I mean it's able to read the json data that's stored in the field correctly because it shows up in the Edit Form just fine. But for some reason SharePoint just displays it as #VALUE! in the list view.

1

There are 1 answers

0
Ami Schreiber On

So after many frustrating hours it looks like there are several issues that arise when using custom fields in a Document Library.

  1. You can't use them in any meaningful way and expect the data to be saved when using a custom upload page. In other words, if you want to create your own custom upload page that combines the file upload input field and browse button along with your own custom fields embedded in a ListFieldIterator then the values WILL NOT BE SAVED. This is a fact! The reason is that the operation for uploading the file and creating the initial ListItem along with generating it's ID value occurs ASYNCHRONOUSLY with respect to the ListItem EventReceiver. So what does this mean exactly? It means that when you try to access the values stored in your custom field(s) in the SPItemEventProperties parameter of the ItemAdded method in the ListItem's Event Receiver all of those values will be null since the current SPContext is completely unaware of the existence of those fields and their respective values because all of the events that occur with respect to the initial document upload are executed in a different thread...asynchronously. Conversely, when the custom fields attempt to "save themselves" back to the newly uploaded document the SPField.ListItem's document ID is still set to zero because these custom fields are...you guessed it, executing in a different thread and are not "in synch" with the upload event that took place which generated the new document ID. Although I've read about a few different workarounds regarding this issue, none of them seem to work, or they are very convoluted or require you to abandon using custom fields which isn't really a workaround but more of a "throwing in the towel". One suggestion was to simply update the Elements.xml file for the EventReceiver by simply adding a "Synchronous" entry to force the event to occur synchronously instead of asynchronously. At first I thought this was too easy and too good to be true. As it turns out, I was right. :)
  2. You can't nest a custom ListFieldIterator inside a custom control and expect your custom fields to save the data that they contain. You MUST use the ListFieldIterator directly in your form template. Period! If you try and wrap the ListFieldIterator with your custom fields in a custom control you will be very frustrated with the results.

As a side note, once the document has been uploaded and an ID has been created, you CAN enter data into your custom fields in the Edit Form and the values WILL be saved because now your code will actually be able to reference the ListItem's ID value since the ListItem will already exist in the list. Again, this is contrary to a custom upload form where the ID for the ListItem does not yet exist because you haven't actually uploaded the document yet.

I REALLY wish that Microsoft would provide some sort of update that would allow developers to get around this issue with Document Libraries and I think that it's pretty clear that they knew this was an issue when they first released SharePoint which is why the default behavior for the Document Library "New Form" is to present the user with a standalone Upload form which then redirects the user to the Edit Form so that they could avoid all of this. Of course this leaves developers who wish to allow users to upload a document and enter data on the same screen without a leg to stand on when using custom fields. Your only alternative is to use custom forms and programmatically set all of the field values and add in tons and tons of conditional logic for every single permutation of all the different fields and layout possibilities but that's a whole other animal and certainly defeats the whole reason why Microsoft created the concept of custom fields in the first place!