将参数从网址传递到视图

本文关键字:视图 址传 参数 | 更新日期: 2023-09-27 18:18:39

我注意到 mvc 默认项目中的一些东西让我想知道它是如何工作的。当我使用个人用户帐户身份验证创建默认 MVC 项目时,Visual Studio 使用两个"重置密码"操作来搭建帐户控制器基架。一个通过 GET 请求接受字符串参数。操作如下所示:

   // GET: /Account/ResetPassword  
    [AllowAnonymous]  
    public ActionResult ResetPassword(string code)  
    {  
        return code == null ? View("Error") : View();  
    }  

视图如下所示:

@model SISGRAD_MVC.Models.ResetPasswordViewModel
@{
    ViewBag.Title = "Reset password";
}
<h2>@ViewBag.Title.</h2>
@using (Html.BeginForm("ResetPassword", "Account", FormMethod.Post, new { @class = "form-horizontal", role = "form" }))
{
    @Html.AntiForgeryToken()
    <h4>Reset your password.</h4>
    <hr />
    @Html.ValidationSummary("", new { @class = "text-danger" })
    @Html.HiddenFor(model => model.Code)
    <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 class="form-group">
        @Html.LabelFor(m => m.Password, new { @class = "col-md-2 control-label" })
        <div class="col-md-10">
            @Html.PasswordFor(m => m.Password, new { @class = "form-control" })
        </div>
    </div>
    <div class="form-group">
        @Html.LabelFor(m => m.ConfirmPassword, new { @class = "col-md-2 control-label" })
        <div class="col-md-10">
            @Html.PasswordFor(m => m.ConfirmPassword, new { @class = "form-control" })
        </div>
    </div>
    <div class="form-group">
        <div class="col-md-offset-2 col-md-10">
            <input type="submit" class="btn btn-default" value="Reset" />
        </div>
    </div>

我使用 URL 中的代码访问操作,GET 样式,并且视图知道从 URL 初始化模型属性。有趣的是,这仅在我使用 @Html.HiddenFor() 时才有效。这如何工作,视图如何知道何时从 URL 中提取数据,何时不从中提取数据?

将参数从网址传递到视图

因为你的方法

public ActionResult ResetPassword(string code)

DefaultModelBinder会将 code 的值添加到ModelState

HiddenFor(m => m.Code) 方法使用来自ModelState的值,而不是来自模型的值(如果存在(,因此它将呈现

<input type="hidden" name="Code" id="Code" value="###" />

其中###是传递给方法的值。

您关于"视图知道从 URL 初始化模型属性">的说法不正确。该模型未初始化,实际上您可以使用null进行测试

<div>@Model.Code</div>

这将引发"对象引用未设置为对象的实例">异常,而

<div>@ViewData.ModelState["Code"].Value.AttemptedValue</div>

将显示正确的值。

旁注:从您的评论中,DisplayFor(m => m.Code) 不显示该值的原因是它正在使用ViewData中的值(这是null,因为模型是null的(。默认显示模板使用以下代码(请参阅源代码(

internal static string StringTemplate(HtmlHelper html)
{
  return html.Encode(html.ViewContext.ViewData.TemplateInfo.FormattedModelValue);
}

与使用以下代码的HiddenFor(m => m.Code)相反(请参阅源代码

default:
  string attemptedValue = (string)htmlHelper.GetModelStateValue(fullName, typeof(string));
  tagBuilder.MergeAttribute("value", attemptedValue ?? ((useViewData) ? htmlHelper.EvalString(fullName, format) : valueParameter), isExplicitValue);
  break;

另请注意,如果使用url: "Account/ResetPassword/{code}"定义路由,则无需在视图中添加隐藏输入。默认情况下,它将添加为路由值 - BeginForm()方法将呈现

<form action="Account/ResetPassword/###" ... >