使用多种表单时验证失败 [英] Validation failing when using multiple forms

查看:41
本文介绍了使用多种表单时验证失败的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用

当我在不输入凭据的情况下提交第一份表格时,验证失败.表单以GET的形式重新加载,URL为/home/signin ,并且不会显示预期的错误消息.

控制器的 ModelState 无效,但我无法弄清楚为什么这种状态没有传递回视图.

我做错了什么?如何获得可用于多种表单的验证?

这是我的代码:


控制器

 导入System.Threading.Tasks导入System.Web.Mvc导入Website.ViewModels.Home导入Microsoft.AspNet.Identity.Owin命名空间控制器部分公共类HomeController< AllowAnonymous>公共功能Index()作为ActionResultDim oViewModel作为SignInOrSignUpoViewModel =新SignInOrSignUp返回Me.View("Index",oViewModel)结束功能< HttpPost>< ValidateAntiForgeryToken>公共异步函数登录(作为登录模型)作为任务(作为动作结果)Dim oViewModel作为SignInOrSignUpDim eStatus作为SignInStatusDim oAction作为ActionResultoViewModel =带有{.SignIn = Model}的新SignInOrSignUp如果Me.ModelState.IsValid然后eStatus =等待我.SignInManager.PasswordSignInAsync(Model.Username,Model.Password,isPersistent:= False,shouldLockout:= False)如果eStatus = SignInStatus.Success然后oAction = Me.Redirect("www.domain.com")别的Me.ModelState.AddModelError(",无效的登录尝试".)oAction = Me.View("Index",oViewModel)万一别的oAction = Me.View("Index",oViewModel)万一返回oAction结束功能末级结束命名空间 

ViewModel

 导入System.ComponentModel.DataAnnotations命名空间ViewModels.Home公开课登录< Required(ErrorMessage:="需要用户名.")>< Display(Name:="用户名")>公共属性用户名作为字符串<必需>公共属性密码为字符串< Display(Name:=" Remember Me")>公共属性"RememberMe"为布尔型末级结束命名空间 

查看

  @ModelType ViewModels.Home.SignInOrSignUp@代码布局=什么都没有结束码<!DOCTYPE html>< html>< head><元字符集="utf-8";/><元名称=视口"内容=宽度=设备宽度,初始比例= 1.0."< title>网站</title>@ Scripts.Render(〜/scripts/bootstrap")@ Scripts.Render(〜/scripts/jquery")@ Styles.Render(〜/styles/bootstrap")@ Styles.Render(〜/styles/home")</head><身体>< div class ="row">< div class =包装器">< div class ="section">< h5>在此处登录</h5>< div class ="box">< div class =标题栏">登录</div>@使用(Html.BeginForm("signin","home",FormMethod.Post,{.id ="SignInForm"}新建的)))@ Html.AntiForgeryToken@ HTML.EditorFor(功能(M)模型.登录)@< div class ="button"><输入类型=提交";value =登录"Class ="button"/></div>@< div class ="anchor">< a href ="/">忘记密码了吗?</a></div>最终使用</div></div>< div class ="section">< h5>或在此处输入您的城市代码</h5>< div class ="box">< div class =标题栏">注册</div>@使用(Html.BeginForm("signup","home",FormMethod.Post,{.id ="SignUpForm"}}的新内容))@ Html.AntiForgeryToken@ HTML.EditorFor(功能(M)模型.SignUp)@< div class ="button"><输入类型=提交";value ="Continue"Class ="button"/></div>最终使用</div></div></div></div></body></html> 

-编辑-

