ASP.NET MVC Viewmodel 编辑 returns 空字段(项目未通过 ID 标识)
ASP.NET MVC Viewmodel Edit returns empty fields (item is not identified by id)
我之前得到了一些帮助 here 但现在 "Edit" 出现了一些问题。目前卡在HttpGet,HttpPost还没来
简而言之,每当我单击要编辑的现有项目时,它 returns 一个空表单 as seen here 而不是预期值。 (您可能认为这是因为我对“创建”和“编辑”使用了完全相同的视图,但不幸的是,这不是,即使我过去常常将它们分开,也有相同的结果。)
Town.cs
using System.Collections.Generic;
namespace City.Models
{
public class Town
{
public Town()
{
Streets = new List<Street>();
}
public int TownId { get; set; }
public string TownName { get; set; }
public virtual ICollection<Street> Streets { get; set; }
}
}
Street.cs
using System.Collections.Generic;
namespace City.Models
{
public class Street
{
public Street()
{
Houses = new List<House>();
}
public int StreetId { get; set; }
public string StreetName { get; set; }
public virtual ICollection<House> Houses { get; set; }
}
}
House.cs
using System.Collections.Generic;
namespace City.Models
{
public class House
{
public House()
{
Floors = new List<Floor>();
}
public int HouseId { get; set; }
public string HouseName { get; set; }
public ICollection<Floor> Floors { get; set; }
}
}
Floor.cs
using System.Collections.Generic;
namespace City.Models
{
public class Floor
{
public Floor()
{
FireExtinguishers = new List<FireExtinguisher>();
}
public int FloorId { get; set; }
public int FloorNumber { get; set; }
public virtual ICollection<FireExtinguisher> FireExtinguishers { get; set; }
}
}
FireExtinguisher.cs
using System.ComponentModel;
namespace City.Models
{
public class FireExtinguisher
{
public int FireExtinguisherId { get; set; }
[DisplayName("Fire Extinguisher")]
public string FireExtinguisherName { get; set; }
public int FloorId { get; set; }
public int HouseId { get; set; }
public int StreetId { get; set; }
public int TownId { get; set; }
public Floor Floor { get; set; }
public House House { get; set; }
public Street Street { get; set; }
public Town Town { get; set; }
}
}
MyViewModel.cs
using System.Collections.Generic;
namespace City.Models
{
public class MyViewModel
{
public IEnumerable<Town> TownId { get; set; }
public IEnumerable<Street> StreetId { get; set; }
public IEnumerable<House> HouseId { get; set; }
public IEnumerable<Floor> FloorId { get; set; }
public FireExtinguisher FireExtinguisher { get; set; }
public string FireExtinguisherName { get; set; }
}
}
Create/Edit 查看
@model City.Models.MyViewModel
<h2>Add new or edit existing FE</h2>
@using (Html.BeginForm())
{
@Html.AntiForgeryToken()
<div class="form-horizontal">
<hr />
@Html.ValidationSummary(true, "", new { @class = "text-danger" })
<div class="col-md-12">
<div class="form-group">
@Html.LabelFor(model => model.TownId, "Town", new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.DropDownListFor(model => model.TownId, new SelectList(Model.TownId, "TownId", "TownName"), "Choose Town", new { @class = "form-control" })
@Html.ValidationMessageFor(model => model.TownId, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.StreetId, "Street", new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.DropDownListFor(model => model.StreetId, new SelectList(Model.StreetId, "StreetId", "StreetName"), "Choose Street", new { @class = "form-control" })
@Html.ValidationMessageFor(model => model.StreetId, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.HouseId, "House", new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.DropDownListFor(model => model.HouseId, new SelectList(Model.HouseId, "HouseId", "HouseName"), "Choose House", new { @class = "form-control" })
@Html.ValidationMessageFor(model => model.HouseId, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.FloorId, "Floor", new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.DropDownListFor(model => model.FloorId, new SelectList(Model.FloorId, "FloorId", "FloorNumber"), "Choose Floor", new { @class = "form-control" })
@Html.ValidationMessageFor(model => model.FloorId, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.FireExtinguisherName, "Fire Extinguisher", new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.TextBoxFor(model => model.FireExtinguisherName, new { @class = "form-control", Value = "" })
@Html.ValidationMessageFor(model => model.FireExtinguisherName, "", new { @class = "text-danger" })
</div>
</div>
</div>
<div>
<div>
<input type="submit" value="Do it" class="btn btn-default" />
</div>
</div>
</div>
}
<div>
@Html.ActionLink("Back to List", "Index")
</div>
@section Scripts {
@Scripts.Render("~/bundles/jqueryval")
}
Homecontroller.cs
using System;
using System.Linq;
using System.Net;
using System.Web.Mvc;
using City.Models;
namespace City.Controllers
{
public class HomeController : Controller
{
private ApplicationDbContext db;
private MyViewModel viewModel;
public HomeController()
{
db = new ApplicationDbContext();
var town = db.Towns.ToList();
var street = db.Streets.ToList();
var house = db.Houses.ToList();
var floor = db.Floors.ToList();
viewModel = new MyViewModel()
{
TownId = town,
StreetId = street,
HouseId = house,
FloorId = floor
};
}
public ActionResult Index()
{
return View(db.FireExtinguishers.ToList());
}
[HttpGet]
public ActionResult Create()
{
return View(viewModel);
}
[HttpPost]
public ActionResult Create(FireExtinguisher fe)
{
if (ModelState.IsValid)
{
db.FireExtinguishers.Add(fe);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(viewModel);
}
[HttpGet]
public ActionResult Edit(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
var fe = db.FireExtinguishers.Find(id);
var town = db.Towns.ToList();
var street = db.Streets.ToList();
var house = db.Houses.ToList();
var floor = db.Floors.ToList();
viewModel = new MyViewModel()
{
FireExtinguisher = fe,
TownId = town,
StreetId = street,
HouseId = house,
FloorId = floor
};
return View("Create", viewModel);
}
[HttpPost]
public ActionResult Edit()
{
throw new NotImplementedException();
}
}
}
任何帮助将不胜感激,谢谢
就我个人而言,我喜欢使用 View- 和 Post-Models 作为一个明确的声明,发送到 View (ViewModel) 的内容以及通过 Post 发回的内容。作为命名约定,模型名称 class 采用控制器名称和操作名称。
我从 Post模型开始,你的情况就是这样
public class HomeEditPostModel
{
[Required]
[MaxLength(50)]
public string Name { get; set; }
[Required]
public int TownId { get; set; }
[Required]
public int StreetId { get; set; }
[Required]
public int HouseId { get; set; }
[Required]
public int FloorId { get; set; }
}
现在对于视图,我们需要一些下拉字段集合,我们可以从select
public class SelectionItem<TKey>
{
public TKey Key { get; set; }
public string DisplayName { get; set; }
}
public class HomeEditViewModel : HomeEditPostModel
{
public IEnumerable<SelectionItem<int>> Town { get; set; }
public IEnumerable<SelectionItem<int>> Street { get; set; }
public IEnumerable<SelectionItem<int>> House { get; set; }
public IEnumerable<SelectionItem<int>> Floor { get; set; }
}
现在的景色
@model WebApplication6.Models.HomeEditViewModel
@{
ViewBag.Title = "Edit";
}
<h2>Edit</h2>
@using (Html.BeginForm())
{
@Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>HomeEditSubmitModel</h4>
<hr />
@Html.ValidationSummary(true, "", new { @class = "text-danger" })
<div class="form-group">
@Html.LabelFor(model => model.Name, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.Name, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.Name, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.TownId, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.DropDownListFor(model => model.TownId, new SelectList(Model.Town, "Key", "DisplayName"), "Choose Town", new { @class = "form-control" })
@Html.ValidationMessageFor(model => model.TownId, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.StreetId, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.DropDownListFor(model => model.StreetId, new SelectList(Model.Street, "Key", "DisplayName"), "Choose Street", new { @class = "form-control" })
@Html.ValidationMessageFor(model => model.StreetId, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.HouseId, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.DropDownListFor(model => model.HouseId, new SelectList(Model.House, "Key", "DisplayName"), "Choose House", new { @class = "form-control" })
@Html.ValidationMessageFor(model => model.HouseId, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.FloorId, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.DropDownListFor(model => model.FloorId, new SelectList(Model.Floor, "Key", "DisplayName"), "Choose Floor", new { @class = "form-control" })
@Html.ValidationMessageFor(model => model.FloorId, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Save" class="btn btn-default" />
</div>
</div>
</div>
}
<div>
@Html.ActionLink("Back to List", "Index")
</div>
@section Scripts {
@Scripts.Render("~/bundles/jqueryval")
}
最后是控制器(仅相关部分)
public class HomeController : Controller
{
[HttpGet]
public ActionResult Edit(int id)
{
// just some fake data for demonstration
var model = new HomeEditViewModel
{
Name = "Name",
Floor = Enumerable.Range(1, 10).Select(e => new SelectionItem<int> { Key = e, DisplayName = $"Floor {e}" }),
Street = Enumerable.Range(1, 10).Select(e => new SelectionItem<int> { Key = e, DisplayName = $"Street {e}" }),
House = Enumerable.Range(1, 10).Select(e => new SelectionItem<int> { Key = e, DisplayName = $"House {e}" }),
Town = Enumerable.Range(1, 10).Select(e => new SelectionItem<int> { Key = e, DisplayName = $"Town {e}" }),
FloorId = 3,
StreetId = 4,
HouseId = 5,
TownId = 6,
};
return View(model);
}
[HttpPost]
public ActionResult Edit(int id, HomeEditPostModel model)
{
// needs to save the data here
return RedirectToAction(nameof(Index));
}
}
我之前得到了一些帮助 here 但现在 "Edit" 出现了一些问题。目前卡在HttpGet,HttpPost还没来
简而言之,每当我单击要编辑的现有项目时,它 returns 一个空表单 as seen here 而不是预期值。 (您可能认为这是因为我对“创建”和“编辑”使用了完全相同的视图,但不幸的是,这不是,即使我过去常常将它们分开,也有相同的结果。)
Town.cs
using System.Collections.Generic;
namespace City.Models
{
public class Town
{
public Town()
{
Streets = new List<Street>();
}
public int TownId { get; set; }
public string TownName { get; set; }
public virtual ICollection<Street> Streets { get; set; }
}
}
Street.cs
using System.Collections.Generic;
namespace City.Models
{
public class Street
{
public Street()
{
Houses = new List<House>();
}
public int StreetId { get; set; }
public string StreetName { get; set; }
public virtual ICollection<House> Houses { get; set; }
}
}
House.cs
using System.Collections.Generic;
namespace City.Models
{
public class House
{
public House()
{
Floors = new List<Floor>();
}
public int HouseId { get; set; }
public string HouseName { get; set; }
public ICollection<Floor> Floors { get; set; }
}
}
Floor.cs
using System.Collections.Generic;
namespace City.Models
{
public class Floor
{
public Floor()
{
FireExtinguishers = new List<FireExtinguisher>();
}
public int FloorId { get; set; }
public int FloorNumber { get; set; }
public virtual ICollection<FireExtinguisher> FireExtinguishers { get; set; }
}
}
FireExtinguisher.cs
using System.ComponentModel;
namespace City.Models
{
public class FireExtinguisher
{
public int FireExtinguisherId { get; set; }
[DisplayName("Fire Extinguisher")]
public string FireExtinguisherName { get; set; }
public int FloorId { get; set; }
public int HouseId { get; set; }
public int StreetId { get; set; }
public int TownId { get; set; }
public Floor Floor { get; set; }
public House House { get; set; }
public Street Street { get; set; }
public Town Town { get; set; }
}
}
MyViewModel.cs
using System.Collections.Generic;
namespace City.Models
{
public class MyViewModel
{
public IEnumerable<Town> TownId { get; set; }
public IEnumerable<Street> StreetId { get; set; }
public IEnumerable<House> HouseId { get; set; }
public IEnumerable<Floor> FloorId { get; set; }
public FireExtinguisher FireExtinguisher { get; set; }
public string FireExtinguisherName { get; set; }
}
}
Create/Edit 查看
@model City.Models.MyViewModel
<h2>Add new or edit existing FE</h2>
@using (Html.BeginForm())
{
@Html.AntiForgeryToken()
<div class="form-horizontal">
<hr />
@Html.ValidationSummary(true, "", new { @class = "text-danger" })
<div class="col-md-12">
<div class="form-group">
@Html.LabelFor(model => model.TownId, "Town", new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.DropDownListFor(model => model.TownId, new SelectList(Model.TownId, "TownId", "TownName"), "Choose Town", new { @class = "form-control" })
@Html.ValidationMessageFor(model => model.TownId, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.StreetId, "Street", new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.DropDownListFor(model => model.StreetId, new SelectList(Model.StreetId, "StreetId", "StreetName"), "Choose Street", new { @class = "form-control" })
@Html.ValidationMessageFor(model => model.StreetId, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.HouseId, "House", new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.DropDownListFor(model => model.HouseId, new SelectList(Model.HouseId, "HouseId", "HouseName"), "Choose House", new { @class = "form-control" })
@Html.ValidationMessageFor(model => model.HouseId, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.FloorId, "Floor", new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.DropDownListFor(model => model.FloorId, new SelectList(Model.FloorId, "FloorId", "FloorNumber"), "Choose Floor", new { @class = "form-control" })
@Html.ValidationMessageFor(model => model.FloorId, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.FireExtinguisherName, "Fire Extinguisher", new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.TextBoxFor(model => model.FireExtinguisherName, new { @class = "form-control", Value = "" })
@Html.ValidationMessageFor(model => model.FireExtinguisherName, "", new { @class = "text-danger" })
</div>
</div>
</div>
<div>
<div>
<input type="submit" value="Do it" class="btn btn-default" />
</div>
</div>
</div>
}
<div>
@Html.ActionLink("Back to List", "Index")
</div>
@section Scripts {
@Scripts.Render("~/bundles/jqueryval")
}
Homecontroller.cs
using System;
using System.Linq;
using System.Net;
using System.Web.Mvc;
using City.Models;
namespace City.Controllers
{
public class HomeController : Controller
{
private ApplicationDbContext db;
private MyViewModel viewModel;
public HomeController()
{
db = new ApplicationDbContext();
var town = db.Towns.ToList();
var street = db.Streets.ToList();
var house = db.Houses.ToList();
var floor = db.Floors.ToList();
viewModel = new MyViewModel()
{
TownId = town,
StreetId = street,
HouseId = house,
FloorId = floor
};
}
public ActionResult Index()
{
return View(db.FireExtinguishers.ToList());
}
[HttpGet]
public ActionResult Create()
{
return View(viewModel);
}
[HttpPost]
public ActionResult Create(FireExtinguisher fe)
{
if (ModelState.IsValid)
{
db.FireExtinguishers.Add(fe);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(viewModel);
}
[HttpGet]
public ActionResult Edit(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
var fe = db.FireExtinguishers.Find(id);
var town = db.Towns.ToList();
var street = db.Streets.ToList();
var house = db.Houses.ToList();
var floor = db.Floors.ToList();
viewModel = new MyViewModel()
{
FireExtinguisher = fe,
TownId = town,
StreetId = street,
HouseId = house,
FloorId = floor
};
return View("Create", viewModel);
}
[HttpPost]
public ActionResult Edit()
{
throw new NotImplementedException();
}
}
}
任何帮助将不胜感激,谢谢
就我个人而言,我喜欢使用 View- 和 Post-Models 作为一个明确的声明,发送到 View (ViewModel) 的内容以及通过 Post 发回的内容。作为命名约定,模型名称 class 采用控制器名称和操作名称。
我从 Post模型开始,你的情况就是这样
public class HomeEditPostModel
{
[Required]
[MaxLength(50)]
public string Name { get; set; }
[Required]
public int TownId { get; set; }
[Required]
public int StreetId { get; set; }
[Required]
public int HouseId { get; set; }
[Required]
public int FloorId { get; set; }
}
现在对于视图,我们需要一些下拉字段集合,我们可以从select
public class SelectionItem<TKey>
{
public TKey Key { get; set; }
public string DisplayName { get; set; }
}
public class HomeEditViewModel : HomeEditPostModel
{
public IEnumerable<SelectionItem<int>> Town { get; set; }
public IEnumerable<SelectionItem<int>> Street { get; set; }
public IEnumerable<SelectionItem<int>> House { get; set; }
public IEnumerable<SelectionItem<int>> Floor { get; set; }
}
现在的景色
@model WebApplication6.Models.HomeEditViewModel
@{
ViewBag.Title = "Edit";
}
<h2>Edit</h2>
@using (Html.BeginForm())
{
@Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>HomeEditSubmitModel</h4>
<hr />
@Html.ValidationSummary(true, "", new { @class = "text-danger" })
<div class="form-group">
@Html.LabelFor(model => model.Name, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.Name, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.Name, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.TownId, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.DropDownListFor(model => model.TownId, new SelectList(Model.Town, "Key", "DisplayName"), "Choose Town", new { @class = "form-control" })
@Html.ValidationMessageFor(model => model.TownId, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.StreetId, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.DropDownListFor(model => model.StreetId, new SelectList(Model.Street, "Key", "DisplayName"), "Choose Street", new { @class = "form-control" })
@Html.ValidationMessageFor(model => model.StreetId, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.HouseId, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.DropDownListFor(model => model.HouseId, new SelectList(Model.House, "Key", "DisplayName"), "Choose House", new { @class = "form-control" })
@Html.ValidationMessageFor(model => model.HouseId, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.FloorId, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.DropDownListFor(model => model.FloorId, new SelectList(Model.Floor, "Key", "DisplayName"), "Choose Floor", new { @class = "form-control" })
@Html.ValidationMessageFor(model => model.FloorId, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Save" class="btn btn-default" />
</div>
</div>
</div>
}
<div>
@Html.ActionLink("Back to List", "Index")
</div>
@section Scripts {
@Scripts.Render("~/bundles/jqueryval")
}
最后是控制器(仅相关部分)
public class HomeController : Controller
{
[HttpGet]
public ActionResult Edit(int id)
{
// just some fake data for demonstration
var model = new HomeEditViewModel
{
Name = "Name",
Floor = Enumerable.Range(1, 10).Select(e => new SelectionItem<int> { Key = e, DisplayName = $"Floor {e}" }),
Street = Enumerable.Range(1, 10).Select(e => new SelectionItem<int> { Key = e, DisplayName = $"Street {e}" }),
House = Enumerable.Range(1, 10).Select(e => new SelectionItem<int> { Key = e, DisplayName = $"House {e}" }),
Town = Enumerable.Range(1, 10).Select(e => new SelectionItem<int> { Key = e, DisplayName = $"Town {e}" }),
FloorId = 3,
StreetId = 4,
HouseId = 5,
TownId = 6,
};
return View(model);
}
[HttpPost]
public ActionResult Edit(int id, HomeEditPostModel model)
{
// needs to save the data here
return RedirectToAction(nameof(Index));
}
}