In ASP.NET Core MVC, I have multiple forms on a page, and the validation summaries show on both forms

huangapple go评论59阅读模式
英文:

In ASP.NET Core MVC, I have multiple forms on a page, and the validation summaries show on both forms

问题

如果我在页面上有两个表单,并提交其中一个,同样的验证摘要会显示在两者上。

我正在使用Umbraco 10的SurfaceController,但我不知道这是否相关。

控制器看起来像这样:

[HttpPost]
[ValidateUmbracoFormRouteString]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Login(LoginForm model)
{
	if (!ModelState.IsValid)
	{
		ModelState.AddModelError(string.Empty, "请提供用户名和密码");
		return CurrentUmbracoPage();
	}
	//...snipped...
}

验证摘要看起来像这样

@Html.ValidationSummary()

我有另一个类似的用于注册的表单,当我提交该表单时,注册验证会显示在登录区域的标题中。

我查看了'prefix'参数,但未能找到与其使用相关的任何文档。

英文:

If I have two forms on a page, and submit one the same validation summary shows for both.

I am using an Umbraco 10 SurfaceController but I don't know that this is relevant.

The controller looks like this:

[HttpPost]
[ValidateUmbracoFormRouteString]
[ValidateAntiForgeryToken]
public async Task&lt;IActionResult&gt; Login(LoginForm model)
{
	if (!ModelState.IsValid)
	{
		ModelState.AddModelError(string.Empty, &quot;Please provide username and password&quot;);
		return CurrentUmbracoPage();
	}
	//...snipped...
}

The validation summary looks like this

@Html.ValidationSummary()

I have another similar form for registration and the registration validation shows in the header login area when I submit that form.

I looked into the 'prefix' parameter but I failed to find any documentation regarding it's use.

答案1

得分: 1

@Html.ValidationSummary()只是根据您的ModelState错误生成IHtmlContent,它根本不知道您提交的哪个表单。

为了决定错误消息应该呈现在哪里,您可以添加一个隐藏的输入,传递与表单相关的值给控制器。

例如,我尝试了以下的最小示例:

public class Entity1
{
    public int Id { get; set; }
    [Required]
    public string? Name { get; set; }
    [Required]
    public string? Prop1 { get; set; }
}

public class Entity2
{
    public int Id { get; set; }
    [Required]
    public string? Name { get; set; }
    [Required]
    public string? Prop2 { get; set; }
}

public class MyViewModel
{
    public Entity1? Entity1 { get; set; }
    public Entity2? Entity2 { get; set; }
}

视图:

<div class="row">
    <div class="col-md-4">
        <form asp-action="Create">
            @if (ViewData["Form"] as string == "form1")
            {
                @Html.ValidationSummary()
            }
            
            <div class="form-group">
                <label asp-for="Entity1.Name" class="control-label"></label>
                <input asp-for="Entity1.Name" class="form-control" />
                <span asp-validation-for="Entity1.Name" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="Entity1.Prop1" class="control-label"></label>
                <input asp-for="Entity1.Prop1" class="form-control" />
                <span asp-validation-for="Entity1.Prop1" class="text-danger"></span>
            </div>
            <input name="form" value="form1" hidden />
            <div class="form-group">
                <input type="submit" value="Create" class="btn btn-primary" />
            </div>
        </form>
        <form asp-action="Create" name="">
            @if (ViewData["Form"] as string == "form2")
            {
                @Html.ValidationSummary()
            }
            <div class="form-group">
                <label asp-for="Entity2.Name" class="control-label"></label>
                <input asp-for="Entity2.Name" class="form-control" />
                <span asp-validation-for="Entity2.Name" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="Entity2.Prop2" class="control-label"></label>
                <input asp-for="Entity2.Prop2" class="form-control" />
                <span asp-validation-for="Entity2.Prop2" class="text-danger"></span>
            </div>
            <input name="form" value="form2" hidden />
            <div class="form-group">
                <input type="submit" value="Create" class="btn btn-primary" />
            </div>
        </form>
    </div>
</div>

<div>
    <a asp-action="Index">Back to List</a>
</div>

控制器:

