Custom list NewForm.aspx ruined in WSS 3.0

Yesterday, I spent 3 hours debugging what's the problem with my custom list after I changed its NewForm.aspx page.

Here are the symptoms: I went to SharePoint Designer 2007, opened NewForm.aspx, deleted the ListFormWebPart web part from it and inserted a Custom List Form (Insert/SharePoint Controls/Custom List Form). Then, I saved it. After I went back to my list and clicked on <New> to create a new item, I got the following popup: "Invalid page URL:" and that's it. The other symptom I found was that when I clicked on the items already created to see them (DispForm.aspx), I got a page with the following text: "An unexpected error has occurred. ", with no further information. I then browsed to NewForm.aspx, which worked well. So, the problem should be something like SharePoint can't find where to go to create a new item.

I then started troubleshooting the problem: back to SharePoint Designer, reset back the page to the site definition, with no luck. Back to SharePoint Designer again, checked the list properties, found that the New item form URL on the Supporting Files is empty. I restored back to the NewForm.aspx, still no luck. Of course, I ran IISRESET after every modification.

Then, I shifted to 2nd gear, set the configuration/SharePoint/SafeMode/CallStack parameter to true and Configuration/system.web/customErrors/mode to Off in web.config (under InetPub\wwwroot\wss\VirtualDirectories\<SiteName> ) to see the call stack on the DispForm.aspx (IISRESET needed then). Here it is:

Object reference not set to an instance of an object.

...

Stack Trace:

[NullReferenceException: Object reference not set to an instance of an object.]

   Microsoft.SharePoint.WebControls.NewItemButton.OnLoad(EventArgs e) +364

   System.Web.UI.Control.LoadRecursive() +47

   System.Web.UI.Control.LoadRecursive() +131

   System.Web.UI.Control.LoadRecursive() +131

   System.Web.UI.Control.LoadRecursive() +131

   System.Web.UI.Control.LoadRecursive() +131

   System.Web.UI.Control.LoadRecursive() +131

   System.Web.UI.Control.LoadRecursive() +131

   System.Web.UI.Control.LoadRecursive() +131

   System.Web.UI.Control.LoadRecursive() +131

   System.Web.UI.Control.LoadRecursive() +131

   System.Web.UI.Control.LoadRecursive() +131

   System.Web.UI.Control.LoadRecursive() +131

   System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +1061

So, the problem occurres in the Microsoft.SharePoint.WebControls.NewItemButton.OnLoad method, which is in Microsoft.SharePoint.dll. So, I attached a debugger to w3wp.exe on the server, set a breakpoint to Microsoft.SharePoint!Microsoft.SharePoint.WebControls.NewItemButton.OnLoad (using WinDbg, the SOS 2.0 extension and the !name2ee and !bpmd commands), and checked where does it fail. Unfortunately, I have no source access to SharePoint 2007, but I could reverse engineered with Lutz Roeder's .NET Reflector, then debugged the assembly code and found that the code fails on the following code line:

base.NavigateUrl = base.Web.GetServerRelativeUrlFromUrl(base.List.Forms[PAGETYPE.PAGE_NEWFORM].Url) + "?Source=" + SPHttpUtility.UrlKeyValueEncode(SPHttpUtility.UrlPathEncode(this.RedirectUrl, true));

We are failing at the red call when we try to retrieve the Form item. We are not even getting the Url property of the Form, this is why we get the “Object reference not set to an instance of an object” hresult. It seems that there’s no PAGETYPE.PAGE_NEWFORM item in the Forms collection. I guess, this is what I can set on the list properties with SharePoint designer (display, edit and new form Urls). So, even if SharePoint Designer shows that the new form set fine, SharePoint can't get it.

Then, I started a Profiler Trace on the SQL Server to check what's the problem. After started the trace, I opened the list properties from SharePoint Designer and captured the SQL calls going to the WSS database. The spotlight went to the following stored procedure then: proc_GetListWebParts. I found that this sp produces a line for each webparts related to a given list. In my case, it produced 2 different lines for the new page webpart. So, the problem seems to be that SharePoing gets too much information and can't decide which New Page is the real one.

