2012-07-05 52 views
2

我希望在視圖中顯示DropDownList,並在我的模型(ExampleAddSetupDto)中包含發送到視圖的列表以填充下拉列表。這工作正常,但如果我有驗證錯誤,並重新顯示在傳入模型中的視圖,我的列表現在爲空。MVC3 - 用於dropdownlist的列表信息在發佈後爲空

我的動作如下(注意:如果ModelState.IsValid失敗,就會出現問題)。此外,Action方法的第二個參數可能看起來很奇怪,因爲我使用Autofac將正確的服務注入方法中)。

[HttpPost] 
    [ValidateAntiForgeryToken] 
    public ActionResult Add(ExampleAddSetupDto add, IServiceAddCommit<IExampleAddSetupDto, IExampleAddCommitDto> service) 
    { 

     if (ModelState.IsValid) 
     { 
      var response = service.Create(add); 
      if (response.IsValid) 
      { 
       TempData["message"] = "You successfully added a new Example Entry"; 
       return View("AddSuccess", response); 
      } 

      //else errors, so copy the errors over to the ModelState 
      response.CopyErrorsToModelState(ModelState, add); 
     } 

     // Some validation error, so redisplay same view 
     return View(add); 

    } 

我的模型看起來是這樣的:

public class ExampleAddSetupDto : IExampleAddSetupDto 
{ 

    [StringLength(50, MinimumLength = 2)] 
    public string Name { get; set; } 

    public int Option1Id { get; set; } 

    public int Option2Id { get; set; } 

    //----------------------------- 
    //now the properties for the drop down lists 

    public IList<Option1> PosibleEntriesForOption1 { get; set; } 
    public IList<Option2> PosibleEntriesForOption2 { get; set; } 

} 

我的看法是:

@model ServiceLayer.Example.DTOs.ExampleAddSetupDto 

@{ 
    ViewBag.Title = "Add"; 
} 

<h2>Add</h2> 

<script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script> 
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script> 

@using (Html.BeginForm()) 
{ 
@Html.AntiForgeryToken() 
@Html.ValidationSummary(true) 
<fieldset> 
    <legend>Add an Example item</legend> 

    <div class="editor-label"> 
     @Html.LabelFor(model => model.Name) 
    </div> 
    <div class="editor-field"> 
     @Html.EditorFor(model => model.Name) 
     @Html.ValidationMessageFor(model => model.Name) 
    </div> 
    <div class="editor-field"> 
     @Html.Label("Option1") 
     @Html.DropDownListFor(model => model.Option1Id, new SelectList(Model.PosibleEntriesForOption1, "Option1Id", "OptionText")) 
     @Html.ValidationMessageFor(model => model.Option1Id) 
    </div> 
    <div class="editor-field"> 
     @Html.Label("Option2") 
     @Html.DropDownListFor(model => model.Option2Id, new SelectList(Model.PosibleEntriesForOption2, "Option2Id", "OptionText")) 
     @Html.ValidationMessageFor(model => model.Option2Id) 
    </div> 
    <p> 
     <input type="submit" value="Create" /> 
    </p> 
</fieldset> 

}

我明白,我需要與返回Model.PosibleEntriesForOption形成。我嘗試使用Html.HiddenFor助手視圖返回列表,即

@Html.HiddenFor(model => model.PosibleEntriesForOption1) 

但這引發錯誤 「值」 System.Collections.Generic.List`1 [DataClasses.ExampleClasses.Option1] ' 是無效的。'。

顯然我在這裏失去了一些東西,我將不勝感激關於如何返回列表的建議,以便重新顯示模型不會導致錯誤。

回答

1

如果你被迫要堅持兩個請求之間的整個列表,不管是什麼原因,我認爲這樣做會用最好的方式:

TempData["EnterUniqueKeyHere"] = PossibleEntriesForOption1; 

來存放它,然後:

PossibleEntriesForOption1 = TempData["EnterUniqueKeyHere"] as IList<Option1>; 

進行檢索。

請注意,存儲在TempData中的任何內容都將在單個請求後自動刪除。

+0

謝謝丹。所有的答案都證實我需要在返回頁面之前重新加載列表。有點可惜,但這是它的方式。我非常喜歡你的答案丹,因爲它使用TempData,但我可以很好地解決它在服務中,因爲我正在使用模板化服務。 – 2012-07-05 19:01:00

0

如果驗證失敗,則需要使用值列表加載下拉列表。其他方面,它會失敗。

我相信,當你最初加載你的視圖時,它會執行HttpGet方法。在HttpGet方法中,您必須綁定下拉列表

當您提交頁面時,它會執行httpPost方法,如果一切正常,它會提交。如果驗證失敗,它將執行HTTPPost方法,但它無法找到任何下拉綁定。

那麼試試這個:在你的情況

if (ModelState.IsValid) 
      { 
       var response = service.Create(add); 
       if (response.IsValid) 
       { 
        TempData["message"] = "You successfully added a new Example Entry"; 
        return View("AddSuccess", response); 
       } 

       //else errors, so copy the errors over to the ModelState 
       response.CopyErrorsToModelState(ModelState, add); 
      } 
    else //if validation fails, you need to reload the dropdown and display your view. 
     { 
      // populate your dropdown again 
       // You can add errors list into ModelState. 
       ViewData.ModelState.AddModelError("What is the error", "Error Message, "What needs to be done by user, to get it work"); 
      return view(add) 
     } 
+0

這會顯示任何驗證錯誤嗎? – jrummell 2012-07-05 13:41:56

+0

@ jrummell:請參閱我的更新回答,以便在驗證失敗時顯示錯誤。 – 2012-07-05 13:47:49

+0

嗨哈里。是的,我的初始視圖特別填寫PosibleEntriesForOption1和PosibleEntriesForOption2列表。我只是想將這些數據重新發布到帖子中,但顯然這不起作用。我將在錯誤中添加一個重新填充的列表。 – 2012-07-05 19:07:28

0

論添加取得動作,您將創建適當的值模型,這些2個屬性 - PosibleEntriesForOption1 & PosibleEntriesForOption2 由於這些設置不當&可在視圖中,下拉獲取上得到正確渲染。

現在在POST上,當驗證失敗時,您必須重新設置這些屬性。

if (ModelState.IsValid) 
    { 
     // Do something 
    } 

    // before you redisplay the same view 
    // set the properties PosibleEntriesForOption1 & PosibleEntriesForOption2 

    // Some validation error, so redisplay same view 
    return View(add); 
+0

感謝Sandeep提供更新的答案。每個人都確認我無法從帖子中傳回原始列表,因此我需要在帖子操作中重新加載列表。我只需要確定哪裏是最好的地方,因爲代碼將從模板自動生成。 – 2012-07-05 19:04:26

0

丹尼克森的TempData技術可以工作一次,但如果驗證再次失敗,則TempData項爲空。我想我必須重新加載我的列表。

+1

剛剛找到答案,把你的值列表作爲隱藏字段在這樣的視圖中,他們將在您的文章中提供: '@foreach(Model.Locations中的var位置) { @ Html.Hidden( 「地點」,地點) }' – gbelzile 2012-08-16 18:34:45