2012-08-01 136 views
2

我试图创建一个基本的注册表单,从一个下拉列表中接受一个状态的地址。我似乎无法从下拉菜单中将数据提取到包含状态对象的模型中。我试过创建一个自定义模型绑定器,如下所示。当我调试ModelState是有效的,但状态始终为空。模型绑定与ASP.NET MVC的内部嵌套模型

型号:

public class AccountInfo 
{ 
    public virtual Guid accoundID { get; set; } 
    public virtual string city { get; set; } 
    public virtual string email_address { get; set; } 
    public virtual string fax_number { get; set; } 
    public virtual string first_name { get; set; } 
    public virtual string last_name { get; set; } 
    public virtual string mailing_address { get; set; } 
    public virtual string phone_number { get; set; } 
    public virtual State state { get; set; } 
    public virtual string zip_code { get; set; } 
} 
public class State 
{ 
    public virtual int ID { get; set; } 
    public virtual string text { get; set; } 
    public virtual string value { get; set; } 
} 

模型绑定:

public class StateModelBinder : IModelBinder 
{ 
    private RepositoryDB Database; 
    public object BindModel(
     ControllerContext controllerContext, 
     ModelBindingContext bindingContext 
     ) 
    { 
     var key = bindingContext.ModelName + ".state"; 
     var value = bindingContext.ValueProvider.GetValue(key); 
     if (value == null) 
     { 
      return null; 
     } 
     var result = new State(); 
     Database = new RepositoryDB(ConfigurationManager. 
      ConnectionStrings["ConnectionString"].ConnectionString); 

     try 
     { 
      var query = from s in Database.States 
         where s.value == value.ToString() 
         select new State() 
         { 
          text = s.text, 
          ID = s.ID, 
          value = s.value 
         }; 
      result = (State)query.ToList().ElementAt(0);   
     } 
     catch (Exception ex) 
     { 
      bindingContext.ModelState.AddModelError(bindingContext.ModelName, ex.Message); 
      bindingContext.ModelState.SetModelValue(key, value); 
     } 


     return result; 
    } 

控制器:

[HttpPost] 
    public ActionResult Index(AccountInfo accountModel) 
    { 
     try 
     { 
      if (ModelState.IsValid) 
      { 
       Database.Account.Add(accountModel); 
       Database.SaveChanges(); 

       return Redirect(Url.Action("Success")); 
      } 
     } 
     catch (Exception ex) 
     { 
      ModelState.AddModelError(String.Empty, ex); 
     } 
     // invalid info - return with error message   
     //repop select lists 
     GetStates(); 
     return View(accountModel); 
    } 
public void GetStates() 
    { 
     IEnumerable<SelectListItem> states = from s in Database.States 
               select new SelectListItem 
               { 
                Text = s.text, 
                Value = s.value 
               }; 

     ViewBag.state = states.ToList(); 
    } 

查看:

@Html.LabelFor(model => model.state, "*State") 
@Html.DropDownListFor(model => model.state, (IEnumerable<SelectListItem>)ViewBag.state) 
+0

你在做什么?为什么要定制模型绑定为什么选择ViewBag?为什么不查看模型? – 2012-08-01 16:30:09

+0

我试图在AccountInfo类中存储“State”(如在邮件地址中)作为对象。我使用来自具有各种可能状态的数据库上的简单表的linq查询填充下拉列表。你能否演示如何使用视图模型而不是我的实现? – 2012-08-01 17:25:13

回答

3

这是你的问题:

@Html.DropDownListFor(model => model.state, (IEnumerable<SelectListItem>)ViewBag.state) 

绑定到model.State不能工作,因为这是一个复杂类型:

public class State 
{ 
    public virtual int ID { get; set; } 
    public virtual string text { get; set; } 
    public virtual string value { get; set; } 
} 

如果你想它的形式是要回发的唯一的事情就是所选下拉项目的值如“MN”(明尼苏达州)而不是全班。 (你没有为每个下拉列表项的值序列化一个“State”类,只是希望每个状态的主键)你需要让你的模型的状态是一个字符串或int,这取决于主键的类型是什么你的状态,像这样:

public class AccountInfo 
{ 
    //... 
    public virtual string/int State { get; set; } 
    //... 
} 

从那里,你可以重新滋润你的状态对象,如果你从一个国家的唯一标识符(这应该是被回发到服务器作为值喜欢字符串或int例如)

+0

好的,谢谢。 – 2012-08-01 17:33:06