ASP.NET mvc RenderAction 登录并注册视图

ASP.NET mvc RenderAction Login And Register Views

我正在开发 NopCommerce v3.80。默认情况下,登录和注册视图是不同的。我需要在不更改太多代码的情况下合并它们,所以我在 Login.cshtml.

中调用了 @{ RenderAction("Register"); }

我还从注册视图中删除了布局 (Layout = "~/Views/Shared/_ColumnsOne.cshtml";)。

问题是当像 'Email Id already Exists!' 这样的验证错误出现时,它会转到注册视图。我需要在登录视图上显示验证或错误消息。但登录视图仅接受登录模型。

请看我的代码:

Register.cshtml

@model RegisterModel 
@using Nop.Web.Models.Customer;
@{
    //Layout = "~/Views/Shared/_ColumnsOne.cshtml";
}

<!-- Registeration fields  -->

Login.cshtml

@model LoginModel
@using Nop.Web.Models.Customer;
@{
    Layout = "~/Views/Shared/_ColumnsOneTT.cshtml";
}

@using (Html.BeginForm("Register", "Customer", FormMethod.Post)){
<div>  
@{ 
    Html.RenderAction("Register");
 }
<input type="submit" value="Submit"/>
}

CustomerController.cs - 注册方法

public ActionResult Register(RegisterModel model){
    // Lot of code
    if (success){
    // lot of code
       return RedirectToRoute("RegisterResult");
    }
    foreach (var error in registrationResult.Errors)
       ModelState.AddModelError("", error);
    PrepareCustomerRegisterModel(model, true, customerAttributesXml);
    return View(model);

}

更新: 我检查了 how to work with two forms in a single view 但它对我没有帮助,因为我不能使用新模型创建选项。

更新 2: 我也尝试了新的模型创建选项,它涵盖了登录和注册模型,但我仍然得到相同的结果。

如果没有比您已经完成的更重要的代码更改,您尝试做的事情实际上是不可行的,因为验证的范围仅限于您正在处理的特定模型。

可能是我能想到的最简单有效的解决方案,就是将登录视图的模型更改为其他两个模型的包装器。

public class AuthenticationModel {
    public LoginModel Login {get;set;} 
    public RegisterModel Register {get;set;}
    public AuthenticationModel (LoginModel lModel, RegisterModel rModel) {
        Login = lModel;
        Register = rModel;
    }
}

这应该可以解决您遇到的大部分问题,但验证消息必须正确针对您的结构:

ModelState.AddModelError("", error);

在您的代码中替换为:

ModelState.AddModelError("Register", error);

除了将模型组合到视图模型中以使用包含两个模型(就像您在这种情况下可能应该做的那样)之外,一个便宜且简单的选择是检测错误并将其作为 viewbag 传回 属性。然后在前端,您可以检查 属性 是否不为空,如果为空则显示一条错误消息。

不过你应该创建一个视图模型,其他一切都只是一个创可贴的解决方法。

您可以将登录和注册模型合并到一个全新的模型中,这样验证就可以针对所需的模型。

感谢大家 efforts.I 必须创建新模型并将注册和登录这两个模型包装在其中。

看起来 how to work with two forms in a single view 对我帮助很大。

但是,我正在为新手发布完整的解决方案。

客户控制器:

正在加载页面

public ActionResult Login(bool? checkoutAsGuest)
        {
            var loginModel= new LoginModel();
            loginModel.UsernamesEnabled = _customerSettings.UsernamesEnabled;
            loginModel.CheckoutAsGuest = checkoutAsGuest.GetValueOrDefault();
            loginModel.DisplayCaptcha = _captchaSettings.Enabled && _captchaSettings.ShowOnLoginPage;

            var registerModel = new RegisterModel();
            PrepareCustomerRegisterModel(registerModel, false);
            registerModel.Newsletter = _customerSettings.NewsletterTickedByDefault;

            return View(new LoginRegisterModel { LoginModel = , RegisterModel = registerModel });
        }

登录POST:

public ActionResult Login(LoginModel model, string returnUrl, bool captchaValid)
        {
        // Previous code as it is
        // Important! I Added this new line - to handle validation problems
        ModelState.Add("LoginValidation", null);
        //If we got this far, something failed, redisplay form
        model.UsernamesEnabled = _customerSettings.UsernamesEnabled;
        model.DisplayCaptcha = _captchaSettings.Enabled && _captchaSettings.ShowOnLoginPage;

        var registerModel = new RegisterModel();
        PrepareCustomerRegisterModel(registerModel, false);
        //enable newsletter by default
        registerModel.Newsletter = _customerSettings.NewsletterTickedByDefault;

        return View(new LoginRegisterModel { LoginModel = model, RegisterModel = registerModel });
    } 

注册:

public ActionResult Register()
        {
            //check whether registration is allowed
            if (_customerSettings.UserRegistrationType == UserRegistrationType.Disabled)
                return RedirectToRoute("RegisterResult", new { resultId = (int)UserRegistrationType.Disabled });

            var model = new RegisterModel();
            PrepareCustomerRegisterModel(model, false);
            model.Newsletter = _customerSettings.NewsletterTickedByDefault;

            var loginModel = new LoginModel();
            loginModel.UsernamesEnabled = _customerSettings.UsernamesEnabled;
            loginModel.DisplayCaptcha = _captchaSettings.Enabled && _captchaSettings.ShowOnLoginPage;

            return View("Login", new LoginRegisterModel { RegisterModel = model, LoginModel = loginModel });

        }

报名POST:

public ActionResult Register(RegisterModel model, string returnUrl, bool captchaValid, FormCollection form)
        {
            // previous code as it is
            // added this line to handle validations

            ModelState.Add("RegisterValidation", null);
            //If we got this far, something failed, redisplay form
            PrepareCustomerRegisterModel(model, true, customerAttributesXml);

            var loginModel = new LoginModel();
            loginModel.UsernamesEnabled = _customerSettings.UsernamesEnabled;
            //loginModel.CheckoutAsGuest = checkoutAsGuest.GetValueOrDefault();
            loginModel.DisplayCaptcha = _captchaSettings.Enabled && _captchaSettings.ShowOnLoginPage;

            return View("Login", new LoginRegisterModel { RegisterModel = model, LoginModel = loginModel });
        }

然后创建了两个部分视图 - _LoginModel.cshtml_registerModel.cshtml。在视图中我只添加了一行

_LoginModel.cshtml:

if (!MvcHtmlString.IsNullOrEmpty(validationSummary) && ViewData.ModelState.ContainsKey("LoginValidation"))
    {
        <div class="message-error">@validationSummary</div>
    }

_RegisterModel.cshtml

@if (!MvcHtmlString.IsNullOrEmpty(validationSummary) && ViewData.ModelState.ContainsKey("RegisterValidation"))
    {
        <div class="message-error">@validationSummary</div>
    }

最后,登录页面

Login.cshtml

替换了注册按钮(左面板带有 )

@using (Html.BeginForm("Register", "Customer", FormMethod.Post)){
<!-- divs and other elements -->
    @Html.Partial("_RegisterModel", Model.RegisterModel)
<!-- divs and other elements -->
}

和登录表单

 @using (Html.BeginForm("Login", "Customer", new { returnUrl = Request.QueryString["returnUrl"] }, FormMethod.Post))
                       {
                        <!-- divs and other elements -->
                        @Html.Partial("_LoginModel", Model.LoginModel)
<!-- divs and other elements -->
                       }