I could fix the problem by hacking the AllDocs and WebParts table, but my WSS 3.0 is in an unsupported state now. If you can't do anything else, the point is that you have to have one line for each web part and you have to do different modifications in the tables above to fix the output of this stored procedure. I also found that if you don't have a ListFormWebPart web part associated with your list on the NewPage.aspx page, you won't get a record to these tables. It doesn't make sense to write more details here, the best thing is if you take a look at the proc_GetListWebParts sp's code and find how the output is produced. The whole thing could be a bit messy.

The problem is that I can't repro the very same problem in my test environment, so the problem could be something specific to my Customer's test environment where I found the problem. I hope that it helps at least localize the problem for someone else. Unfortunately, I don't know any *SUPPORTED* solution for this problem at the moment. If I'll have any updates, I'll follow up on that. In the meantime, if you experience the problem, please write a comment here!

POST-COMMENT: RESOLUTION

Just a quick update - in case if you want to customize your edit form and you haven't "ruined" it yet: hide the ListFormWebPart control and insert the Custom List Form control to your page. You can use this control to customize your form's fields. I published a KB article about this issue at the following location:

Error message when you click "New" to create a new item in a list or when you click an existing item in SharePoint Server 2007: "Invalid page URL" or "An unexpected error has occurred" support.microsoft.com/?id=935504

This is a bug in WSS and might be fixed in the future releases.

POST-POST COMMENT: ALTERNATIVE RESOLUTION

There were many different solutions posted to the comments section in my blog post in the last period of time. Tim Frodermann was kind enough to summarize the best resolution from myang and AngelIndaux:

Here is what I did from A to Z to recover my ruined NewForm.aspx (based upon myang's and AngelIndaux's posts):

1. Open NewForm.aspx and EditForm.aspx in Sharepoint Designer

2. Copy the code for the ListFormWebPart control from the EditForm.aspx. The code in question reaches from

<WebPartPages:ListFormWebPart runat="server" __MarkupType="xmlmarkup" WebPart="true" __WebPartId="{YOUR_GUID}" >

down to

</WebPartPages:ListFormWebPart>

3. Paste it into the broken NewForm.aspx, I pasted it right below the Line:

<WebPartPages:WebPartZone runat="server" FrameType="None" ID="Main" Title="loc:Main"><ZoneTemplate>

4. Within the pasted lines of code look up the lines starting with

<ControlMode

and

<FormType

In the "Control mode" tag replace the "Edit" with "New", in the "FormType"-Section replace the digit "6" with "8".

5. Before saving, you have to generate a new GUID for the pasted control in your NewForm.aspx otherwise your EditForm.aspx will be broken after saving!!!

There are online GUID generators on the internet so you don't need Visual Studio, e. g.:

<www.somacon.com/p113.php>

Generate a new GUID and asign it to the "__WebPartId" attribute in the very first line of code of your control:

<WebPartPages:ListFormWebPart runat="server" __MarkupType="xmlmarkup" WebPart="true" __WebPartId="{YOUR_NEW_GUID_HERE}" >

6. Look up the <ID></ID>-Tag further below (it was about 27 lines below in my case) and change a random number in the ID, e. g.

Before: <ID>g_092cc5f1_f97c_408b_bf66_c7b235af38f9</ID>

After:

<ID>g_092cc5f1_f97c_408b_bf66_c7b235af38f5</ID>

7. Save your work...and your done!

POST-POST-POST COMMENT: YET ANOTHER ALTERNATIVE RESOLUTION

Josh Fraser came up with an alternative solution – thanks Josh for sharing it:

“If you leave the NewForm.aspx just the way it is, create a copy and use the copy to create your custom form, it works like a charm. You can even delete the list form web part from the custom page. WSS can be an odd arena to play in some days.

One thing to note: when you create a custom New/Edit/View form you need to right click on the list in sharepoint designer and select "supporting files" ensure that the new page for "Item" is pointed to the new ASPX file:

clip_image002”. Thank you Josh, again!