Asp.NET MVC Model Binding - Using Bind Parameter Attribute to assign a prefix for a simple type

11,833

Solution 1

I think in order to use [Bind] with a prefix, you need to use a complex type. You are associating the same prefix with each parameter, which doesn't work with the way that the MVC framework does it.

You can create a type to handle the form post:

public class RegistrationForm {
 string EmailAddress {get;set;}
 string FirstName {get;set;}
 string LastName {get;set;}
 string Password {get;set;} 
 string ConfirmPassword {get;set;}
}

Then you can change your signature to:

public ActionResult Register(RegistrationForm register) {
...
}

Solution 2

It seems that for simple types like int and string, the Bind Prefix overrides the model name for the parameters. Using your action method as an example, the DefaultModelBinder would be looking for the name "Register" for all parameters.

In order to work around this and not require a complex type, you need to specify the fully qualified name as Mvc would render it into the HTML markup.

Applying this to your action method, it should look like this:

public ActionResult Register([Bind(Prefix = "Register.EmailAddress")] string emailAddress, [Bind(Prefix = "Register.FirstName")] string firstName, [Bind(Prefix = "Register.LastName")] string LastName, [Bind(Prefix = "Register.Password")] string password, [Bind(Prefix = "Register.onfirmPassword")] string confirmPassword)
Share:
11,833
Jeremy
Author by

Jeremy

Updated on August 21, 2022

Comments

  • Jeremy
    Jeremy over 1 year

    I have a .net mvc app with an controller action which accepts user registration posts. I have the following UI fields: emailaddress, firstname, lastname, password, and confirmpassword. Some of these fields do not belong to a model object (i.e. confirm password does not belong to the user model, only password). My registration form resides on the same view as the login form. So I have to independent forms on the same view, each posting back to different actions.

    I figured i could assign prefixes to the form elements to separate the like fields between register and login. The problem i had was on validation, if an error occurred, the view was re-loaded, a validation message was shown but fields like email (which exist in login and register) would both be populated with the previously entered address. In addition, i had a validation summary above both login and register fields. When an error occurred during registration, both validation summaries were populated with the error messages. I figured assigning prefixes to the fields (register.fieldname and login.fieldname) might help these problems.

    So when the register action handles the post it no longer finds values for the registration form fields and instead returns null. The following is the method signature used for this action...

    Any input as to what's going on here would be great.

    Thanks Jeremy

     public ActionResult Register([Bind(Prefix = "Register")] string emailAddress, [Bind(Prefix = "Register")] string firstName, [Bind(Prefix = "Register")] string LastName, [Bind(Prefix = "Register")] string password, [Bind(Prefix = "Register")] string confirmPassword)
    

    and the following is from my ui, it represents the registration form....

    <h2>Create a New Account</h2>
      <p>
          Use the form below to create a new account. 
      </p>
      <p>
          Passwords are required to be a minimum of <%=Html.Encode(ViewData["PasswordLength"])%> characters in length.
      </p>
      <%= Html.ValidationSummary() %>
    
      <% using (Html.BeginForm("register", "account")) { %>
        <div>
          <fieldset>
            <legend>Account Information</legend>
    
            <table>
              <tr>
                <td><label for="EmailAddress">Email Address:</label></td>
                <td>
                  <%= Html.TextBox("Register.EmailAddress") %>
                  <%= Html.ValidationMessage("Register.EmailAddress")%>
                </td>
              </tr>
              <tr>
                <td><label for="FirstName">First Name</label></td>
                <td>
                  <%= Html.TextBox("Register.FirstName")%>
                  <%= Html.ValidationMessage("Register.FirstName")%>
                </td>
              </tr>   
              <tr>
                <td><label for="LastName">Last Name</label></td>
                <td>
                  <%= Html.TextBox("Register.LastName")%>
                  <%= Html.ValidationMessage("Register.LastName")%>
                </td>
              </tr>           
              <tr>
                <td><label for="password">Password:</label></td>
                <td>
                  <%= Html.Password("Register.password")%>
                  <%= Html.ValidationMessage("Register.password")%>
                </td>
              </tr>
              <tr>
                <td><label for="confirmPassword">Confirm password:</label></td>
                <td>
                  <%= Html.Password("Register.confirmPassword")%>
                  <%= Html.ValidationMessage("Register.confirmPassword")%>
                </td>
              </tr>
              <tr>
                <td colspan="2" class="alignright">
                  <input type="submit" value="Register" />
                </td>
              </tr>
            </table>
          </fieldset>
        </div>
      <% } %>
    </div>
    
  • Tom Lint
    Tom Lint almost 8 years
    That kind of sucks. Why would I have to bind to a complex type if all I need is, say, 3 properties? Seems like a terrible shortcoming.