Banner

QuerySelectorAll Error on BeginFormSitefinity

Jun 27, 2017

When developing a custom form on Sitefinity MVC widgets, the HTML helper method Sitefinity provides, Html.BeginFormSitefinity(), is a very handy resource. You wrap your form elements up inside the whole thing, along with a submit button, and you can point it at an HttpPost Action on your custom MVC widget controller with ease. When you’re putting your form widget on a master page, however, you can run into a rather vague JavaScript error that prevents your form from submitting correctly. The error in JavaScript brings up something about querySelectorAll and you’re left scratching your head as to what you did wrong. The issue, in actuality, is a simple one, with a simple fix.

Only Applies to Master Page-backed Templates

This issue only occurs on master pages, as Sitefinity has to work around the case where the entire page is wrapped in a <form> element. For pure MVC pages (ones based on MVC templates) all Sitefinity does is insert its own <form> tag, and this issue does not occur.

The Problem

When you invoke Html.BeginFormSitefinity() on a page using a template with a master page as its base, it inserts a segment of JavaScript onto the page. This JavaScript encapsulates all the form values and ships them off to whatever controller Action that you specified. The primary issue with this JavaScript snippet is that it makes a rather bold assumption with regards to the <form> tag on your ASP.NET master page. Have a look at the generated snippet of code:

(function () {
    var container = document.getElementById("FormElementsContainer");
    if (container === null)
        return;
  
    var inputs = container.querySelectorAll("input");
    var allInputs = document.forms["aspnetForm"].querySelectorAll('input');
     
    /* rest snipped out */
})();

See where querySelectorAll is being used with regards to the document’s forms? It is depending on your master page <form> to have an ID of “aspnetForm”. When I create new master pages in Visual Studio, it tends to default the <form>’s ID to “form1”, which leads into this BeginFormSitefinity-related error a lot of the time.

The error you run into looks something like this. It occurs when the page is loaded, and trying to submit the form just causes a page refresh with no action taken:

“Uncaught TypeError: Cannot read property ‘querySelectorAll’ of undefined”

The Fix (Plus a Workaround)

As talked about above, the fix is a very trivial one. You don’t have to change a thing about BeginFormSitefinity, but instead you just open up your master page and change the ID of the <form> wrapper tag to “aspnetForm”. If you have other code depending on the original <form> ID, or cannot edit the master page, or are otherwise prevented from making this fix, there’s a workaround that can be done: On the page(s) with your custom MVC form, add a simple snippet of JavaScript to update the <form> tag’s ID at runtime.

$("form").attr("id", "aspnetForm")

As long as your snippet runs before the BeginFormSitefinity JavaScript is reached, it will run normally.

Going Forward

At the time of writing, while Progress has acknowledged that this is a bug, there is still no fix, completed or scheduled, for it. Until Progress fixes this issue, I would recommend always coding your master pages so that the <form>’s ID is set to “aspnetForm” out of the gate. Even if you’re not yet using Html.BeginFormSitefinity, it will be best to head off this potentially-frustrating error before it happens.

Load more comments
comment-avatar

Copyright © 2017 Alain "Lino" Tadros