C# mvc3编辑表单中的下拉列表

C# mvc3编辑表单中的下拉列表,c#,asp.net-mvc-3,razor,html-helper,C#,Asp.net Mvc 3,Razor,Html Helper,这可能很简单,但我似乎无法独自解决。 我创建了一个简单的db和实体模型,如下所示 我正在尝试创建一个创建表单,允许我添加新订单。我一共有3个表,所以我要做的是有一个表单,允许用户输入订单日期,还有一个下拉列表,允许我从产品表中选择产品 我希望能够创建一个添加或编辑视图,允许我将OrderDate插入OrderTable,并将OrderID和所选ProductID插入OrderProduct 我需要在这里执行哪些步骤 我已经创建了一个OrderController并勾选了“添加操作”,然后添加了

这可能很简单,但我似乎无法独自解决。 我创建了一个简单的db和实体模型,如下所示

我正在尝试创建一个创建表单,允许我添加新订单。我一共有3个表,所以我要做的是有一个表单,允许用户输入订单日期,还有一个下拉列表,允许我从产品表中选择产品

我希望能够创建一个添加或编辑视图,允许我将OrderDate插入OrderTable,并将OrderID和所选ProductID插入OrderProduct

我需要在这里执行哪些步骤

我已经创建了一个OrderController并勾选了“添加操作”,然后添加了一个创建视图,如下所示

@model Test.OrderProduct

@{
    ViewBag.Title = "Create2";
}

    <h2>Create2</h2>

<script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>

@using (Html.BeginForm()) {
    @Html.ValidationSummary(true)
    <fieldset>
        <legend>OrderProduct</legend>

        <div class="editor-label">
            @Html.LabelFor(model => model.OrderID)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.OrderID)
            @Html.ValidationMessageFor(model => model.OrderID)
        </div>

        <div class="editor-label">
            @Html.LabelFor(model => model.ProductID)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.ProductID)
            @Html.ValidationMessageFor(model => model.ProductID)
        </div>

        <p>
            <input type="submit" value="Create" />
        </p>
    </fieldset>
}

<div>
    @Html.ActionLink("Back to List", "Index")
</div>
我的问题是,

1.如何将ProductID文本框替换为从Product填充的下拉列表 2.如何从FormCollection获取数据?我只想到了一个foreach,但我不知道如何获得强类型名称

对新手的任何帮助都会很有帮助


谢谢大家!

在过去的一天左右,我也一直在努力解决这个问题。我将分享我有限的知识,希望它能帮助别人

请注意,我使用带有预填充列表的单例来保持示例应用程序的小规模(即没有EF或DB交互)

要显示ProductList,您需要有一个包含ProductList的ViewBag或ViewData项。 您可以在控制器中通过以下方式进行设置

    ViewData["ProductList"] = new SelectList(Models.MVCProduct.Instance.ProductList, "Id", "Name", 1);
然后将视图更新为类似以下内容:

    <div class="editor-field">@Html.DropDownList("ProductList")</div>
@Html.DropDownList(“产品列表”)
对于Post/Create/Update步骤,您需要查看FormCollection以获得结果。在阅读其他帖子时,听起来这里曾经有一个bug,但现在已经修复了,所以请确保您拥有最新的bug。例如,我有一个产品的下拉列表,所以我只需获取所选Id,然后在列表中搜索该产品

    [HttpPost]
    public ActionResult Create(FormCollection form )//Models.MVCOrder newOrder)
    {

        MVC.Models.MVCOrder ord = Models.MVCOrder.Instance.CreateBlankOrder();
        //Update order with simple types (e.g. Quantity)
        if (TryUpdateModel<MVC.Models.MVCOrder>(ord, form.ToValueProvider()))
        {
            ord.Product = Models.MVCProduct.Instance.ProductList.Find(p => p.Id == int.Parse(form.GetValue("ProductList").AttemptedValue));
            ord.Attribute = Models.MVCAttribute.Instance.AttributeList.Find(a => a.Id == int.Parse(form.GetValue("attributeId").AttemptedValue));
            UpdateModel(ord);
            return RedirectToAction("Index");
        }
        else
        {
            return View(ord);
        }
    }
[HttpPost]
公共操作结果创建(FormCollection表单)//Models.MVCOrder newOrder)
{
MVC.Models.MVCOrder ord=Models.MVCOrder.Instance.CreateBlankOrder();
//使用简单类型(例如数量)更新订单
if(TryUpdateModel(ord,form.ToValueProvider()))
{
ord.Product=Models.MVCProduct.Instance.ProductList.Find(p=>p.Id==int.Parse(form.GetValue(“ProductList”).AttemptedValue));
ord.Attribute=Models.MVCAttribute.Instance.AttributeList.Find(a=>a.Id==int.Parse(form.GetValue(“attributeId”).AttemptedValue));
更新模型(ord);
返回操作(“索引”);
}
其他的
{
返回视图(ord);
}
}

