使用ViewModel在一个页面上使用不同的模型绑定两个表单

时间:2014-02-15 17:03:17

标签: c# asp.net-mvc html5 razor

好的,我正在尝试使用ViewModel在一个页面上显示两个表单(绑定到两个不同的模型)。

有问题的表格是登录和注册。我目前正在研究默认的MVC5模板,直到我做对了。

所以我有一个ViewModel:

public sealed class LoginRegisterViewModel
{
    public LoginViewModel LoginViewModel { get; set; }
    public RegisterViewModel RegisterViewModel { get; set; }
}

页面的HTML / Razor代码如下所示,它是Login / Register页面中表单的复制/粘贴,Linq已更改为访问ViewModel中每个内容的属性:

@Model LoginRegisterViewModel
<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>Index</title>
</head>
<body>
    <div class="row">
        <div class="col-md-8">
            <section id="loginForm">
                @using (Html.BeginForm("Login", "Account", new { ReturnUrl = ViewBag.ReturnUrl }, FormMethod.Post, new { @class = "form-horizontal", role = "form" }))
                {
                    @Html.AntiForgeryToken()
                    <h4>Use a local account to log in.</h4>
                    <hr />
                    @Html.ValidationSummary(true)
                    <div class="form-group">
                        @Html.LabelFor(m => m.LoginViewModel.UserName, new { @class = "col-md-2 control-label" })
                        <div class="col-md-10">
                            @Html.TextBoxFor(m => m.LoginViewModel.UserName, new { @class = "form-control" })
                            @Html.ValidationMessageFor(m => m.LoginViewModel.UserName)
                        </div>
                    </div>
                    <div class="form-group">
                        @Html.LabelFor(m => m.LoginViewModel.Password, new { @class = "col-md-2 control-label" })
                        <div class="col-md-10">
                            @Html.PasswordFor(m => m.LoginViewModel.Password, new { @class = "form-control" })
                            @Html.ValidationMessageFor(m => m.LoginViewModel.Password)
                        </div>
                    </div>
                    <div class="form-group">
                        <div class="col-md-offset-2 col-md-10">
                            <div class="checkbox">
                                @Html.CheckBoxFor(m => m.LoginViewModel.RememberMe)
                                @Html.LabelFor(m => m.LoginViewModel.RememberMe)
                            </div>
                        </div>
                    </div>
                    <div class="form-group">
                        <div class="col-md-offset-2 col-md-10">
                            <input type="submit" value="Log in" class="btn btn-default" />
                        </div>
                    </div>
                    <p>
                        @Html.ActionLink("Register", "Register") if you don't have a local account.
                    </p>
                }
            </section>
        </div>
        <div class="col-md-4">
            <section id="socialLoginForm">
                @Html.Partial("_ExternalLoginsListPartial", new { Action = "ExternalLogin", ReturnUrl = ViewBag.ReturnUrl })
            </section>
        </div>
    </div>
    <div class="row">
        @using (Html.BeginForm("Register", "Account", FormMethod.Post, new { @class = "form-horizontal", role = "form" }))
        {
            @Html.AntiForgeryToken()
            <h4>Create a new account.</h4>
            <hr />
            @Html.ValidationSummary()
            <div class="form-group">
                @Html.LabelFor(m => m.RegisterViewModel.UserName, new { @class = "col-md-2 control-label" })
                <div class="col-md-10">
                    @Html.TextBoxFor(m => m.RegisterViewModel.UserName, new { @class = "form-control" })
                </div>
            </div>
            <div class="form-group">
                @Html.LabelFor(m => m.RegisterViewModel.Password, new { @class = "col-md-2 control-label" })
                <div class="col-md-10">
                    @Html.PasswordFor(m => m.RegisterViewModel.Password, new { @class = "form-control" })
                </div>
            </div>
            <div class="form-group">
                @Html.LabelFor(m => m.RegisterViewModel.ConfirmPassword, new { @class = "col-md-2 control-label" })
                <div class="col-md-10">
                    @Html.PasswordFor(m => m.RegisterViewModel.ConfirmPassword, new { @class = "form-control" })
                </div>
            </div>
            <div class="form-group">
                <div class="col-md-offset-2 col-md-10">
                    <input type="submit" class="btn btn-default" value="Register" />
                </div>
            </div>
        }
        @Html.Partial("_RegisterPartial")
    </div>
</body>
</html>

@section Scripts {
    @Scripts.Render("~/bundles/jqueryval")
}

我更新了我的帐户ViewModel,总是指向我的Index方法,并根据需要传入各种ViewModel:

public ActionResult Index(LoginRegisterViewModel loginRegisterViewModel = null)
{
    if (loginRegisterViewModel == null)
    {
        loginRegisterViewModel = new LoginRegisterViewModel()
        {
            LoginViewModel = new LoginViewModel(),
            RegisterViewModel = new RegisterViewModel()
        };
    }

    return View(loginRegisterViewModel);
}

//
// GET: /Account/Login
[AllowAnonymous]
public ActionResult Login(string returnUrl)
{
    ViewBag.ReturnUrl = returnUrl;
    return RedirectToAction("Index");
}

//
// POST: /Account/Login
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Login(LoginViewModel model, string returnUrl)
{
    if (ModelState.IsValid)
    {
        var user = await UserManager.FindAsync(model.UserName, model.Password);
        if (user != null)
        {
            await SignInAsync(user, model.RememberMe);
            return RedirectToLocal(returnUrl);
        }
        else
        {
            ModelState.AddModelError("", "Invalid username or password.");
        }
    }

    // If we got this far, something failed, redisplay form
    return RedirectToAction("Index", new LoginRegisterViewModel
    {
        LoginViewModel = model, 
        RegisterViewModel = new RegisterViewModel()
    });
}

//
// GET: /Account/Register
[AllowAnonymous]
public ActionResult Register()
{
    return View();
}

//
// POST: /Account/Register
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Register(RegisterViewModel model)
{
    if (ModelState.IsValid)
    {
        var user = new ApplicationUser() { UserName = model.UserName };
        var result = await UserManager.CreateAsync(user, model.Password);
        if (result.Succeeded)
        {
            await SignInAsync(user, isPersistent: false);
            return RedirectToAction("Index", "Home");
        }
        else
        {
            AddErrors(result);
        }
    }

    // If we got this far, something failed, redisplay form
    return RedirectToAction("Index", new LoginRegisterViewModel
    {
        LoginViewModel = new LoginViewModel(),
        RegisterViewModel = model
    });
}

当我尝试访问该页面时,我收到以下错误:

  

CS1963:表达式树可能不包含动态操作

在这一行:

@Html.LabelFor(m => m.LoginViewModel.UserName, new { @class = "col-md-2 control-label" })

Visual Studio给出了零错误和零警告。

我无法弄清楚为什么,因为我觉得我已经做好了一切。有人可以帮助我吗?

1 个答案:

答案 0 :(得分:0)

当您尝试在动态对象上使用lambda表达式时,会出现此错误。这不是您指定视图模型类型的方式:

@Model LoginRegisterViewModel

你应该这样做:

@model LoginRegisterViewModel