ASP.NET MVC中的多个表单

8

背景
假设我有以下内容:
在布局 Site.Master 中:

<div class="leftColumn">
    <asp:ContentPlaceHolder ID="MainContent" runat="server" />
</div>
<div class="rightColumn">
    <% Html.RenderPartial("_Login"); %>
    <asp:ContentPlaceHolder ID="SideContent" runat="server" />
</div>

登录的partialView如下:

<form action="/myApp/Account/Login" method="post">
    <input name="name" />Name<br />
    <input name="password" type="password" />Password<br />
    <button>Login</button>
</form>

是否可以仅更新登录小部件表单而不是整个内容页面?

5个回答

15

如果你在谈论HTTP POST,那么只有由表单内的提交按钮(也可以由JavaScript发起)所启动的POST请求才会被发送到服务器。

如果表单是嵌套的,则这种方式不适用。外层表单将始终被提交到服务器。

在下面的示例HTML中,点击第一个表单中的提交按钮不会将第二个表单的值发送到服务器。同样,点击第二个提交按钮也不会将第一个表单的值发布到服务器。

<html>
...
  <body> 
    <div>

      <form action="/Login/Login" method="post">
        <input type="text" name="username" value="" />
        <input type="text" name="passowrd" value="" />
        <input type="submit" name="login" value="Login" />
      </form>


      <form action="/Login/AdminLogin" method="post">
        <input type="text" name="username" value="" />
        <input type="text" name="passowrd" value="" />
        <input type="submit" name="login" value="Login Admin" />
      </form>
    </div>
</body>
</html>
如果你只想更新/更改表单中的一个部分,那么如果不使用JavaScript并执行JavaScript提交(也称为Ajax),则无法完成。

1
耶...尽管那个问题肯定不清楚,但这正是我想听到的答案:“如果你只想更新/更改表单部分中的一个,那么不,这是不可能的,除非使用...”到目前为止,似乎没有一种干净的方法在asp.net mvc中实现所谓的小部件。 :/ - Arnis Lapsa
这并不是MVC的限制 - 你要求只更新页面的一部分,因此你必须在客户端执行某些操作(例如AJAX/JS),因为所有HTML表单根据其定义都会在提交时更改页面。 - Matt Mitchell
问题刚刚获得了“热门”徽章。惊讶地发现自己学到了这么多。这是一个非常愚蠢的问题。:D - Arnis Lapsa

1
如果你有两个简单的表单,可以使用以下方法:
你需要创建两个不同的局部视图。
@model CustomerInfoModel
@using (Ajax.BeginForm("CustomerInfo", "Customer", new AjaxOptions { HttpMethod = "Post", OnBegin = "InfoLoading", OnComplete = "InfoCompleted" }, new { id = "info", @class = "form-horizontal" }))
    {
    <input type="text" class="form-control" name="Name" id="Name" value="@Model.Name" />
    <input type="email" class="form-control" name="Email" id="Email"  value="@Model.Email" />
    <button type="submit" id="save-info" class="btn-medium red">Save</button>
    }

并且

@model CustomerPasswordChangeModel
@using (Ajax.BeginForm("CustomerPasswordChange", "Customer", new AjaxOptions { HttpMethod = "Post", OnBegin = "InfoLoading", OnComplete = "InfoCompleted" }, new { id = "change", @class = "form-horizontal" }))
{
<input type="password" class="form-control" name="OldPassword" id="OldPassword"  value="" />
<input type="password" class="form-control" name="NewPassword" id="NewPassword"  value="" />
<button type="submit" id="save-change" class="btn-medium red" autocomplete="off">Save</button>
}

在您的父视图中,
@Html.Partial("CustomerInfo", Model.CustomerInfo)

并且

@Html.Partial("CustomerPasswordChange", Model.CustomerPasswordChange)

在控制器中:
    [HttpPost]
    public ActionResult CustomerInfo([Bind(Include = "Name,Email")] CustomerInfoModel model)
    {
        if (ModelState.IsValid)
            return new Json(new { success=true, message="Updated.", errors=null);

// do you logic

        return new Json(new { success=false, message="", errors=getHtmlContent(ModelState.Values.SelectMany(v => v.Errors).ToList(), "ModelError"));
    }

    [HttpPost]
    public ActionResult CustomerPasswordChange([Bind(Include = "OldPassword,NewPassword")] CustomerPasswordChangeModel model)
    {
        if (ModelState.IsValid)
            return new Json(new { success=true, message="Updated.", errors=null);

// do you logic

        return new Json(new { success=false, message="", errors=getHtmlContent(ModelState.Values.SelectMany(v => v.Errors).ToList(), "ModelError"));
    }

这将会实现你想要的功能。 < p >< em >注意:getHtmlContent方法只是生成一个错误消息以在页面上显示。没有什么特别之处。如果需要,我可以分享它。


1
如果您构建了一个接受FormCollection的控制器方法,并且您的视图定义了两个表单,那么返回的formcollection将填充来自表单A或表单B的值。您可以检查formCollection并根据其中的值分支逻辑。如果您想非常明确,您可以在两个表单中都出现相同的隐藏变量,并具有可帮助您做出选择的值。
这是一种方法。我相信还有其他几种处理方式。

0
if(pass != true) 
{ 
 ViewData["Message'] = "Hey your login failed!"; Return View("Login") 
}

在ViewPage上

<form action="/tralala/Account/Login" method="post"> 
  <input name="name" />Name<br /> 
  <input name="password" type="password" />Password<br /> 

  <button>Login</button> 
 <div style="color: red"><%=ViewData["Message"] %><div> 
</form>

1
你没理解重点。问题是 - 如何只更新一个表格,如果可能的话,而不是如何使用ViewData字典。 - Arnis Lapsa
抱歉伙计,我一直在阅读你的问题,但我不明白你在问什么。 - Skiltz
1
我只是在问,如果有两个<form>元素的页面一次只能更新其中一个,而不触及另一个,这是否可行? - Arnis Lapsa

0

您的问题不是很清楚。

但就我所理解的来说,答案很可能是肯定的。您可以根据用户输入更新任何您想要更新的内容。


我也不明白你在问什么... 你能否编辑你的问题并提供更多上下文。你的第一个“form”格式不正确,没有任何输入元素... 它是用来做什么的?我认为modelviewstate只更新它尝试绑定的字段...?那是一个登录小部件还是登录页面?或者你有关于验证消息和验证高亮的问题?我不得不创建一些自定义的HTMLHelper扩展来处理多个表单,但我真的不知道它们是否适用于这里,因为我无法理解你的问题... 更多的信息会有所帮助。 - Charlino
非常抱歉,英语也不是我的母语。我会尽力编辑问题。 - Arnis Lapsa

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接