[ASP.NET MVC] ‘formElement is null’ o como un pequeño error te hace perder el tiempo…

Hola! Esta es una breve historia de un pequeño error que cometí y que quiero compartir con vosotros… por si acaso 🙂

Tenía una aplicación ASP.NET MVC que usaba DataAnnotations para la validación de los modelos. El uso de DataAnnotations para permitir la validación de modelos en ASP.NET MVC es muy simple. El primer paso es decorar la clase modelo con los atributos que indican las validaciones a realizar:

public class FooModel
{
[Required(ErrorMessage="Debe entrar un valor!")]
public string Name { get; set; }
}

Aquí simplemente indicamos que la propiedad ‘Name’ debe ser obligatoria. Hay otros validadores como RegularExpressionAttribute que valida contra una expresión regular o RangeAttribute que valida entre rangos, entre otros (y obviamente nos podemos crear los nuestros).

La vista para editar elementos de tipo FooModel es también muy sencilla:

<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<FooMvc.Models.Home.FooModel>" %>

<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
Index
</asp:Content>

<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">

<h2>Index</h2>

<% Html.EnableClientValidation(); %>
<% using (Html.BeginForm()) {%>
<%: Html.ValidationSummary(true) %>

<fieldset>
<legend>Fields</legend>
<div class="editor-label">
<%: Html.LabelFor(model => model.Name) %>
</div>
<div class="editor-field">
<%: Html.TextBoxFor(model => model.Name) %>
<%: Html.ValidationMessageFor(model => model.Name) %>
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
<% } %>
</asp:Content>

Fijaos en la llamada a Html.EnableClientValidation() que lo que hace es habilitar las validaciones en cliente (además de las de servidor claro, recordad que siempre debe validarse en servidor con independencia de que también se valide en cliente). Si no usamos EnableClientValidation() tenemos sólo validación en servidor. El uso de la validación en cliente requiere el uso de la ajax library, así que en mi master page he incluído lo siguiente:

<script src="../../Scripts/MicrosoftAjax.js" type="text/javascript"></script>
<script src="../../Scripts/MicrosoftMvcAjax.js" type="text/javascript"></script>
<script src="../../Scripts/MicrosoftMvcValidation.js" type="text/javascript"></script>

Finalmente queda sólo el controlador… Es extremadamente simple:

public class HomeController : Controller
{
public ActionResult Index()
{
return View();
}

[HttpPost()]
public ActionResult Index(FooModel model)
{
if (ModelState.IsValid)
{
// Validación OK
}
else
{
return View(model);
}
}

}

El método Index sin parámetros es el que responde a la petición GET /host/Home/Index y devuelve la vista. Cuando se hace submit del formulario, se llama a /host/Home/Index pero usando POST por lo que se usa el método Index que recibe un FooModel. ASP.NET MVC hace binding automáticamente entre los parámetros POST y las propiedades de FooModel, por lo que obtenemos el objeto con los datos del usuario. La propiedad ModelState.IsValid me devuelve si las validaciones son correctas o no (y si no lo son, generalmente lo que se hace es mostrar de nuevo la vista para que el usuario pueda corregir los datos).

Hasta ahí todo normal… sólo que a mi no me funcionaba. Recordad que había habilitado las validaciones en cliente, así que si hacía submit del formulario sin entrar ningún valor para la propiedad Name, me debería mostrar el error sin hacer POST… pero me lo hacía. Es decir, me ignoraba las validaciones en cliente.

Después de varios intentos y mirando que podía estar pasando, lo ejecuté con Firefox para ver si es que se daba algún error de javascript (internet explorer no me decía nada). Y efectivamente en la consola de javascript de Firefox me aparecía un error: formElement is null.

Una búsqueda en Google no me dio muchos resultados… A alguien más le pasaba lo mismo pero ninguna de las respuestas eran aplicables a mi caso. Después de algunas paranoias (era mi primer proyecto asp.net mvc2 con el vs2010 rtm y a lo mejor algo no se había instalado bien), investigando el código html generado vi esto:

<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="/wEPDwUJNDEyOTQxNTc1ZGRm6ES0w4WmJi1Rd8IlwFU8wFLynCBA/haT9Dce2tSlxQ==" />

Coooomo??? Un Viewstate??? Y que se supone que hace aquí? Bueno… Pues sabéis de donde venía? Pues de aquí:

<form id="form1" runat="server">
<div>
<asp:ContentPlaceHolder ID="MainContent" runat="server">
</asp:ContentPlaceHolder>
</div>
</form>

Y donde estaba este maléfico <form runat=”server”>? Pues sí, sí: en la master page.

Y por qué? Bueno… pues porque cuando añadí la master page me equivoqué y añadí una “Master Page” en lugar de una “MVC 2 View Master Page”:

image

Así que esa es mi historia de como un error tonto puede llegar a darte verdaderos quebraderos que cabeza… 🙂

Un saludo!

PD: Y ahora voy a escribir 100 veces “cuando añada una master page a mi proyecto, voy a fijarme que sea una master page de MVC 2”… 🙂

5 comentarios sobre “[ASP.NET MVC] ‘formElement is null’ o como un pequeño error te hace perder el tiempo…”

  1. @Luis
    Que bueno el vídeo, jejejeeee… 😛 😛 😛 😛

    No te digo como me sentí cuando descubrí que había pasado… 🙂 ^_^

    Un saludo!!!

  2. José,

    Me acabas de dar una alegria increible! Vengo hace tres dias con un error muy parecido, en firefox no me generaba el form tag en una partial view.

    Probé lo que hiciste y funciono!

    creo que volvi a ver la luz.. jaja.

    Gracias!

Responder a lruiz Cancelar respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *