在 ASP.Net MVC 中的同一视图中分离两个表单

Posted

技术标签:

【中文标题】在 ASP.Net MVC 中的同一视图中分离两个表单【英文标题】:Separating two forms in the same view in ASP.Net MVC 【发布时间】:2009-06-04 20:15:19 【问题描述】:

我已将创建帐户视图和登录视图合并到同一个视图中。所以这是一个有两个表单的视图,但是当我提交时它们会混合在一起。如果我尝试登录并显示错误:

html.ValidationSummary()

两种形式都会出错。我开始将字段重命名为loginPassword,createPassword,因为否则当我提交并且密码丢失时,它会在两边都标记为丢失。

将这两种形式分开以便它们可以在同一个视图/页面上独立工作的方法是什么?

【问题讨论】:

【参考方案1】:

啊,是的,我以前必须这样做。我发现的方法是在 ViewData 中设置一个标志,详细说明发布了哪个表单,然后我为 ValidationSummary 创建了自己的扩展方法。

代码现在不在我身边,所以我现在会尽力为它做一些空气代码,这显然只是一个如何做的概念,所以从表面上看。

首先,我会使用与 tvanfosson 建议的“EntryPageModel”相同的设置。

查看 - 注意 Html.MyValidationSummary

<% using(Html.BeginForm("NewAccount", "Account")) %>
<%  %>
    <%= Html.MyValidationSummary("NewAccountForm") %>

    <%= Html.TextBox("NewAccount.FirstName") %>
    <%= Html.TextBox("NewAccount.LastName") %>
    <%= Html.TextBox("NewAccount.Email") %>
    <%= Html.Password("NewAccount.Password") %>
    <%= Html.Password("NewAccount.ConfirmPassword") %>
<%  %>

<% using(Html.BeginForm("Login", "Account")) %>
<%  %>
    <%= Html.MyValidationSummary("LoginForm") %>

    <%= Html.TextBox("Login.Email") %>
    <%= Html.Password("Login.Password") %>
<%  %>

控制器 - 注意 ViewData["PostedForm"]

public class Account : Controller

    private EntryPageModel _viewModel;

    public ActionResult NewAccount(FormCollection formValues)
    
        try
        
            //binding and validation for _viewModel.NewAccount
        
        catch
        
            ViewData["PostedForm"] = "NewAccountForm";
            return View("RegisterAndLogin", _viewModel);
        
    

    public ActionResult Login(FormCollection formValues)
    
        try
        
            //binding and validation for _viewModel.Login
        
        catch
        
            ViewData["PostedForm"] = "LoginForm";
            return View("RegisterAndLogin", _viewModel); //You'll want to pass in a model
        
    

自定义html扩展

namespace System.Web.Mvc

    public static class HtmlExtensions
    
        public static string MyValidationSummary(this HtmlHelper html, string formName)
        
            if (!string.IsNullOrEmpty(html.ViewData["PostedForm"])
                && (html.ViewData["PostedForm"] == formName))
            
                return html.ValidationSummary();
            

            return "";
        
    

HTH, 查尔斯

【讨论】:

这就是应该在 ValidationSummary() 中伪造的...如果只有一种方法可以检测在哪个视图中调用操作,则调用 ValidationSummary() 则它可以在没有显式的情况下工作行动论据!【参考方案2】:

我不得不处理同样的问题。我发现没有办法使用内置的 ValidationSummary() 来分隔验证消息。这里有两个建议:

    将验证摘要放置在可以同时应用于两种表单的区域。例如,如果登录和注册表单并排放置,则将验证摘要放置在两个表单上方居中的 div 中。我在Mahalo login page 上找到了这种风格的示例。 在适当的控制器操作方法中,向 ViewData 添加一些内容,指示调用了哪个操作。在视图中,每个表单都有一个 ValidationSummary,但每个表单都将根据您添加到 ViewData 的内容有条件地呈现。

无论哪种方式,表单字段都应该被唯一命名。

我选择了解决方案 #1,因为我对能够让它看起来的方式感到满意。但是,如果您需要根据提交的表单将验证摘要显示在两个不同的位置,请使用 #2。

【讨论】:

【参考方案3】:

输入元素确实需要不同的名称/ID,即使它们采用不同的形式。除非它们具有不同的名称,否则它将触发每个控件的验证逻辑,因为它基于控件的名称进行匹配。我认为您通过更改名称来区分它们是正确的。

我会用一个复合模型来设置它,也许这样你就可以做类似的事情(注意这是不完整的):

<%= Html.TextBox( "Login.Name" ) %>
<%= Html.TextBox( "Login.Password" ) %>


<%= Html.TextBox( "NewAccount.Name" ) %>
<%= Html.TextBox( "NewAccount.Password" ) %>
<%= Html.TextBox( "NewAccount.ConfirmPassword" ) %>

在服务器端,使用 binder 的前缀选项

public ActionResult Login( [Bind(Prefix="Login")]AccountModel model )

    ...

你的模型看起来像:

public class AccountModel

      public string Name  get; set; 
      public string Password  get; set; 
      public string ConfirmPassword  get; set; 


public class EntryPageModel

     public AccountModel Login  get; set; 
     public AccountModel NewAccount  get; set; 

【讨论】:

哦!对。我会留下不同的 id 和名称,但 ValidationSummary 会以两种形式捕获所有内容。 ...而且我认为您每页只需要一个验证摘要。我认为它旨在作为模型状态字典中所有错误的总结。 感谢您的代码。我需要在登录表单和创建帐户表单中的创建帐户操作中显示登录操作的验证错误。显示错误两次或远离表单对用户来说不是很友好。 哦,我真的没有模型,它只是动作方法中的表单和参数。这就是模板生成它的方式。我应该创建模型吗?【参考方案4】:

如果表单发布到完全不同的操作,那么您的 ModelStateDictionary 应该只包含被调用的操作提供的错误。

能贴出相关代码吗?

【讨论】:

但是 Html.ValidationSummary() 选择所有错误,任何形式。 关于代码,你可以只看一个新创建的项目的登录和创建帐户操作。现在我有一个 logInOrCreateAccount() 方法,它显示了一个具有两种形式的视图,一个指向 logIn() 另一个指向 createAccount()。 哦,我明白了。是的,验证摘要不是特定于表单的。你可以把它放在页面顶部的中心位置,或者完全省略它。自己写一个带前缀的也不难。【参考方案5】:

我不确定是否有办法拆分 ValidationSummary()。

对于您的表单,您可以使用各种字段创建要绑定的模型类。不过,它不会比你已经拥有的更多。

【讨论】:

我对改名没意见,它很干净,但没关系。这是我现在无法解决的 ValidationSummary。

以上是关于在 ASP.Net MVC 中的同一视图中分离两个表单的主要内容,如果未能解决你的问题,请参考以下文章

如何在 ASP.NET Core MVC 的同一视图中添加/创建多个一对多关系

如何在 ASP.NET MVC 4 中的两个完全不同的视图之间保留数据?

ASP.NET MVC 5 如何在同一视图中编辑 Parent 和 List<> 类型 Child

ASP.NET MVC 3 CMS 支持多租户?

ASP.NET中MVC的理解

iframe 在 MVC 视图中加载 asp.net web 表单