C# Asp.NET MVC 模型绑定 - 使用绑定参数属性为简单类型分配前缀

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/592508/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-04 09:32:12  来源:igfitidea点击:

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

c#.netasp.netasp.net-mvcmodel-binding

提问by Jeremy

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.

我有一个 .net mvc 应用程序,它带有一个接受用户注册帖子的控制器操作。我有以下 UI 字段:电子邮件地址、名字、姓氏、密码和确认密码。其中一些字段不属于模型对象(即确认密码不属于用户模型,只有密码)。我的注册表单与登录表单位于同一视图中。所以我必须在同一个视图上独立的表单,每个回发不同的动作。

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.

我想我可以为表单元素分配前缀来分隔注册和登录之间的类似字段。我遇到的问题是验证,如果发生错误,视图会重新加载,显示验证消息,但电子邮件(存在于登录和注册中)等字段都将填充先前输入的地址。此外,我在登录和注册字段上方都有一个验证摘要。当注册期间发生错误时,两个验证摘要都填充了错误消息。我认为为字段(register.fieldname 和 login.fieldname)分配前缀可能有助于解决这些问题。

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...

因此,当 register 操作处理帖子时,它不再查找注册表单字段的值,而是返回 null。以下是用于此操作的方法签名...

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....

以下是我的ui,它代表注册表....

<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>

回答by user31934

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.

我认为为了使用带有前缀的 [Bind],您需要使用复杂类型。您将相同的前缀与每个参数相关联,这与 MVC 框架的做法不同。

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) {
...
}

回答by Tom Lint

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.

似乎对于像 int 和 string 这样的简单类型,绑定前缀会覆盖参数的模型名称。以您的操作方法为例, DefaultModelBinder 将为所有参数查找名称“Register”。

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.

为了解决这个问题并且不需要复杂类型,您需要指定完全限定名称,因为 Mvc 会将其呈现到 HTML 标记中。

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)