2012-01-05 1 views
0

Я использую MVC3 с бритвой, и я хочу сделать регистрационную форму, где я могу выбрать роль с выпадающим списком .Регистрационная форма с ролями MVC3, Ошибка: элемент ViewData имеет тип «system.sting» должен быть «IEnumerable <selectlistitem>

я получаю роли в списке и все это, но когда я нажимаю отправить я получаю:.

ViewData элемента, который имеет ключ «роль» типа System.String но должна быть типа IEnumerable<SelectListItem>

Мой код

Модель:

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

Мой контроллер:

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] 
    public ActionResult Register(RegisterModel model) 
    { 
     if (ModelState.IsValid) 
     { 
      // Attempt to register the user 
      MembershipCreateStatus createStatus; 
      Membership.CreateUser(model.UserName, model.Password, model.Email, null, null, true, null, out createStatus); 

      if (createStatus == MembershipCreateStatus.Success) 
      { 
       Roles.AddUserToRole(model.UserName, model.Role); 
       return RedirectToAction("Index", "Home"); 
      } 
      else 
      { 
       ModelState.AddModelError("", ErrorCodeToString(createStatus)); 
      } 
     } 

     // If we got this far, something failed, redisplay form 
     return View(model); 
    } 

Мое мнение:

<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.ValidationMessageFor(m => m.Role) 

     </div> 

Когда я использовать отладчик, чтобы проверить мой код, в контроллере, когда я смотрю на модель параметров и на model.Role Я вижу правую строку. Кто-нибудь знает какое-либо решение моей проблемы?

+0

Я только что попробовал этот код (с некоторыми изменениями, чтобы заменить процедуру GetAllRoles, добавить кнопку отправки в форму и удалить строки членства из сообщения), и она отлично работала. В конце вы говорите, что это работает в режиме отладки, но не когда вы запускаете его в выпуске? – Dangerous

+0

Нет, он не работает в режиме отладки, но модель получает правильную строку для него, но когда я делаю model.Role, я получаю сообщение об ошибке. – TobiasW

+0

Итак, вы говорите, что вы можете запустить код, и он отобразит выпадающее поле в окне реестра? Из того, что я собираю, вы можете выбрать значение в раскрывающемся списке, нажмите «Отправить» и перерыв в начале вашего действия по почте. Вы можете видеть, что модель содержит выбранное значение? Итак, если вы продолжаете выполнять код после этого разрыва, возникает ошибка? Это верно? – Dangerous

ответ

3

В вашем действии POST вы не заселив roleList в ViewBag в том случае, когда вы снова отобразить вид:

... 
// If we got this far, something failed, redisplay form 

// but before redisplaying the form ensure that we have populated the 
// ViewBag.roleList that this form depends on 
ViewBag.roleList = ... same stuff as your GET action 
return View(model); 

Это, как говорится, я бы рекомендовал вам избавиться от ViewBag и добавить RoleList недвижимость к модели вида:

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

    public IEnumerable<SelectListItem> RoleList 
    { 
     get 
     { 
      return Roles 
       .GetAllRoles() 
       .Select(x => new SelectListItem 
       { 
        Value = x, 
        Text = x 
       }) 
       .ToList(); 
     } 
    } 
} 

, а затем:

public ActionResult Register() 
{ 
    var model = new RegisterModel(); 
    return View(model); 
} 

[HttpPost] 
public ActionResult Register(RegisterModel model) 
{ 
    if (ModelState.IsValid) 
    { 
     // Attempt to register the user 
     MembershipCreateStatus createStatus; 
     Membership.CreateUser(model.UserName, model.Password, model.Email, null, null, true, null, out createStatus); 
     if (createStatus == MembershipCreateStatus.Success) 
     { 
      Roles.AddUserToRole(model.UserName, model.Role); 
      return RedirectToAction("Index", "Home"); 
     } 
     else 
     { 
      ModelState.AddModelError("", ErrorCodeToString(createStatus)); 
     } 
    } 

    // If we got this far, something failed, redisplay form 
    return View(model); 
} 
не

и в вашем сильно типизированной:

@model RegisterModel 
... 

<div class="editor-label"> 
    @Html.LabelFor(m => m.Role) 
</div> 
<div class="editor-field"> 
    @Html.DropDownListFor(m => m.Role, Model.RoleList) 
    @Html.ValidationMessageFor(m => m.Role) 
</div> 

Нет больше ViewBag => нет проблем.

+1

Спасибо, что помогли, но я должен был использовать foreach для заполнения RoleList, .select дал мне ошибку. – TobiasW

+0

Хотя я на 4 года позади .... Я реализовал вышеуказанный код и получил ошибку «Не удалось подключиться к БД» – singhswat