2015-10-20 79 views
1

我注意到mvc默认项目中的一些东西,这让我想知道它是如何工作的。当我使用个人用户帐户身份验证创建ddefault MVC项目时,Visual Studio使用两个“ResetPassword”操作为AccountController构建脚手架。一个通过GET请求接受字符串参数的人。该行动是这样的:从url传递参数来查看

// 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> 

我访问网址中包含的代码操作,GET-风格,视图知道初始化模式来自网址的媒体资源。有趣的一点是,这只有在我使用@Html.HiddenFor()时才有效。这是如何工作的,以及该视图如何知道何时从URL中获取数据以及何时不需要?

+1

如果你用'账户/ ResetPassword/{}代码定义的路径'那么你甚至不需要隐藏的输入(它将默认添加到死记硬件参数中) –

+0

来自路径值,查询字符串值和模型的所有值,并添加到由View控件帮助程序用来设置窗体控件的相关值的值的ViewDataDictionary中 –

+0

@StephenMuecke关于第二条评论,我也怀疑这一点,但调试器中的一步一步显示并清空ViewDataDictionary,直至完成视图渲染。此外,它为什么只与Html.HiddenFor()一起工作?我尝试过DisplayFor,但它不工作。 – jose

回答

2

因为你的方法是

public ActionResult ResetPassword(string code) 

DefaultModelBinder而从模型中的值,如果他们存在,因此,它将使code值将增加ModelState

HiddenFor(m => m.Code)方法从ModelState使用值

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

其中###是v你传给了方法。

您声明“视图知道从URL初始化模型属性”是不正确的。该模型没有初始化,其实null你可以测试使用

<div>@Model.Code</div> 

这将抛出一个“不设置到对象的实例对象引用。”例外,而

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

将显示正确的值。

边注:从您的意见,即DisplayFor(m => m.Code)不显示值的原因是,它是用在ViewData值(这是null因为模型是null)。默认显示模板使用下面的代码(参见source code

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

,而不是HiddenFor(m => m.Code)它使用下面的代码(参见source 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/###" ... >