[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create(MyViewModel myvm)
{
    // .......
    ModelState.AddModelError("", "ModelErr");
    var formname = HttpContext.Request.Form["form"].ToString();
    ViewData["Form"] = formname;
    return View(myvm);
}

结果如下:图像链接

英文:

@Html.ValidationSummary() just generates IHtmlContent accroding to your ModelState error,it doesn't know which form you posted at all

In order to decide where the error message should be rendered,you could add a hidden input pass a value related the form to controller

For Example,I tried with a minimal example as below:

public class Entity1
{
public int Id { get; set; }
[Required]
public string? Name { get; set; }
[Required]
public string? Prop1 { get; set; }
}
public class Entity2
{
public int Id { get; set; }
[Required]
public string? Name { get; set; }
[Required]
public string? Prop2 { get; set; }
}
public class MyViewModel
{
public Entity1? Entity1 { get; set; }
public Entity2? Entity2 { get; set; }
}

View:

&lt;div class=&quot;row&quot;&gt;
&lt;div class=&quot;col-md-4&quot;&gt;
&lt;form asp-action=&quot;Create&quot;&gt;
@if (ViewData[&quot;Form&quot;] as string == &quot;form1&quot;)
{
@Html.ValidationSummary()
}
&lt;div class=&quot;form-group&quot;&gt;
&lt;label asp-for=&quot;Entity1.Name&quot; class=&quot;control-label&quot;&gt;&lt;/label&gt;
&lt;input asp-for=&quot;Entity1.Name&quot; class=&quot;form-control&quot; /&gt;
&lt;span asp-validation-for=&quot;Entity1.Name&quot; class=&quot;text-danger&quot;&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;div class=&quot;form-group&quot;&gt;
&lt;label asp-for=&quot;Entity1.Prop1&quot; class=&quot;control-label&quot;&gt;&lt;/label&gt;
&lt;input asp-for=&quot;Entity1.Prop1&quot; class=&quot;form-control&quot; /&gt;
&lt;span asp-validation-for=&quot;Entity1.Prop1&quot; class=&quot;text-danger&quot;&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;input name=&quot;form&quot; value=&quot;form1&quot; hidden /&gt;
&lt;div class=&quot;form-group&quot;&gt;
&lt;input type=&quot;submit&quot; value=&quot;Create&quot; class=&quot;btn btn-primary&quot; /&gt;
&lt;/div&gt;
&lt;/form&gt;
&lt;form asp-action=&quot;Create&quot; name=&quot;&quot;&gt;
@if (ViewData[&quot;Form&quot;] as string == &quot;form2&quot;)
{
@Html.ValidationSummary()
}
&lt;div class=&quot;form-group&quot;&gt;
&lt;label asp-for=&quot;Entity2.Name&quot; class=&quot;control-label&quot;&gt;&lt;/label&gt;
&lt;input asp-for=&quot;Entity2.Name&quot; class=&quot;form-control&quot; /&gt;
&lt;span asp-validation-for=&quot;Entity2.Name&quot; class=&quot;text-danger&quot;&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;div class=&quot;form-group&quot;&gt;
&lt;label asp-for=&quot;Entity2.Prop2&quot; class=&quot;control-label&quot;&gt;&lt;/label&gt;
&lt;input asp-for=&quot;Entity2.Prop2&quot; class=&quot;form-control&quot; /&gt;
&lt;span asp-validation-for=&quot;Entity2.Prop2&quot; class=&quot;text-danger&quot;&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;input name=&quot;form&quot; value=&quot;form2&quot; hidden /&gt;
&lt;div class=&quot;form-group&quot;&gt;
&lt;input type=&quot;submit&quot; value=&quot;Create&quot; class=&quot;btn btn-primary&quot; /&gt;
&lt;/div&gt;
&lt;/form&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;a asp-action=&quot;Index&quot;&gt;Back to List&lt;/a&gt;
&lt;/div&gt;

Controller:

[HttpPost]
[ValidateAntiForgeryToken]
public async Task&lt;IActionResult&gt; Create(MyViewModel myvm)
{
.......
ModelState.AddModelError(&quot;&quot;, &quot;ModelErr&quot;);
var formname = HttpContext.Request.Form[&quot;form&quot;].ToString();
ViewData[&quot;Form&quot;] = formname;
return View(myvm);
}

The result:
In ASP.NET Core MVC, I have multiple forms on a page, and the validation summaries show on both forms

huangapple
  • 本文由 发表于 2023年7月11日 13:45:15
  • 转载请务必保留本文链接:https://go.coder-hub.com/76658973.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定