使用标记帮助程序将下拉列表值保存到数据库ASP.net 5.0 MVC 6

时间:2016-02-25 13:45:07

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

我正在尝试使用MVC6和Entity Framework 7将我的下拉列表值保存到ASP.NET Web应用程序中的数据库,但值不保存。

我有两个名为费用的课程,当用户创建费用时,他们需要选择一个国家/地区。我填写了国家/地区下拉列表,但是当保存费用时,countryid没有保存到数据库中。

模型

public class Country
{        public int Countryid { get; set; }
        public string CountryCode { get; set; }
}

public class Expense
{
    public int ExpenseId { get; set; }

    [DisplayFormat(DataFormatString = "{0:dd/MM/yyyy}",
    ApplyFormatInEditMode = true)]
    public DateTime ExpenseDate { get; set; }
    public virtual Country Countryid { get; set; }

费用控制器

 private void PopulateCountriesDropDownList(object selectedCountry = null)
    {
        var list = _context.Countries.OrderBy(r => r.CountryCode).ToList().Select(rr =>

        new SelectListItem { Value = rr.Countryid.ToString(), Text = rr.CountryCode }).ToList();
        ViewBag.Countries = list;
    }
    // GET: Expenses/Create
    public IActionResult Create()
    {
        PopulateCountriesDropDownList();
                   return View();
    }

    // POST: Expenses/Create
    [HttpPost]
    [ValidateAntiForgeryToken]
    public IActionResult Create(Expense expense)
    {
        if (ModelState.IsValid)
        {
            _context.Expenses.Add(expense);
            _context.SaveChanges();
            return RedirectToAction("Index");
        }
        PopulateCountriesDropDownList(expense.Countryid);

        return View(expense);
    }

查看

 <div class="form-group">
        <label asp-for="Countryid" class="col-md-2 control-label"></label>
        <div class="col-md-10">
            <select asp-for="Countryid" class="form-control"asp-items=@ViewBag.Countries></select>
            <span asp-validation-for="Countryid" class="text-danger" />
        </div>
    </div>

1 个答案:

答案 0 :(得分:1)

首先,Expense模型中的Countryid属性是一个复杂类型(Country)。模型绑定器无法将发布的Countryid表单值映射到此Complex对象。

您应该将CountryId属性添加到Int

类型的Expense模型中
public class Expense
{
    public int ExpenseId { get; set; }

    [DisplayFormat(DataFormatString = "{0:dd/MM/yyyy}",
    ApplyFormatInEditMode = true)]
    public DateTime ExpenseDate { get; set; }
    public int CountryId { set;get;}
    public virtual Country Country { get; set; }    
}

虽然这样可以解决问题,但更好一点。干净的解决方案是使用视图模型在视图和操作方法之间传输数据。使用此方法,您的视图不会与ORM生成的实体类紧密耦合。

因此,为 视图创建一个视图模型,其中包含视图所需的属性

public class CreateExpenseVm
{
   public List<SelectListItem> Countries { set;get;}
   public int CountryId { set;get;}
   //Add other properties, if your view need them.
}

在您的GET操作中,您创建此类的对象,加载Countries集合属性并将其发送到您的视图。

public ActionResult Create()
{
   var vm=new CreateExpenseVm();
   vm.Countries = _context.Countries.OrderBy(r => r.CountryCode)
                       .Select(x=>new SelectListItem { Value=x.CountryId.ToString(),
                                                       Text=x.CountryCode}).ToList();
   return View(vm);
}

在您看来,这是我们的新视图模型的强类型,

@model CreateExpenseVm
<form asp-controller="Expense" asp-action="Create">      
    <label>Select Country</label>
    <select asp-for="CountryId" asp-items="@Model.Countries" >
        <option>Please select one</option>
    </select>
    <input type="submit"/>
</form>

并在您的HttpPost操作中,使用CreateExpenseVm作为参数类型。提交表单时,默认模型绑定器将能够将发布的表单数据映射到此类对象的属性。

[HttpPost]
public ActionResult Create(CreateExpenseVm model)
{
   var e=new Expense { CountryId=model.CountryId };
   e.ExpenseDate = DateTime.Now;
   dbContext.Expenses.Add(e);
   dbContext.SaveChanges();
   return RedirectToAction("Index");
}