[ASP.NET] Validaciones no intrusivas en ASP.NET 4.5
Publicado por Julio Avellaneda en 09/02/2012
Hola a todos, volviendo al desarrollo Web, hoy quiero aprovechar este post para mostrar una de las nuevas características de ASP.NET 4.5 que son las validaciones no intrusivas y el error que vamos a obtener cuando creamos una nueva aplicación Web.
Vamos a crear una nueva aplicación Web, agregar una nueva página aspx y allí vamos a tener un formulario para el registro de personas, adicionalmente usaremos algunos validadores que ofrece ASP.NET (si no los conoces revisa este post), entonces el sencillo código que necesitamos es:
1: <form id="form1" runat="server">2: <div>3: <table>4: <tr>5: <td>Nombre:</td>6: <td>7: <asp:TextBox ID="txtNombre" runat="server" Width="300px"></asp:TextBox>8: <asp:RequiredFieldValidator ID="requiredNombre" runat="server" ControlToValidate="txtNombre" ErrorMessage="*"></asp:RequiredFieldValidator>9: </td>10: </tr>11: <tr>12: <td>Correo:</td>13: <td>14: <asp:TextBox ID="txtCorreo" runat="server" Width="300px"></asp:TextBox>15: <asp:RequiredFieldValidator ID="requiredCorreo" runat="server" ControlToValidate="txtCorreo" ErrorMessage="*"></asp:RequiredFieldValidator>16: </td>17: </tr>18: <tr>19: <td>Usuario:</td>20: <td>21: <asp:TextBox ID="txtUsuario" runat="server" Width="300px"></asp:TextBox>22: <asp:RequiredFieldValidator ID="requiredUsuario" runat="server" ControlToValidate="txtUsuario" ErrorMessage="*"></asp:RequiredFieldValidator>23: </td>24: </tr>25: <tr>26: <td>Clave:</td>27: <td>28: <asp:TextBox ID="txtClave" runat="server" Width="300px" TextMode="Password"></asp:TextBox>29: <asp:RequiredFieldValidator ID="requiredClave" runat="server" ControlToValidate="txtClave" ErrorMessage="*"></asp:RequiredFieldValidator>30: </td>31: </tr>32: <tr>33: <td><asp:Button ID="btnGuardar" runat="server" Text="Guardar" /></td>34: </tr>35: </table>36: </div>37: </form>
Como vemos, el HTML es muy simple, peor ahora si lanzamos la aplicación vamos a obtener el siguiente error:
Extraño no? simplemente creamos una página bastante sencilla (sin nada de código de servidor) y ya está fallando… pero si revisamos un poco el error vemos que dice “WebForms UnobtrusiveValidationMode requires a ScriptResourceMapping…” y ya tenemos una idea del error, lo que pasa es que con ASP.NET 4.5 tenemos una nueva característica la cual reducir la cantidad de código JavaScript necesario, la definición exacta dice:
You can now configure the built-in validator controls to use unobtrusive JavaScript for client-side validation logic. This significantly reduces the amount of JavaScript rendered inline in the page markup and reduces the overall page size.
Y dicha característica viene habilitada por defecto, para deshabilitarla vamos a nuestro Global.asax y en el evento Application_Start le decimos:
1: ValidationSettings.UnobtrusiveValidationMode = System.Web.UI.UnobtrusiveValidationMode.None;
Y ahora si lanzamos de nuevo la aplicación va a funcionar… pero no estaríamos aprovechando la validación no intrusiva, y si revisamos el HTML que es generado en el cliente tenemos:
1: <!DOCTYPE html>2:3: <html xmlns="http://www.w3.org/1999/xhtml">4: <head><title>5: Formulario6: </title></head>7: <body>8: <form method="post" action="index.aspx" onsubmit="javascript:return WebForm_OnSubmit();" id="form1">9: <div class="aspNetHidden">10: <input type="hidden" name="__EVENTTARGET" id="__EVENTTARGET" value="" />11: <input type="hidden" name="__EVENTARGUMENT" id="__EVENTARGUMENT" value="" />12: <input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="2pkd4JZKXmDyDJwu0HIaaT5x/EzINW3Fmj5ECNYtq721M2fzxgYIW/yLzuVDUpE6C5+JtdW4Mo7Mh7EH1jcQPCiVMtXSlRRYD3i7hJ3zQLM=" />13: </div>14:15: <script type="text/javascript">16: //<![CDATA[17: var theForm = document.forms['form1'];18: if (!theForm) {19: theForm = document.form1;20: }21: function __doPostBack(eventTarget, eventArgument) {22: if (!theForm.onsubmit || (theForm.onsubmit() != false)) {23: theForm.__EVENTTARGET.value = eventTarget;24: theForm.__EVENTARGUMENT.value = eventArgument;25: theForm.submit();26: }27: }28: //]]>29: </script>30:31:32: <script src="/WebResource.axd?d=pynGkmcFUV13He1Qd6_TZAlhwiK26CMjFC_AwUoa5b3ERCspA6cmt_C-L8IOpCe633BVnc0wcDgTvonIIsSvwQ2&t=634776373276709129" type="text/javascript"></script>33:34:35: <script src="/WebResource.axd?d=x2nkrMJGXkMELz33nwnakEDhIJdn4zA9e1UqVq1SVvHhRhIprKEH70Wnr0YNmajC6LdVxQkRSvYza9nzCfZpzIEPGw7MYTdtpXpxdmoJjww1&t=634776373276709129" type="text/javascript"></script>36: <script type="text/javascript">37: //<![CDATA[38: function WebForm_OnSubmit() {39: if (typeof(ValidatorOnSubmit) == "function" && ValidatorOnSubmit() == false) return false;40: return true;41: }42: //]]>43: </script>44:45: <div class="aspNetHidden">46:47: <input type="hidden" name="__EVENTVALIDATION" id="__EVENTVALIDATION" value="bZYSXvfMEK7zHv9kV0tE+oZEnunr/8QE7gS9ULLQ4JyQa0/rv/1MRHr1bmVesMg6m/hAbEjp+lbFzmo0SV+QBKLDALpSfGJ0DfJ5FA03pkiwbqmguFNLc2gD7rvhbwgkveOk/e6MOPe2FJKM0lEwaBBiTadifQmqoEyokjWDmTbeUzilOBcBLxfc4JnhDC5gTorEWeVaxxVnfEZrKxCLsg==" />48: </div>49: <div>50: <table>51: <tr>52: <td>Nombre:</td>53: <td>54: <input name="txtNombre" type="text" id="txtNombre" style="width:300px;" />55: <span id="requiredNombre" style="visibility:hidden;">*</span>56: </td>57: </tr>58: <tr>59: <td>Correo:</td>60: <td>61: <input name="txtCorreo" type="text" id="txtCorreo" style="width:300px;" />62: <span id="requiredCorreo" style="visibility:hidden;">*</span>63: </td>64: </tr>65: <tr>66: <td>Usuario:</td>67: <td>68: <input name="txtUsuario" type="text" id="txtUsuario" style="width:300px;" />69: <span id="requiredUsuario" style="visibility:hidden;">*</span>70: </td>71: </tr>72: <tr>73: <td>Clave:</td>74: <td>75: <input name="txtClave" type="password" id="txtClave" style="width:300px;" />76: <span id="requiredClave" style="visibility:hidden;">*</span>77: </td>78: </tr>79: <tr>80: <td><input type="submit" name="btnGuardar" value="Guardar" onclick="javascript:WebForm_DoPostBackWithOptions(new WebForm_PostBackOptions("btnGuardar", "", true, "", "", false, false))" id="btnGuardar" /></td>81: </tr>82: </table>83: </div>84:85: <script type="text/javascript">86: //<![CDATA[87: var Page_Validators = new Array(document.getElementById("requiredNombre"), document.getElementById("requiredCorreo"), document.getElementById("requiredUsuario"), document.getElementById("requiredClave"));88: //]]>89: </script>90:91: <script type="text/javascript">92: //<![CDATA[93: var requiredNombre = document.all ? document.all["requiredNombre"] : document.getElementById("requiredNombre");94: requiredNombre.controltovalidate = "txtNombre";95: requiredNombre.errormessage = "*";96: requiredNombre.evaluationfunction = "RequiredFieldValidatorEvaluateIsValid";97: requiredNombre.initialvalue = "";98: var requiredCorreo = document.all ? document.all["requiredCorreo"] : document.getElementById("requiredCorreo");99: requiredCorreo.controltovalidate = "txtCorreo";100: requiredCorreo.errormessage = "*";101: requiredCorreo.evaluationfunction = "RequiredFieldValidatorEvaluateIsValid";102: requiredCorreo.initialvalue = "";103: var requiredUsuario = document.all ? document.all["requiredUsuario"] : document.getElementById("requiredUsuario");104: requiredUsuario.controltovalidate = "txtUsuario";105: requiredUsuario.errormessage = "*";106: requiredUsuario.evaluationfunction = "RequiredFieldValidatorEvaluateIsValid";107: requiredUsuario.initialvalue = "";108: var requiredClave = document.all ? document.all["requiredClave"] : document.getElementById("requiredClave");109: requiredClave.controltovalidate = "txtClave";110: requiredClave.errormessage = "*";111: requiredClave.evaluationfunction = "RequiredFieldValidatorEvaluateIsValid";112: requiredClave.initialvalue = "";113: //]]>114: </script>115:116:117: <script type="text/javascript">118: //<![CDATA[119:120: var Page_ValidationActive = false;121: if (typeof(ValidatorOnLoad) == "function") {122: ValidatorOnLoad();123: }124:125: function ValidatorOnSubmit() {126: if (Page_ValidationActive) {127: return ValidatorCommonOnSubmit();128: }129: else {130: return true;131: }132: }133: //]]>134: </script>135: </form>136: </body>137: </html>
Como vemos son 137 líneas de código y en la parte final bastante código JavaScript.
Ahora vamos a habilitar la validación no intrusiva (recuerden en el Global.asax):
1: ValidationSettings.UnobtrusiveValidationMode = System.Web.UI.UnobtrusiveValidationMode.WebForms;
Y para solucionar el error simplemente adicionamos la librería jQuery, pero lo debemos hacer de nuevo en el Global.asax de la siguiente manera:
1: ScriptManager.ScriptResourceMapping.AddDefinition("jquery",2: new ScriptResourceDefinition3: {4: Path = "/Scripts/jquery-1.8.0.js"5: }6: );
En Path especificamos la ruta de la librería, y ahora si volvemos a lanzar la aplicación y a revisar el HTML generado tenemos:
1: <!DOCTYPE html>2:3: <html xmlns="http://www.w3.org/1999/xhtml">4: <head><title>5: Formulario6: </title></head>7: <body>8: <form method="post" action="index.aspx" onsubmit="javascript:return WebForm_OnSubmit();" id="form1">9: <div class="aspNetHidden">10: <input type="hidden" name="__EVENTTARGET" id="__EVENTTARGET" value="" />11: <input type="hidden" name="__EVENTARGUMENT" id="__EVENTARGUMENT" value="" />12: <input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="alparljtLhNy2xupYlZBZObSGVyvyxxogr8jThTTwWgWjbCJGZlWBvzpy1msUcxlr7zmHWThPw30eTwgrEBC9jxViHQKMQdl97MNwbdtIyg=" />13: </div>14:15: <script type="text/javascript">16: //<![CDATA[17: var theForm = document.forms['form1'];18: if (!theForm) {19: theForm = document.form1;20: }21: function __doPostBack(eventTarget, eventArgument) {22: if (!theForm.onsubmit || (theForm.onsubmit() != false)) {23: theForm.__EVENTTARGET.value = eventTarget;24: theForm.__EVENTARGUMENT.value = eventArgument;25: theForm.submit();26: }27: }28: //]]>29: </script>30:31:32: <script src="/WebResource.axd?d=pynGkmcFUV13He1Qd6_TZAlhwiK26CMjFC_AwUoa5b3ERCspA6cmt_C-L8IOpCe633BVnc0wcDgTvonIIsSvwQ2&t=634776373276709129" type="text/javascript"></script>33:34:35: <script src="/Scripts/jquery-1.8.0.js" type="text/javascript"></script>36: <script src="/WebResource.axd?d=x2nkrMJGXkMELz33nwnakEDhIJdn4zA9e1UqVq1SVvHhRhIprKEH70Wnr0YNmajC6LdVxQkRSvYza9nzCfZpzIEPGw7MYTdtpXpxdmoJjww1&t=634776373276709129" type="text/javascript"></script>37: <script type="text/javascript">38: //<![CDATA[39: function WebForm_OnSubmit() {40: if (typeof(ValidatorOnSubmit) == "function" && ValidatorOnSubmit() == false) return false;41: return true;42: }43: //]]>44: </script>45:46: <div class="aspNetHidden">47:48: <input type="hidden" name="__EVENTVALIDATION" id="__EVENTVALIDATION" value="+364tW9Dc7pDt6plQ90xe5FouuoNJLAEzbosO0J1tGmDKGpwQcxZ1kdqIV/tRvjZENOFLgzZM85V7T0z3t6I607wioiuB8cTrjZfCFSxHIPE/QbqekiEkZw9CeWGtKKGd2SzLZyMEXvyjxGP4xzOcHDDG0s00+EWD0Gay9W4uDXNzzVdNiwpoNp6dSj21Rvzuttb/+4L1dlkpikZJVdSig==" />49: </div>50: <div>51: <table>52: <tr>53: <td>Nombre:</td>54: <td>55: <input name="txtNombre" type="text" id="txtNombre" style="width:300px;" />56: <span data-val-controltovalidate="txtNombre" data-val-errormessage="*" id="requiredNombre" data-val="true" data-val-evaluationfunction="RequiredFieldValidatorEvaluateIsValid" data-val-initialvalue="" style="visibility:hidden;">*</span>57: </td>58: </tr>59: <tr>60: <td>Correo:</td>61: <td>62: <input name="txtCorreo" type="text" id="txtCorreo" style="width:300px;" />63: <span data-val-controltovalidate="txtCorreo" data-val-errormessage="*" id="requiredCorreo" data-val="true" data-val-evaluationfunction="RequiredFieldValidatorEvaluateIsValid" data-val-initialvalue="" style="visibility:hidden;">*</span>64: </td>65: </tr>66: <tr>67: <td>Usuario:</td>68: <td>69: <input name="txtUsuario" type="text" id="txtUsuario" style="width:300px;" />70: <span data-val-controltovalidate="txtUsuario" data-val-errormessage="*" id="requiredUsuario" data-val="true" data-val-evaluationfunction="RequiredFieldValidatorEvaluateIsValid" data-val-initialvalue="" style="visibility:hidden;">*</span>71: </td>72: </tr>73: <tr>74: <td>Clave:</td>75: <td>76: <input name="txtClave" type="password" id="txtClave" style="width:300px;" />77: <span data-val-controltovalidate="txtClave" data-val-errormessage="*" id="requiredClave" data-val="true" data-val-evaluationfunction="RequiredFieldValidatorEvaluateIsValid" data-val-initialvalue="" style="visibility:hidden;">*</span>78: </td>79: </tr>80: <tr>81: <td><input type="submit" name="btnGuardar" value="Guardar" onclick="javascript:WebForm_DoPostBackWithOptions(new WebForm_PostBackOptions("btnGuardar", "", true, "", "", false, false))" id="btnGuardar" /></td>82: </tr>83: </table>84: </div>85: </form>86: </body>87: </html>
Lo primero que observamos es que solo tenemos 87 líneas en contra de las 137 anteriores (bastantes menos no?), lo segundo es que ya no tenemos tanto código JavaScript y lo tercero es que aparecen nuevos atributos en los span, y esos atributos son los que ahora determinan las validaciones. Inicialmente el HTML de un span era:
1: <span id="requiredNombre" style="visibility:hidden;">*</span>
Y luego con la validación no intrusiva lista:
1: <span data-val-controltovalidate="txtNombre" data-val-errormessage="*" id="requiredNombre" data-val="true" data-val-evaluationfunction="RequiredFieldValidatorEvaluateIsValid" data-val-initialvalue="" style="visibility:hidden;">*</span>
Como se puede ver, se han generado nuevos atributos del tipo data-val-<…> los cuales determinan como se realizará la validación.
Espero les sea de utilidad este post, saludos!





[ASP.NET] Validaciones no intrusivas en ASP.NET 4.5 « MSExpertos escribió
[...] [ASP.NET] Validaciones no intrusivas en ASP.NET 4.5 [...]
Resumen Post 2012 « Todo en ASP.NET escribió
[...] [ASP.NET] Validaciones no intrusivas en ASP.NET 4.5 [...]