2015-10-20 57 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/###" ... >