2014-12-18 191 views
0

我想通過HttpPost將模型數據從視圖(和視圖內的PartialView)傳遞迴控制器。 (改編自Pass SelectedValue of DropDownList in Html.BeginForm() in ASP.NEt MVC 3將模型數據從視圖傳遞到控制器

爲什麼?我想顯示每個具有DropDownList和多個選項的資產列表。提交表單以從DropDownList中讀取所選項目。

我2(簡體)型號:

public class Booking 
{ 
    public int BookingID { get; set; } 
    public int StoreID { get; set; } 
    ... 
    public IEnumerable<AssetShort> Assets { get; set; } 
} 

public class AssetShort 
{ 
    public int AssetID { get; set; } 
    .... 
    public int SelectedAction { get; set; } 
    public IEnumerable<SelectListItem> ActionList { get; set; } 
} 

在我的預訂控制器>創建我生成列表:

public ActionResult Booking(int id) 
    { 
    // get myBag which contains a List<Asset> 
    // booking corresponds to 'id' 

     var myAssets = new List<AssetShort>(); 
     foreach (var a in myBag.Assets) 
     { 
      var b = new AssetShort(); 
      b.AssetID = a.ID; 
      b.SelectedAction = 0; 
      b.ActionList = new[] 
       { 
      new SelectListItem { Selected = true, Value = "0", Text = "Select..."}, 
      new SelectListItem { Selected = false, Value = "1", Text = "Add"}, 
      new SelectListItem { Selected = false, Value = "2", Text = "Remove"}, 
      new SelectListItem { Selected = false, Value = "3", Text = "Relocate"}, 
      new SelectListItem { Selected = false, Value = "4", Text = "Upgrade"}, 
      new SelectListItem { Selected = false, Value = "5", Text = "Downgrade"} 
       }; 
      myAssets.Add(b); 
     }; 

     var model = new BookingRequirementsViewModel 
      { 
       BookingID = booking.ID, 
       StoreID = booking.StoreID, 
       Assets = myAssets.ToList(), 
      }; 
     return View(model); 

筆者認爲:

@model uatlab.ViewModels.BookingRequirementsViewModel 
@{ 
    ViewBag.Title = "Booking step 2"; 
} 
<h4>Your booking ref. @Model.BookingID</h4> 
@using (Html.BeginForm("Booking2", "Booking", FormMethod.Post)) 
{ 
<fieldset> 
    @Html.AntiForgeryToken() 
    @Html.HiddenFor(model => model.StoreID) 

    @Html.Partial("_Assets", Model.StoreAssets) 

    <input type="submit" value="Cancel" class="btn btn-default" /> 
    <input type="submit" value="Next" class="btn btn-default" /> 
</fieldset> 
} 

局部視圖包括

@foreach (var item in Model) 
{ 
    <tr> 
     <td>@item.Name</td> 
     <td>@item.Number</td> 
     <td>@Html.DropDownListFor(modelItem=>item.SelectedAction, item.ActionList)</td> 
    </tr> 
} 

所以,這一切工作正常,在瀏覽器中,我可以列出的每個資產選擇的下拉列表中,但是當我提出調回唯一的價值是STOREID因爲它是在一個「 HiddenFor」。

的booking2控制器有一個參數型號:

public ActionResult Booking2(BookingRequirementsViewModel model) 
{ 
    //loop through model.Assets and display SelectedActions 
} 

讓我說清楚的問題是 - 在Booking2控制器的型號爲NULL在調試模式下查看時,我得到錯誤「對象引用未設置爲對象的實例。「

任何想法,請如何從視圖回傳模型到控制器?

問候 克雷格

+1

您無法使用部分來在集合中生成控件。如果你檢查html,你會看到你有'name'屬性重複(以及重複的'id'屬性是無效的html)。您需要在主視圖中使用'for'循環,或者爲'Assets'使用自定義的'EditorTemplate'。 – 2014-12-18 23:05:24

回答

1

你需要創建一個AssetShortEditorTemplate。我還建議把ActionListBookingRequirementsViewModel所以你不能再生每個AssetShort

您發佈不決策意識的車型新SelectList。您的控制器有var model = new BookingRequirementsViewModel { ..., Assets = myAssets.ToList() };,但在您看來您指的是@Html.Partial("_Assets", Model.StoreAssets)?這兩個不同的屬性。我會認爲StoreAssetsIEnumerable<AssetShort>

/Views/Shared/EditorTemplates/AssetShort.cshtml

@model AssetShort 
<tr> 
    <td>@Html.DispayFor(m => m.Name)</td> 
    .... 
    <td> 
    @Html.DropDownListFor(m => m.SelectedAction, (IEnumerable<SelectListItem>)ViewData["actionList"], "--Please select--") 
    @Html.ValidationMessageFor(m => m.SelectedAction) 
    </td> 
</tr> 

在主視圖

@model uatlab.ViewModels.BookingRequirementsViewModel 
.... 
@using (Html.BeginForm()) // Not sure why you post to a method with a different name 
{ 
    .... 
    @Html.HiddenFor(m => m.StoreID) 
    @Html.EditorFor(m => m.StoreAssets, new { actionList = Model.ActionList }) 
    .... 
} 

在控制器

public ActionResult Booking(int id) 
{ 
    .... 
    var model = new BookingRequirementsViewModel 
    { 
    BookingID = booking.ID, 
    StoreID = booking.StoreID, 
    Assets = myBag.Assets.Select(a => new AssetShort() 
    { 
     AssetID = a.ID, 
     SelectedAction = a.SelectedAction, // assign this if you want a selected option, otherwise the "--Please select--" option will be selected 
     .... 
    }) 
    }; 
    ConfigureViewModel(model); // Assign select list 
    return View(model); 
} 

而且一個單獨的方法來生成SelectList因此如果您返回視圖,則需要在GET方法中調用它,並在POST方法中再次調用它。注意使用的DropDownListFor()過載以生成選項標籤(空值)如上,並且沒有點設置Selected屬性(的SelectedAction值確定什麼被選擇時,沒有此)

private ConfigureViewModel(BookingRequirementsViewModel model) 
{ 
    model.ActionList = new[] 
    { 
    new SelectListItem { Value = "1", Text = "Add"}, 
    .... 
    new SelectListItem { Value = "5", Text = "Downgrade"} 
    }; 
} 

和POST

public ActionResult Booking(BookingRequirementsViewModel model) 
{ 
    if (!ModelState.IsValid) 
    { 
    ConfigureViewModel(model); // Re-assign select list 
    return View(model); 
    } 
    // save and redirect 
} 

我建議也正在與[Required]屬性SelectedAction爲空的,所以你得到的客戶端和服務器端驗證

public class AssetShort 
{ 
    public int AssetID { get; set; } 
    .... 
    [Required] 
    public int? SelectedAction { get; set; } 
} 
+0

Stephen 請問一個問題... 預訂控制器中用於填寫BookingRequirementsModel模型: SelectedAction = a.SelectedAction, 這看起來像我需要Assets模型中的SelectedAction,我目前還沒有。 是嗎? 問候 – 2014-12-19 09:21:39

+0

我只是假設你有它。如果你實際上沒有將所選選項的值保存到數據庫中,那麼我想你不需要它,但是在那種情況下,它在'AssetShort'中的實際用途是什麼? – 2014-12-19 09:27:53

+0

謝謝,讓它工作。 – 2014-12-19 10:15:04

相關問題