1

我正在开发一个小应用程序,以便更好地理解MVC3和Razor的工作方式。我使用的是MVC3,所有代码都是自动生成的(通过T4的dbContext,通过添加控制器的控制器,来自EDMX模型的Databese ...)。DropDownlistFor使用MVC3创建新实体

在我的模型我有这个简单的模型: http://i.stack.imgur.com/nyqu4.png

public partial class Application 
{ 
    public int Id { get; set; } 
    public string Name { get; set; } 

    public virtual ApplicationType ApplicationType { get; set; } 
} 

public partial class ApplicationType 
{ 
    public int Id { get; set; } 
    public string Type { get; set; } 
} 

正如你所看到的,ApplicationType基本上是一个枚举(耻辱,EF 4对枚举不支持)。所以,在我的ApplicationController我有这样的:

public ActionResult Create() 
{ 
    ViewBag.AppTypes = new SelectList(db.ApplicationTypes.OrderBy(c => c.Type), "Id", "Type"); 
    return View(); 
} 

[HttpPost] 
public ActionResult Create(Application application) 
{ 
    if (ModelState.IsValid) 
    { 
     db.Applications.Add(application); 
     db.SaveChanges(); 
     return RedirectToAction("Index"); 
    } 

    return View(application); 
} 

在我看来:

@Html.DropDownListFor(model => model.ApplicationType.Id, (SelectList)ViewBag.AppTypes, "Choose...") 

现在我面临两个问题:未填充

1)ApplicationType:

As @ Html.DropDownListFor只呈现一个简单的选择,它填充ID,但不填充Type属性,如下所示(对不起,我可以' T型柱图像作为我是新来的):

http://i.stack.imgur.com/96IR1.png

你可以看到,ID是确定的图片,但类型是空的。

我在做什么错了?

2)复制数据

的第二个问题是,如果我在调试期间手动填写Type属性(模拟正确的工作流的情况),ApplicationType被复制到数据库中,而不是仅参照一个旧的注册表。

那么,我怎样才能使@ Html.DropDownListFor引用一个先前的现有项目,而不是创建一个新的?

感谢您的帮助!

回答

0

我相信你所犯的错误是在视图中使用你的域模型,并假设在后期整个模型应该完全绑定并准备存储在数据库中。虽然可以在视图中使用域模型,但最好单独创建查看模型

例如:

public class ApplicationViewModel 
{ 
    public int Id { get; set; } 
    public string Name { get; set; } 

    public SelectList ApplicationTypeList { get; set; } 
    public string ApplicationTypeId { get; set; } 
} 

在你看来:

@Html.DropDownListFor(model => model.ApplicationTypeId, Model.ApplicationTypeList , "Choose...") 

在你的控制器

[HttpPost] 
public ActionResult Create(ApplicationViewModel model) 
{ 
    if (ModelState.IsValid) 
    { 
     Application application = new Application() 
     { 
      Id = model.Id, 
      Name = model.Name, 
      ApplicationType = db.ApplicationTypes 
       .First(a => a.Id == model.ApplicationTypeId); 

     }; 
     db.Applications.Add(application); 
     db.SaveChanges(); 
     return RedirectToAction("Index"); 
    } 

    return View(model); 
} 

然后,您可以验证您的视图模型的ApplicationTypeId对应于实际应用键入模型状态验证的一部分。您可以使用AutoMapper加快将视图模型转换为域模型的过程。

+0

令人惊叹!所以我的问题不在于代码本身,而在于MVC如何工作。这很容易理解和遵循。 – 2012-04-26 17:45:02

+0

顺便说一句,我使用的是不同的方法: 公共的ActionResult创建(应用程序) { 如果(ModelState.IsValid) { INT appTypeID = Convert.ToInt32(ModelState中[ “ApplicationType.Id”]值。 AttemptedValue); application.ApplicationType = db.ApplicationTypes.Single(s => s.Id == appTypeID); 我对此解决方案感到不满 – 2012-04-26 17:47:58

0

你试过:

@Html.DropDownListFor(model => model.ApplicationType.Id, m => m.ApplicationType.Type, "Choose...") 

注意的第二个参数的变化。

+0

谢谢@ mirezus!不幸的是,它不起作用,因为第二个参数需要一个,而不是lambda。 – 2012-04-26 11:31:40

+0

哦,没错。您通常可以将项目内联到selectlistitem中,即:new SelectListItem {Text = m.TextToUse,Data = m.DataToUse} – mirezus 2012-05-16 17:42:40