我最近几天才开始研究MVC3,因此如果您能提供任何关于改进上述内容的建议,我将不胜感激。

首先,不要绑定到订单实体。永远不要绑定到EF对象,始终尝试使用视图模型。使视图的生活更简单,这就是本文的目标

因此,请使用如下视图模型:

public class CreateOrderViewModel
{
   public int OrderId { get; set; }
   public DateTime OrderDate { get; set; }
   public int SelectedProductId { get; set; }
   public IEnumerable<SelectListItem> Products { get; set; }
}
然后呈现产品列表:(基本HTML除外)

我唯一不知道怎么做的就是绑定到DateTime字段。我猜您可能需要一个扩展方法(HTML助手),用于呈现日期选择器之类的东西。对于此视图(创建新订单),只需默认设置为
DateTime.Now

现在,进入
[HttpPost]
控制器操作:

[HttpGet]
public ActionResult Create()
{
   var model = new CreateOrderViewModel
   {
      Products = db.Products
                   .ToList() // this will fire a query, basically SELECT * FROM Products
                   .Select(x => new SelectListItem
                    {
                       Text = x.ProductName,
                       Value = x.ProductId
                    });
   };

   return View(model);
}
[HttpPost]
public ActionResult Create(CreateOrderViewModel model)
{
   try
   {
      // TODO: this manual stitching should be replaced with AutoMapper
      var newOrder = new Order
      {
         OrderDate = DateTime.Now,
         OrderProduct = new OrderProduct
         {
            ProductId = SelectedProductId
         }
      };

      db.Orders.AddObject(newOrder);
      return RedirectToAction("Index");
   }
   catch
   {
      return View();
   }
}
现在,我也认为你的EF模型需要改进

对我来说(用英语来说),一个产品可以有很多订单,一个订单可以有很多产品。

所以,它应该是多对多的。目前它是一个1-1的冗余联接表。你是从数据库生成的吗?如果是这样,您的数据库可能需要工作

您应该在订单实体上有一个名为产品的导航属性,该属性引用了产品的集合,通过对多对多中的联接表进行无提示联接而成为可能


这也意味着你不再有DropDownList,而是一个多选DropDownList。

谢谢Craig。您发布MVC的几天(截至发帖时)解决了我几天来试图从DropDownListFor获取所选值的问题

我在Create视图中获取DDLF的选定值没有问题,但是Edit视图是一个完全不同的问题——我所做的任何尝试都无法在帖子中获取选定值。我注意到所选的值潜伏在ModelState的AttemptedValue中,所以Google博士把我介绍到这里

我有这个想法

    @Html.DropDownList(model => model.ContentKeyID, Model.ContentKeys, Model.ContentKeyName)
其中ContentKeys是通过ViewModel从DB填充的选择列表,ContentKeyName是当前选择的名称

wierd的事情是,我在视图上以相同的方式填充了另一个DDL。这个有效。为什么,我不知道。这是表单上的第二个DDL,但我看不出有什么不同

我在其他地方读到,可能是我使用了guid作为Id,但这似乎没有什么区别——我改为Int32,但我不认为我必须这样做——我认为是enum不同意DDLF。空值看起来也没有什么区别

现在,我已经将表单集合添加到PostActionResult中,并使用

-看法

-财务主任(职位)


一切都很好,我可以继续做更令人兴奋的事情。为什么最简单的事情能让你坚持这么久?

有趣的是,这正是我目前的问题,但这里没有人回答。我原以为MVC迷们会在2秒钟内跳到这个上面。在上面的
[HttpGet]
方法中,我不断收到一个错误,告诉我我不能隐式地将int转换为
value=x.id
位的字符串!我添加了一个
ToString()
,但是我得到了这个错误:错误7无法即时消息
[HttpPost]
public ActionResult Create(CreateOrderViewModel model)
{
   try
   {
      // TODO: this manual stitching should be replaced with AutoMapper
      var newOrder = new Order
      {
         OrderDate = DateTime.Now,
         OrderProduct = new OrderProduct
         {
            ProductId = SelectedProductId
         }
      };

      db.Orders.AddObject(newOrder);
      return RedirectToAction("Index");
   }
   catch
   {
      return View();
   }
}
    @Html.DropDownList(model => model.ContentKeyID, Model.ContentKeys, Model.ContentKeyName)
    @Html.DropDownList("ContentKey", Model.ContentKeys)
    contentKeyId = int.Parse(form.GetValue("ContentKey").AttemptedValue);