【问题标题】:DropDownlistFor Creating New Entity with MVC3DropDownlistFor 使用 MVC3 创建新实体
【发布时间】:2012-04-25 21:29:07
【问题描述】:

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

在我的模型中,我有这个简单的模型: 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:

由于@Html.DropDownListFor 仅呈现一个简单的选择,它会填充 ID,但不会填充 Type 属性,如下所示(抱歉,我是新来的,所以无法发布图片):

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

图中可以看到ID是ok的,但是Type是空的。

我做错了什么?

2) 重复数据

第二个问题是,如果我在调试期间手动填充 Type 属性(模拟正确的工作流场景),ApplicationType 会在数据库中被复制,而不是仅引用旧注册表。

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

感谢您的帮助!

【问题讨论】:

    标签: asp.net-mvc-3 entity-framework razor html.dropdownlistfor


    【解决方案1】:

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

    例如:

    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);
     }
    

    然后您可以验证您的 View Model 的 ApplicationTypeId 是否对应于您的模型状态验证的真实应用程序类型部分。您可以使用AutoMapper 加快将视图模型转换为域模型的过程。

    【讨论】:

    • 太棒了!所以我的问题不在于代码本身,而在于 MVC 的工作方式。这很容易理解和遵循。
    • 顺便说一句,我使用了不同的方法: public ActionResult Create(Application application) { if (ModelState.IsValid) { int appTypeID = Convert.ToInt32(ModelState["ApplicationType.Id"].Value.尝试值); application.ApplicationType = db.ApplicationTypes.Single(s => s.Id == appTypeID);我对这种解决方法感到不安......
    【解决方案2】:

    你试过了吗:

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

    注意第二个参数的变化。

    【讨论】:

    • 谢谢,@mirezus!不幸的是,它不起作用,因为第二个参数需要 ,而不是 lambda。
    • 哦,没错。您通常可以将项目包装到内联的 selectlistitem 中,即: new SelectListItem { Text= m.TextToUse , Data = m.DataToUse }
    猜你喜欢
    • 2011-09-08
    • 1970-01-01
    • 1970-01-01
    • 2011-06-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多