在此期间,我已经能够通过笨拙的解决方法不受阻碍:

  @Code如果IsPost AndAlso Request.Path ="/home/signin",还有Model.SignIn.Username.Isthing然后@ Html.ValidationMessageFor(Function(Model)Model.SignIn.Username,需要用户名",新的{.class ="text-danger"})万一结束码 

但是我仍然想使用内置的验证机制,如果有可能在同一个视图中使用多种形式的话.

解决方案

您可以尝试以下两种方法:

1.在页面上放入验证摘要:

使用此选项,您无需更改控制器中的任何内容,但可以在页面上显示错误摘要.您将不会看到突出显示的字段,但仍然可以显示所有错误,例如:

 < body>< div class ="row">< div class =包装器">@ Html.ValidationSummary(false)...</div></div></body> 

这不是一个优雅的解决方案!

2.在控制器中,使用 SignInOrSignUp 作为输入,但从用户界面提供 SignIn SignUp 模型:

使用这种方法,您无需更改vbhtml/cshtml文件,因为在控制器方法上的参数类型只是您要更改的地方,它仍将保留:

 命名空间Controllers.Home部分公共类HomeController...< HttpPost>< ValidateAntiForgeryToken>公共异步函数SignIn(模型为SignInOrSignUp)作为Task(动作结果)...结束功能< HttpPost>公共异步函数注册(模型为SignInOrSignUp)作为任务(ActionResult的)...结束功能末级结束命名空间 

除非涉及到一些复杂的验证,否则此方法将像魅力一样发挥作用!

I'm using this construct to host multiple forms in the same view:

When I submit the first form without entering credentials, validation fails. The form reloads as a GET, with a URL of /home/signin, and the expected error messages don't display.

The controller's ModelState is invalid as expected, but I can't figure out why this state isn't passed back to the view.

What am I doing wrong? How can I get validation to work with multiple forms?

Here's my code:


Controller

Imports System.Threading.Tasks
Imports System.Web.Mvc
Imports Website.ViewModels.Home
Imports Microsoft.AspNet.Identity.Owin

Namespace Controllers.Home
  Partial Public Class HomeController
    <AllowAnonymous>
    Public Function Index() As ActionResult
      Dim oViewModel As SignInOrSignUp

      oViewModel = New SignInOrSignUp

      Return Me.View("Index", oViewModel)
    End Function

    <HttpPost>
    <ValidateAntiForgeryToken>
    Public Async Function SignIn(Model As SignIn) As Task(Of ActionResult)
      Dim oViewModel As SignInOrSignUp
      Dim eStatus As SignInStatus
      Dim oAction As ActionResult

      oViewModel = New SignInOrSignUp With {.SignIn = Model}

      If Me.ModelState.IsValid Then
        eStatus = Await Me.SignInManager.PasswordSignInAsync(Model.Username, Model.Password, isPersistent:=False, shouldLockout:=False)

        If eStatus = SignInStatus.Success Then
          oAction = Me.Redirect("www.domain.com")
        Else
          Me.ModelState.AddModelError("", "Invalid signin attempt.")
          oAction = Me.View("Index", oViewModel)
        End If
      Else
        oAction = Me.View("Index", oViewModel)
      End If

      Return oAction
    End Function
  End Class
End Namespace

ViewModel

Imports System.ComponentModel.DataAnnotations

Namespace ViewModels.Home
  Public Class SignIn
    <Required(ErrorMessage:="User Name is required.")>
    <Display(Name:="User Name")>
    Public Property Username As String

    <Required>
    Public Property Password As String

    <Display(Name:="Remember Me")>
    Public Property RememberMe As Boolean
  End Class
End Namespace

View

@ModelType ViewModels.Home.SignInOrSignUp

@Code
  Layout = Nothing
End Code

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Website</title>
  @Scripts.Render("~/scripts/bootstrap")
  @Scripts.Render("~/scripts/jquery")
  @Styles.Render("~/styles/bootstrap")
  @Styles.Render("~/styles/home")
</head>
<body>
  <div class="row">
    <div class="wrapper">
      <div class="section">
        <h5>Sign in here</h5>
        <div class="box">
          <div class="titlebar">Sign In</div>
          @Using (Html.BeginForm("signin", "home", FormMethod.Post, New With {.id = "SignInForm"}))
            @Html.AntiForgeryToken
            @Html.EditorFor(Function(M) Model.SignIn)
            @<div class="button">
              <input type="submit" value="Sign In" Class="button" />
            </div>
            @<div class="anchor">
              <a href="/">Forgot your password?</a>
            </div>
          End Using
        </div>
      </div>
      <div class="section">
        <h5>Or enter your City Code here</h5>
        <div class="box">
          <div class="titlebar">Sign Up</div>
          @Using (Html.BeginForm("signup", "home", FormMethod.Post, New With {.id = "SignUpForm"}))
            @Html.AntiForgeryToken
            @Html.EditorFor(Function(M) Model.SignUp)
            @<div class="button">
              <input type="submit" value="Continue" Class="button" />
            </div>
          End Using
        </div>
      </div>
    </div>
  </div>
</body>
</html>

--EDIT--

I've been able to get unblocked in the meantime with a clunky workaround in my view:

@Code
  If IsPost AndAlso Request.Path = "/home/signin" AndAlso Model.SignIn.Username.IsNothing Then
    @Html.ValidationMessageFor(Function(Model) Model.SignIn.Username, "Username is required", New With {.class = "text-danger"})
  End If
End Code

But I'd still like to use the in-built validation mechanism if it's possible to do so with multiple forms in the same view.

解决方案

There are 2 things you can try:

1. Put validation summary on the page:

With this option you are not changing anything in your controller but you are putting error summary on your page. You will not get highlighted field but you will still be able to display all errors, like:

<body>
  <div class="row">
    <div class="wrapper">
      @Html.ValidationSummary(false)
      ...
    </div>
  </div>
</body>

Not an elegant solution!

2. In controller use SignInOrSignUp as an input but from UI provide either SignIn or SignUp model:

With this approach you are not changing your vbhtml/cshtml file it will remain as it is only thing you are changing is type of argument on controller methods:

Namespace Controllers.Home
  Partial Public Class HomeController
    ...
    <HttpPost>
    <ValidateAntiForgeryToken>
    Public Async Function SignIn(Model As SignInOrSignUp) As Task(Of ActionResult)
       ...
    End Function
        
    <HttpPost>
    Public Async Function SignUp(Model As SignInOrSignUp) As Task(Of ActionResult)
       ...
    End Function
  End Class
End Namespace

unless there is some complex validation involved, this approach will work like a charm!

这篇关于使用多种表单时验证失败的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