Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ASP.NET 4.5 TryUpdateModel not picking Form values in WebForm using Master-Page

I am using WebForms and I am trying to perform Model Validation inside a Master-Page and for some reason the model is not picking up the values, meaning that after the validation fires if I enter a good value, the model keeps coming back empty hence triggering the validation over and over. If I put the code in page without Master-Page it works fine. I was able to put a very simple example and honestly, it's hard to believe that as common as MasterPages are, nobody has ran into this scenario so far. For the purpose of this example I embedded the Model in the Code Behind but having outside makes no different. Any idea will be greatly welcome. Thanks.

--Master-Page--

<%@ Master Language="C#" AutoEventWireup="true" CodeFile="test.master.cs" Inherits="test" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
    <asp:ContentPlaceHolder id="head" runat="server">
    </asp:ContentPlaceHolder>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <asp:ContentPlaceHolder id="ContentPlaceHolder1" runat="server">

        </asp:ContentPlaceHolder>
    </div>
    </form>
</body>
</html>

-- WebForm --

<%@ Page Title="" Language="C#" MasterPageFile="~/test.master" AutoEventWireup="true" CodeFile="test3.aspx.cs" Inherits="test3" %>

<asp:Content ID="Content1" ContentPlaceHolderID="head" Runat="Server">
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="ContentPlaceHolder1" Runat="Server">
    <div>
        <asp:ValidationSummary ID="valSummary" runat="server" />
    </div>
        <div><label>First Name:</label></div>
        <div><input type="text" id="FirstName" runat="server" /></div>
        <div><label>Middle Name:</label></div>
        <div><input type="text" id="MiddleName" runat="server" /></div>
        <div><label>Last Name:</label></div>
        <div><input type="text" id="LastName" runat="server" /></div>
    <div>
        <asp:Button ID="btnSubmit" runat="server"  Text="Submit" />
    </div>
</asp:Content>

-- Code Behind --

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.ModelBinding;
using System.ComponentModel.DataAnnotations;


public partial class test3 : System.Web.UI.Page
{
    public class testClass2
    {
        [Required()]
        [MinLength(2)]
        public string FirstName { get; set; }

        public string MiddleName { get; set; }

        [Required()]
        [MinLength(2)]
        public string LastName { get; set; }
    }

    protected void Page_Load(object sender, EventArgs e)
    {

        if (Page.IsPostBack)
        {
            testClass2 tc = new testClass2();
            if (TryUpdateModel(tc, new FormValueProvider(ModelBindingExecutionContext)))
            {
                System.Diagnostics.Debug.WriteLine("test");
            }
        }
    }
}
like image 830
user3679573 Avatar asked Jun 06 '14 13:06

user3679573


2 Answers

The problem is indeed caused by usage of the master page. When used outside of the data bound control (such as GridView, FormView, Menu, etc.), FormValueProvider expects to have the same keys in Request.Form dictionary as property names in model object.

If you will take a closer look at generated HTML you will see that all input tags in form with master page have name attribute value set to something like ctl00$ContentPlaceHolder1$FirstName, ctl00$ContentPlaceHolder1$LastName, etc. while form without master page leaves name attribute intact and equal to the value of control's ID property.

This is the way of how UniqueID is generated to avoid name duplication (which should be avoided because in Web Forms we can have only one form tag and thus have controls with same ID's both on master page and form page).

And this is the cause why FormValueProvider cannot get values for your testClass2 object, it just cannot find FirstName, LastName, MiddleName values in posted form.

like image 79
Alexander Manekovskiy Avatar answered Nov 17 '22 07:11

Alexander Manekovskiy


I found a solution.You can write a little front-end code to set the name equal to id and don't forget to set ClientIDMode to Static

<script>
    $("input[type=text]").each(function () {
         var id = $(this).attr("id");
         $(this).attr("name", id);
    });
</script>
like image 34
Jason Yang Avatar answered Nov 17 '22 05:11

Jason Yang