简体   繁体   English

MVC 5-当对象是页面视图模型的属性时,如何将对象映射到Action?

[英]MVC 5 - How can I map an object to an Action when that object is a property of the view model for the page?

I have a login view model defined as such. 我有这样定义的登录视图模型

public class LoginViewModel
{
    [Required]
    public String Username { get; set; }

    [Required]
    [DataType(DataType.Password)]
    public String Password { get; set; }


    /// <summary>
    /// The default constructor.
    /// </summary>
    public LoginViewModel()
    {

    }
}

And my master page takes a base view model defined as: 我的母版页采用定义为的基本视图模型

public abstract class CommonViewModel
{
    #region Properties
    public LoginViewModel LoginModel { get; set; }                
    #endregion

    #region Functions

    /// <summary>
    /// The default constructor.
    /// </summary>
    public CommonViewModel()
    {

    }

    #endregion
}

In master layout I have a login form . 主布局中,我有一个登录表单 This form is laid out as such. 这种形式是这样布置的。

<form id="login-form" method="post" action="@Url.Action("Login", "Account")">
    <div class="form-element">                            
        @Html.LabelFor(m => m.LoginModel.Username, Resources.MasterPageStrings.LoginUsername, new { @class = "login-form-label" })                            
        @Html.TextBoxFor(m => m.LoginModel.Username, new
        {
            @class = "login-form-input login-form-input-common required",
            @autofocus = String.Empty,
            @placeholder = Resources.MasterPageStrings.LoginUsername
        })
    </div>
    <div class="form-element">
        @Html.LabelFor(m => m.LoginModel.Password, Resources.MasterPageStrings.LoginPassword, new { @class = "login-form-label" })
        @Html.TextBoxFor(m => m.LoginModel.Password, new
        {
            @class = "login-form-input login-form-input-common required",
            @placeholder = Resources.MasterPageStrings.LoginPassword,
            @type = "password"
        })
    </div>
    <div class="form-element">
        @Html.LabelFor(m => m.LoginModel.RememberMe, Resources.MasterPageStrings.LoginRememberMe, new { @class = "login-form-label" })
        @Html.CheckBoxFor(m => m.LoginModel.RememberMe, new
        {
            @class = "login-form-input login-form-input-common",
            @placeholder = Resources.MasterPageStrings.LoginRememberMe
        })
    </div>
    <div class="form-element">
        <input type="submit" class="login-form-submit login-form-input-common" value="@Resources.MasterPageStrings.LoginLoginLabel">
    </div>
</form>

When I submit to the account controller, I don't have the login view model mapped. 当我提交给帐户控制器时,我没有映射登录视图模型。

/// <summary>
/// Logs the user into the application.
/// </summary>
/// <param name="model">The login view model uses to login.</param>        
/// <returns>The view you were trying to get to.</returns>
[HttpPost]
[AllowAnonymous]
[Route("Login")]
public async Task<ActionResult> Login(Models.ViewModels.Common.LoginViewModel model)
{

}

The view model is always the default empty values of null for username and password. 视图模型始终是用户名和密码的默认空值null。 How can I get the login model to map in the account controller login action? 如何获取登录模型以映射到帐户控制器登录操作中?

I can't map to the common view model as I get an error that I can't instantiate an abstract class. 由于出现无法实例化抽象类的错误,因此无法映射到通用视图模型。

the reason why you are receiving null is because you are sending the data based on the model of the view which is CommonViewModel , if you take a property 收到null的原因是,如果您采用的是属性,则基于基于CommonViewModel模型的CommonViewModel发送数据

@Html.TextBoxFor(m => m.LoginModel.Password, new
                            {
                                @class = "login-form-input login-form-input-common required",
                                @placeholder = Resources.MasterPageStrings.LoginPassword,
                                @type = "password"
                            })

and if you see the rendered html the name will be LoginModel.Password but in the action you are trying to get LoginViewModel which has no property LoginModel.Password 并且如果您看到rendered html则名称将为LoginModel.Password但是在操作中,您尝试获取没有属性LoginModel.Password LoginViewModel

so your action should be 所以你的动作应该是

[HttpPost]
[AllowAnonymous]
[Route("Login")]
public async Task<ActionResult> Login(CommonViewModel model)
{
 var loginmodel= model.LoginModel; //here you can access the properties like loginmodel.Password
}

Update 更新资料

another solution is to name the Html Helpers same as the name of properties of LoginViewModel so your view will be 另一个解决方案是将Html Helpers的名称与LoginViewModelproperties名称相同,这样您的视图将

<form id="login-form" method="post" action="@Url.Action("Login", "Account")">
    <div class="form-element">                            
        @Html.Label("Username", Resources.MasterPageStrings.LoginUsername, new { @class = "login-form-label" })                            
        @Html.TextBox("Username", new
        {
            @class = "login-form-input login-form-input-common required",
            @autofocus = String.Empty,
            @placeholder = Resources.MasterPageStrings.LoginUsername
        })
    </div>
    <div class="form-element">
        @Html.Label("Password", Resources.MasterPageStrings.LoginPassword, new { @class = "login-form-label" })
        @Html.TextBox("Password", new
        {
            @class = "login-form-input login-form-input-common required",
            @placeholder = Resources.MasterPageStrings.LoginPassword,
            @type = "password"
        })
    </div>
    <div class="form-element">
        @Html.Label("RememberMe", Resources.MasterPageStrings.LoginRememberMe, new { @class = "login-form-label" })
        @Html.CheckBox("RememberMe", new
        {
            @class = "login-form-input login-form-input-common",
            @placeholder = Resources.MasterPageStrings.LoginRememberMe
        })
    </div>
    <div class="form-element">
        <input type="submit" class="login-form-submit login-form-input-common" value="@Resources.MasterPageStrings.LoginLoginLabel">
    </div>
</form>

and your action will be 你的动作将是

[HttpPost]
[AllowAnonymous]
[Route("Login")]
public async Task<ActionResult> Login(Models.ViewModels.Common.LoginViewModel model)
{

}

Try to change your Login action so that it takes a CommonViewModel instead of a LoginViewModel. 尝试更改您的Login操作,以使其使用CommonViewModel而不是LoginViewModel。

Or better pratice, separate the code for the view into a partial view, set model of that view to LoginViewModel and render the partial like this : 或者更好的做法是,将视图的代码分成部分视图,将该视图的模型设置为LoginViewModel,然后像这样呈现部分视图:

@Html.RenderPartial("_LoginView", Model.LoginModel )

(assuming that the model type on your base view is CommonViewModel) (假设基本视图上的模型类型为CommonViewModel)

Partial View was made for this kind of situation. 针对这种情况进行了部分查看。 Create a partial view and paste your login HTML. 创建局部视图并粘贴您的登录HTML。 Keep the model of partial view as LoginViewModel and render it in the master page. 将部分视图的模型保留为LoginViewModel并将其呈现在母版页中。 That's it! 而已!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM