MVC中的DropdownLists

时间:2012-12-09 16:54:18

标签: c# asp.net-mvc entity-framework

我试图在MVC中使用DropdownlistFor将对象添加到我的数据库中。我可以很好地填充下拉列表,但是当我发布表单时,我得到一个错误,因为下拉列表的ID(这是Team对象的外键)被填充但不是实际值。这是我的代码:

    [HttpGet]
        public ActionResult FixtureAdd()
        {
            IEnumerable<SelectListItem> teams = _repository.GetTeams()
              .Select(c => new SelectListItem
              {
                  Value = c.TeamId.ToString(),
                  Text = c.TeamName
              }).ToList();

            IEnumerable<SelectListItem> weeks = _repository.GetWeeks()
              .Select(c => new SelectListItem
              {
                  Value = c.ToString(),
                  Text = c.ToString()
              }).ToList();

            ViewBag.Teams = new SelectList(teams, "Value", "Text");
            ViewBag.Weeks = new SelectList(weeks, "Value", "Text");

            string apiUri = Url.HttpRouteUrl("DefaultApi", new { controller = "fixture", });
            ViewBag.ApiUrl = new Uri(Request.Url, apiUri).AbsoluteUri.ToString();

            return View();
        }

        [HttpPost]
        public ActionResult FixtureAdd(Fixture fx)
        {
            if (ModelState.IsValid)
            {
                try
                {
                     //TODO: Add insert logic here
                    _repository.AddFixture(fx);
                    return RedirectToAction("FixtureAdd");
                }
                catch (DbEntityValidationException dbEx)
                {
                    foreach (var validationErrors in dbEx.EntityValidationErrors)
                    {
                        foreach (var validationError in validationErrors.ValidationErrors)
                        {
                            Trace.TraceInformation("Property: {0} Error: {1}", validationError.PropertyName, validationError.ErrorMessage);
                        }
                    }

                    return View(fx);
                }   
            }
            else
            {
                IEnumerable<SelectListItem> teams = _repository.GetTeams()
                  .Select(c => new SelectListItem
                  {
                      Value = c.TeamId.ToString(),
                      Text = c.TeamName
                  }).ToList();

                ViewBag.Teams = new SelectList(teams, "Value", "Text");

                IEnumerable<SelectListItem> weeks = _repository.GetWeeks()
                  .Select(c => new SelectListItem
                  {
                      Value = c.ToString(),
                      Text = c.ToString()
                  }).ToList();

                ViewBag.Weeks = new SelectList(teams, "Value", "Text");

                return View(fx);
            }
        }

    public IEnumerable<Team> GetTeams()
        {
            return _db.Teams.ToArray();
        }

public partial class Fixture
    {
        public int FixtureId { get; set; }
        public string Season { get; set; }
        public byte Week { get; set; }

        //foreign key
        public int AwayTeamId { get; set; }
        //navigation properties
        public virtual Team AwayTeam { get; set; }

        //foreign key
        public int HomeTeamId { get; set; }
        //navigation properties
        public virtual Team HomeTeam { get; set; }

        public byte? AwayTeamScore { get; set; }
        public byte? HomeTeamScore { get; set; }
    }

@using (Html.BeginForm()) {
    @Html.ValidationSummary(true)

    <fieldset>
        <legend>Fixture</legend>

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

        <div class="editor-label">
            @Html.LabelFor(model => model.Week)
        </div>
        <div class="editor-field">
            @Html.DropDownListFor(model => model.Week, (SelectList)ViewBag.Weeks)
        </div>

        <div class="editor-label">
            @Html.LabelFor(model => model.AwayTeam.TeamId)
        </div>
        <div class="editor-field">
            @Html.DropDownListFor(model => model.AwayTeam.TeamId, (SelectList)ViewBag.Teams)
            @Html.ValidationMessageFor(model => model.AwayTeam.TeamId)
        </div>
        <div class="editor-label">
            @Html.LabelFor(model => model.AwayTeamScore)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.AwayTeamScore)
            @Html.ValidationMessageFor(model => model.AwayTeamScore)
        </div>
        <div class="editor-label">
            @Html.LabelFor(model => model.HomeTeam.TeamId)
        </div>
        <div class="editor-field">
            @Html.DropDownListFor(model => model.HomeTeam.TeamId, (SelectList)ViewBag.Teams)
            @Html.ValidationMessageFor(model => model.HomeTeam.TeamId)
        </div>
        <div class="editor-label">
            @Html.LabelFor(model => model.HomeTeamScore)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.HomeTeamScore)
            @Html.ValidationMessageFor(model => model.HomeTeamScore)
        </div>

        <p>
            <button data-bind='click: save'>Add fixture</button>
        </p>
    </fieldset>
}

TeamId外键字段填充在帖子中,但TeamName不填充。有什么想法吗?这是我第一次尝试这个,所以我希望我可能会犯这个错误。

1 个答案:

答案 0 :(得分:0)

与传统ASP不同,MVC重量轻,不会将所有这些对象存储在隐藏字段中。也就是说,如果您有以下内容:

class Customer {
  public Int32 Id { get; set; }
  public String Name { get; set; }
}

在普通的ASP中,您可以将这些对象的集合映射到下拉列表,在帖子后面,您将获得结果中引用的原始对象。 MVC不会以这种方式工作,因为它不再存储这些对象。因此,如果您需要该目标对象,则需要使用传递的ID并重新检索所需的结果。

为您的模型上的CustomerId属性显示以下EditorTemplate:

@model Int32
@Html.DropDownListFor(x => x, new SelectList(
  Customers.GetAllCustomers().Select(y => new SelectListItem {
    Value = y.Id,
    Text = y.Name,
    Selected = Model == y.Id
  })
);

当然:

@Html.EditorFor(x => x.CustomerId) @* Use above EditorTemplate *@

然后在你的提交动作中:

[HttpPost]
public ActionResult(MyViewModel model)
{
  if (ModelState.IsValid)
  {
    // ID was passed, re-fetch the customer based on selected id
    Customer customer = Customers.GetById(model.CustomerId)
    /* ... */
  }
  /* ... */
  return View();
}