2013-09-25 107 views
4

我正在一個管理面板,將允許用戶添加一個或許多其他用戶。有一個文本區域,管理員可以在其中輸入要添加到應用程序的一個或多個用戶ID,該用戶ID與就業過程中分配的用戶ID相對應。提交時,應用程序從包含所有員工的數據庫中提取姓名,電子郵件等,並將其顯示在屏幕上進行驗證。屏幕上還包含一些用於分配一些權限的複選框,如CanWriteIsAdmin模型綁定與多個實體

查看

using (Html.BeginForm()) 
     { 
      <table> 
       <tr> 
        <th> 
        </th> 
        <th> 
         @Html.DisplayNameFor(model => model.User.First().ID) 
        </th> 
        <th> 
         @Html.DisplayNameFor(model => model.User.First().Name) 
        </th> 
        <th> 
         @Html.DisplayNameFor(model => model.User.First().Email) 
        </th> 
        <th> 
         @Html.DisplayNameFor(model => model.User.First().CanWrite) 
        </th> 
        <th> 
         @Html.DisplayNameFor(model => model.User.First().IsAdmin) 
        </th> 
       </tr> 

       @foreach (var item in Model.User) 
       { 
        <tr> 
         <td> 
          <input type="checkbox" name="id" value="@item.ID" checked=checked/> 
         </td> 
         <td> 
          @Html.DisplayFor(modelItem => item.ID) 
         </td> 
         <td> 
          @Html.DisplayFor(modelItem => item.Name) 
         </td> 
         <td> 
          @Html.DisplayFor(modelItem => item.Email) 
         </td> 
         <td> 
          @Html.CheckBoxFor(modelItem => item.CanWrite) 
         </td> 
         <td> 
          @Html.CheckBoxFor(modelItem => item.IsAdmin) 
         </td> 
        </tr> 
       } 

      </table> 
      <input type="submit" /> 
     } 

注:之所以用名ID複選框是給不添加用戶的能力,一旦名稱等信息已被提取,例如,一個用戶你並不意味着將意外添加到ID列表中。

型號

public class User 
{ 
    public int ID { set; get; } 
    public string Name { set; get; } 
    public bool IsAdmin { set; get; } 
    public bool CanWrite { set; get; } 
    public string Email{ set; get; } 

} 

控制器

[HttpPost] 
public ActionResult Create(IEnumerable<User> model) 
{ 
    //With this code, model shows up as null 
} 

在單用戶的情況下,我知道我可以使用User model在我的控制器動作的參數。如何調整此代碼以便一次添加多個用戶?這甚至有可能嗎?

回答

1

你在正確的軌道上,傑夫。你只需要擴展你有一點點。

首先,您的模型爲null的原因是您的操作是因爲輸入字段在表單上的命名方式。您的油田是在沿着這一行渲染:

<input id="item_CanWrite" name="item.CanWrite" type="checkbox" value="true" /> 
<input name="item.CanWrite" type="hidden" value="false" /> 

注意nameitem.CanWrite。這裏的問題在於,因爲你循環了模型中的所有用戶,所以實質上給所有輸入字段賦予相同的名稱。這可以防止MVC能夠建模綁定到POST數據,因爲它無法區分每個User

爲了解決這個問題,你需要你的電話更改爲Html.DisplayFor爲了讓MVC每個User過程作爲一個獨立的實體,從而使設置字段的每個User的按順序命名。這允許模型聯編程序正確綁定到這些字段。像這樣:

@for (int i = 0; i < Model.Count(); i++) 
{ 
    <tr> 
     <td> 
      <input type="checkbox" name="id" value="@Model[i].ID" checked=checked/> 
     </td> 
     <td> 
      @Html.DisplayFor(m => m[i].ID) 
     </td> 
     <td> 
      @Html.DisplayFor(m => m[i].Name) 
     </td> 
     <td> 
      @Html.DisplayFor(m => m[i].Email) 
     </td> 
     <td> 
      @Html.CheckBoxFor(m => m[i].CanWrite) 
     </td> 
     <td> 
      @Html.CheckBoxFor(m => m[i].IsAdmin) 
     </td> 
    </tr> 
} 

如果您檢查這些領域現在是如何呈現爲HTML,你會看到他們這個樣子:

<input checked="checked" data-val="true" data-val-required="The CanWrite field is required." name="[0].CanWrite" type="checkbox" value="true" /> 
<input name="[0].CanWrite" type="hidden" value="false" /> 
<input checked="checked" data-val="true" data-val-required="The CanWrite field is required." name="[1].CanWrite" type="checkbox" value="true" /> 
<input name="[1].CanWrite" type="hidden" value="false" /> 

正如你所看到的,每個User都有自己單獨的指數。我用了一個簡單的測試設置與下面的控制器方法,它拿起正確的記錄數在我的測試模型:

[HttpPost] 
public ActionResult Index(IEnumerable<User> model) 
{ 
    // Process your data. 

    return View(model); 
} 

不過,我想在這裏提出一個進一步的改進,以去除在你看來的邏輯。要做到這一點,我們可以使用DisplayTemplates,而不是循環:

  1. 創建視圖的當前文件夾內的文件夾DisplayTemplates(例如,如果你的觀點是Home\Index.cshtml,創建文件夾Home\DisplayTemplates)。
  2. 在該目錄中創建一個與您的模型匹配的名稱的強類型視圖(即在這種情況下該視圖將被稱爲User.cshtml)。
  3. 在視圖中放置重複的邏輯。

您的模板現在應該是這個樣子(不包括對無論您User模型所在的命名空間):現在

@model User 

<tr> 
    <td> 
     <input type="checkbox" name="id" value="@Model.ID" checked=checked/> 
    </td> 
    <td> 
     @Html.DisplayFor(m => m.ID) 
    </td> 
    <td> 
     @Html.DisplayFor(m => m.Name) 
    </td> 
    <td> 
     @Html.DisplayFor(m => m.Email) 
    </td> 
    <td> 
     @Html.CheckBoxFor(m => m.CanWrite) 
    </td> 
    <td> 
     @Html.CheckBoxFor(m => m.IsAdmin) 
    </td> 
</tr> 

,在原來的看法,你可以用這個代替所有的循環:

@using (Html.BeginForm()) 
{ 
    <table> 
     @Html.DisplayForModel() 
    </table> 
    <input type="submit" value="Submit" /> 
} 

如果您想了解更多關於綁定到集合,請參閱an answer我另一個問題提供。

1

我只是開始ASP.NET MVC,但我想你只需要創建一個視圖模型類,它有一個IEnumerable<User>類型的屬性,用於存儲你的用戶集合。然後將其傳遞給您的視圖並返回到您的POST處理程序。

1

嘗試這樣:

型號

public class Employee 
{ 
    public IEnumerable<User> Employees { set; get; } 
} 

public class User 
{ 
    public int ID { set; get; } 
    public string Name { set; get; } 
    public bool IsAdmin { set; get; } 
    public bool CanWrite { set; get; } 
    public string Email{ set; get; } 
} 

查看

@model Employee 

@using(Html.BeginForm() 
{ 
    // build HTML table, not much different from yours 
} 

控制器

[HttpPost] 
public ActionResult Create(Employee model) 
{ 
    // model will have an IEnumerable property with the User info 
} 
+0

正是我的意思。好例子。 – meilke