【问题标题】:Pass model from partial view to controller将模型从局部视图传递到控制器
【发布时间】:2014-11-13 18:23:09
【问题描述】:

所以我的局部视图看起来像 -

@model Example.Models.ForgotPasswordViewModel

@Html.ValidationSummary("", new { @class = "text-danger" })
<div class="form-group">
    @Html.LabelFor(m => m.Email, new { @class = "col-md-2 control-label" })
    <div class="col-md-10">
        @Html.TextBoxFor(m => m.Email, new { @class = "form-control" })
    </div>
</div>
<div style="font-size: 16px; text-align:center; margin-top:10px;">
    @Html.ActionLink("Email Link", "ForgotPassword", "Account")
</div>

作为 asp.net 的开箱即用 ForgotPassword 视图的一部分,但我将它变成了部分视图。原来的视图被包裹在“Html.BeginForm(..”中,但我显然不能这样做。(它导致表单中的表单)

如何通过传递声明的 @model 来调用 Account 控制器的 ForgotPassword 方法?

由@Html.TextBoxFor(m => m.Email, new { @class= "form-control" }) 生成的HTML:

<input class="form-control" id="Email" name="Email" type="text" value="" />

您的 AccountController.ForgetPassword(..) 的签名:

//
// POST: /Account/ForgotPassword
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> ForgotPassword(ForgotPasswordViewModel model)
{
    if (ModelState.IsValid)
    {
        var user = await UserManager.FindByNameAsync(model.Email);
        if (user == null || !(await UserManager.IsEmailConfirmedAsync(user.Id)))
        {
            // Don't reveal that the user does not exist or is not confirmed
            return View("ForgotPasswordConfirmation");
        }

        // For more information on how to enable account confirmation and password reset please visit http://go.microsoft.com/fwlink/?LinkID=320771
        // Send an email with this link
        string code = await UserManager.GeneratePasswordResetTokenAsync(user.Id);
        var callbackUrl = Url.Action(
            "ResetPassword", "Account", 
             new { userId = user.Id, code = code }, 
             protocol: Request.Url.Scheme);

        await UserManager.SendEmailAsync(user.Id, "Reset Password", "Please reset your password by clicking <a href=\"" + callbackUrl + "\">here</a>");
        return View("ForgotPasswordConfirmation");
    }

    // If we got this far, something failed, redisplay form
    return RedirectToAction("Index", "Home");
}

正如 Erik 指出的,需要确保字段在局部视图中是唯一标识的。该帖子有两次电子邮件。

【问题讨论】:

  • 您只能POST 使用表单或ajax 到控制器(IE ActionLink 不提交表单,它只是创建一个超链接)。因此,您的选择是将这个部分移到表单之外,或者使用 javascript/ajax 更改表单目的地,然后提交表单(但要小心,因为现在您在同一个表单上还有可能相互冲突的其他表单元素)。
  • @ErikPhilips 如何使用 AJAX 更改表单的目的地?
  • 抱歉打错了,应该是or use javascript/jquery to change...
  • Ok.. @ErikPhilips 如何使用 jQuery 更改表单的目的地? :)
  • 您不能使用 ajax 来更改表单目的地,但您可以使用 ajax 手动将表单的值发布到任何 actionResult 或 API。然而,这不会很优雅。

标签: c# asp.net-mvc razor asp.net-mvc-5


【解决方案1】:

@ErikPhilips 如何使用 jQuery 更改表单的目的地? :)

我会将 Action 链接更改为按钮:

@Html.ValidationSummary("", new { @class = "text-danger" })
<div class="form-group">
    @Html.LabelFor(m => m.Email, new { @class = "col-md-2 control-label" })
    <div class="col-md-10">
        @Html.TextBoxFor(m => m.Email, new { @class = "form-control" })
    </div>
</div>
<div style="font-size: 16px; text-align:center; margin-top:10px;">
    <input type="button" 
            value="Email Link" 
            class="change-form-url"
            data-url="@Url.Action("ForgotPassword", "Account")"/>
</div>

jquery:

$(document).ready(funciton()
{
  $('.change-form-url').on('click', function()
  {
    var url = $(this).data('url');
    var form = $(this).closest('form');
    form.prop('action', url);
    form.submit();
  });
});

这个我没有测试,应该和你想要的很接近。

【讨论】:

  • 测试被高估了...完美运行!谢谢!
  • jQuery 应该非常简单。如果有任何不妥之处,请告诉我。
  • 即使我在 Account 控制器中正确的 ForgotPassword 方法中设置了一个断点,但传入的模型只有一个元素,即 email,并且它为 null。虽然我填了。为什么它会在没有输入电子邮件地址的情况下传递模型?
  • 您确定 Partial 包含在表单中吗?
  • 是的,它就在那里。我有 java 脚本可以在点击链接时显示它。
【解决方案2】:

BeingForm 有一些重载:

@using (Html.BeginForm("ActionName","Controller"))
{
    @Html.TextBox("Name");
    @Html.Password("Password");
    <input type="submit" value="Sign In">
}

将动作名称和控制器名称添加到 beginForm 调用中,您可以覆盖 Post 的默认位置。

我建议您在主表单之外调用局部视图,这样一页上就有两个表单(不是嵌套的)。然后您可以将忘记密码模型指向正确的控制器方法。

【讨论】:

  • The original view was wrapped in "Html.BeginForm(..", but I obviously can't do that. (It results in a form inside a form) 正是 OP 不希望发生的事情。
  • 所以您已经在 FORM 中创建了一个 FORM。正是他不希望发生的事情。
  • 覆盖是什么意思?我认为你的意思是point to the correct controller method?。 OP 所说的是,他有一个带有表单(我们将其称为表单 A)的视图,该表单似乎与忘记密码模型完全无关。在表格 A 中,他调用这个部分来显示忘记密码模型。他不能简单地将部分包装在一个表格(表格 B)中,因为这样他就有一个表格内的表格。如果他将表单 A 移动到部分表单中,他就会失去视图表单及其功能。
  • 我不明白为什么他不能在原始表单之外调用忘记密码模型......一页上的两个表单。我的意思也是超载;犯了一个很像你的错字。此外,ActionResult 是一种控制器方法...只是俚语,因为它是典型的返回类型。
猜你喜欢
  • 1970-01-01
  • 2013-11-20
  • 1970-01-01
  • 2018-02-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-10-28
相关资源
最近更新 更多