0

あまりにも長い間これにいました!次の問題に関するアドバイス...

追加されたコード:

モデル:AccountModels.cs

[Required]
[Display(Name = "Select role: ")]
public String Role { get; set; }

コントローラー:AccountController.cs

  // GET: /Account/Register

public ActionResult Register()
{ 
    List<SelectListItem> list = new List<SelectListItem>();
    SelectListItem item; 
    foreach (String role in Roles.GetAllRoles()) 
    { 
        item = new SelectListItem { Text = role, Value = role }; 
        list.Add(item); 
    }
    ViewBag.roleList = (IEnumerable<SelectListItem>)list;
    return View();
}

[HTTpPost]にも

if (createStatus == MembershipCreateStatus.Success)
{
    Roles.AddUserToRole(model.UserName, model.Role);

    MailClient.SendWelcome(model.Email);
    FormsAuthentication.SetAuthCookie(model.UserName, false /* createPersistentCookie */);
    return RedirectToAction("Create", "Customers");
}

表示:Register.cshtml

<div class="editor-label">      
    @Html.LabelFor(m => m.Role)  
</div>      
<div class="editor-field">
    @Html.DropDownListFor(m => m.Role, ViewBag.roleList as IEnumerable<SelectListItem>)

コードは機能し、ユーザーが役割を選択できるようにしますが、ユーザーが新しいアカウントを作成するときに検証ルールに違反すると、崩壊します。

例:パスワードが通常一致しない場合、検証が開始されますが、新しいコードが追加されたため、アプリケーションがクラッシュします。

エラーを作成するコード:

@Html.DropDownListFor(m => m.Role, ViewBag.roleList as IEnumerable<SelectListItem>)

エラーコード

キー「Role」を持つViewDataアイテムのタイプは「System.String」ですが、タイプは「IEnumerable」である必要があります。

4

1 に答える 1

3

検証が失敗した HttpPost アクションメソッドでこの問題が発生していると思います。HttpPostreturn View()アクションメソッドにステートメントがあると思います。ビューを再度返すと、ViewData は null になります。そのため、ドロップダウンのためにデータを再度リロードする必要があります

public ActionResult Register()
{
 //If validation ok, save
 if (createStatus == MembershipCreateStatus.Success)
 {
   //dio stuff
 }
 else
 { 
    List<SelectListItem> list = new List<SelectListItem>();
    SelectListItem item; 
    foreach (String role in Roles.GetAllRoles()) 
    { 
        item = new SelectListItem { Text = role, Value = role }; 
        list.Add(item); 
    }
    ViewBag.roleList = (IEnumerable<SelectListItem>)list; 
    return View();
 }
}

理想的には、ViewData を使用してこれを処理することはありません。これを処理する ViewModel を用意します。

public class RegisterViewModel
{
 public string FirstName { set;get;} 
 public IEnumerable<SelectListItem> Roles { get; set; }
 public int SelectedRoleId { get; set; }
}

get アクション呼び出しで、ViewModel をビューに戻します。

public ActionResult Register()
{
  RegisterViewModel objViewModel=new RegisterViewModel();
  objViewModel.Roles=GetAllRolesAs();  // returns the list of roles to this property
  return View(objViewModel);
}

ビューを強く型付けする

@model RegisterViewModel
@using (Html.BeginForm())
{
   @Html.TextBoxFor(m => m.FirstName)

   @Html.DropDownListFor(x => x.SelectedRoleId,new SelectList(Model.Roles , "Value","Text"),   "Select Role")
  <input type="submit" value="Save" />
}

HttpPostAction で、この ViewModel オブジェクトをパラメーターとして受け取ります

[HttpPost]
public ActionResult Register(RegisterViewModel objVM)
{
  if(ModelState.IsValid)
  {
    //Check your custom validation also
    if (createStatus == MembershipCreateStatus.Success)
    {
          //Save and then Redirect

    }
    else
    {
      objVM.Roles=GetAllRolesAs(); // get the list of roles here again because HTTP is stateless
    }
  }  
 return View(objVM);
}
于 2012-04-08T02:37:27.747 に答える