JustNik

Umbraco Forms and the Query String - A dilemma

Umbracologoblue05
The following information came to light using Umbraco v8 and Umbraco Forms v8 - it may or may not still be the case with v9+!.

Introduction

Today I found myself investigating an issue where some work had been completed to allow an Umbraco Form submission to result in a redirection to a 3rd party website. However when it was being tested, clicking the submit button on the Umbraco Form was resulting a Null Reference Exception - as any .Net developer will know, these are great fun to investigate, especially when they are being thrown in a closed source bit of code, in this case by the Umbraco Forms Controller. It's even more fun when my initial testing did not result in the same problem.

The form in questions was using magic strings (v9 version help), specifically ones that read values from the Request object to pre-populate some values on the form, one of which would then be used post submission to return the visitor to their original website.

TLDR

Query String parameters called "model" will break Umbraco Forms form submissions because of classic .Net Framework model binding behaviour.

The problem

As mentioned in the introduction, when this was being tested, the form was failing to submit throwing an Object not set error in the UmbracoFormsController.HandleForm method, all other forms on the site were still working and my test form on my local environment would submit successfully reading values from the query string.

The investigation

Fortunately this site was running in Umbraco Cloud which allowed me to restore the problematic form into my local environment to try and help me investigate further. So, after the form (and thank you page) was restored I set about testing.

Step 1: Put the form on a page - I already had a test page which I had been using previously so I updated the picked form.
Step 2: Load the form - So I loaded the page with the form in question, added the querystring - which looked something like this ?make=xyz&model=F40&value=35000.... (there were a few other bits that made up the query string, but you get the idea).
Step 3: Populate the remaining required fields
Step 4: Submit the form - And boom, the exception is thrown - okay great, now it's repeatable - there must be something wrong with this form.. right?

So, now I had the problem locally I set about trying to figure out why. The form had a few fields where the alias's were really long, which used to be problematic.. lets remove those, well actually I just updated the aliases to be shorter initially but the problem still occurred. Then I removed the fields in question completely, nope, still a problem. Next up, lets remove the workflow that was using a custom email template just in case. Again no dice. Finally, let's systematically remove all the questions on the form, one at a time and re-test the form. Each time the form still threw the same problem. What the hell!

Okay, so let's create a brand new form with no questions on it. Nope, that doesn't work and throws the error still....

Finally, let's put it back to the form we know was working - and now this is broken! Seriously! Any form I test is now broken!

At this point I raised the question to the Umbraco MVP's and a few other people as I was out of ideas (I'd already spoken to a colleague about it as well) - this was making no sense!

My question was:

Afternoon everyone - before I post this more publicly... does anyone have advice on debugging a null reference exception being thrown by Umbraco forms (v8 compatible version) when the form is submitted.


The stack trace indicates that the error is thrown in the "UmbracoFormsController.HandleForm" method and as this is all closed source I have no idea how to figure out what is null! When I look at the request being sent to the server it looks like it's fully populated.

A few people suggested overriding the UmbracoFormsController with my own controller so that's what I did, very simply I created the following class:

public class MyFormsController : UmbracoFormsController
{
    //..constructor omitted for ease

   [HttpPost]
   //additional attributes omitted for ease
   public ActionResult HandleFormSubmission (FormViewModel model)
   {
           return base.HandleForm(model);
   }
}

Once this was created the question was, how do I get Umbraco Forms to use this controller - well that was actually really easy.

Turns out you only need to update the forms Render.cshtml where BeginUmbracoForm is being called. So I updated this call to reference my custom controller and my handle form submission method.

Hey presto, I was able to intercept the form submission which was great. Now I could start trying to figure out what was null.

The model was null

Are you kidding me! How is the model null! The form is submitting the data, I can see it in the network tab of the browsers dev tools! How can the model be null!

The above is a short summary of the questions I was asking myself at this point!

But wait, no, it couldn't be... could it?... really? - I loaded the test page without a query string component and tested the form.

I'm pretty sure most people in a 10 mile radius could heard the thud as my head hit the desk! It worked, the form submitted with no issues. Why it took this long for me to try this I have no idea.

Did you know in Net Framework...

Did you know that in .Net Framework, controllers automatic model binding looks at both the Query String and the Form Data/request payload even on a post request and unlike in dotnet, there isn't (as far as I'm aware) a way to explicitly tell the binding where to look. As the query string contained a parameter called "model" this was attempting to bind to the action parameter of the same name, and this was overriding the binding from the form data (for some unknown reason).

So that was the problem! Now what was the solution.. well workaround.

The solution

Simply, a minor tweak to the custom controller, let's rename the action parameter from model to umbFormModel. Suddenly everything started working! Although it does mean I still need the custom controller to act as a bit of middleware between the form submission and Umbraco's core controller.

Code:

This is a version of the final amends:

//Controller
public class MyFormsController : UmbracoFormsController
{
    //..constructor omitted for ease

   [HttpPost]
   [ValidateFormsAntiForgeryToken]
   [ValidateInput(false)]
   public ActionResult HandleFormSubmission (FormViewModel umbFormModel)
   {
           return base.HandleForm(umbFormModel);
   }
}

//Update to Render.cshtml
@using (Html.BeginUmbracoForm<MyFormsController>("HandleFormSubmission", null, Model.HtmlAttributes))

Thanks for reading.

JustNik
Connect with me
Twitter GitHub LinkedIn
© JustNik 2025