好的,所以我在编辑视图中显示一个允许我为员工选择多种资格的字段时遇到了一些麻烦。
一些背景知识 - 我为一家公司工作,该公司要求我创建和雇用数据库/网络应用程序,他们可以使用这些应用程序找到具有相关技能的人员。
我是C#,MVC,实体框架,SQL的新手(公平地说,只是软件开发)但是我确实有很强的IT背景,而且我能够相对快速地选择。
我决定在我的方法中使用实体框架代码优先,并且它不是太粗糙......到目前为止。
如上所述,我在编辑视图中显示一个字段时遇到问题,该字段允许我从数据库中的多对多关系中选择多个资格。见截图。
我的模型如下
namespace reBase.Models
{
[Table("contactsTbl")]
public class contactsClass
{
[Key]
public int ID { get; set; }
[Required]
[Display(Name = "First Name")]
[RegularExpression(@"^([A-Za-z])+$", ErrorMessage = "Please Enter a Vaild Name")]
public string FirstName { get; set; }
[Required]
[Display(Name = "Surname")]
[RegularExpression(@"^([A-Za-z])+$", ErrorMessage = "Please Enter a Vaild Name")]
public string LastName { get; set; }
[Required]
[Display(Name = "Mobile Number")]
[RegularExpression(@"([0-9])")]
public string MobNo { get; set; }
public string LandLine { get; set; }
[Display(Name = "Email")]
[RegularExpression(@"^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$",
ErrorMessage = "Please Enter a vaild Email Address")]
public string EmailAddress { get; set; }
[RegularExpression(@"£[0-9]", ErrorMessage = "Please enter a Valid Rate (£ required)")]
public string HourlyRate { get; set; }
public string FullName
{ get { return FirstName + " " + LastName; } }
public Nullable<int> empStatusID { get; set; }
public Nullable<int> regionID { get; set; }
public bool isOnSite { get; set; }
public virtual empStatusClass empStatusClass { get; set; }
public virtual regionsClass regionsClass { get; set; }
public List<tradesClass> tradesClass { get; set; }
public List<ticketsClass> ticketsClass { get; set; }
}
[Table("empStatusTbl")]
public partial class empStatusClass
{
public empStatusClass()
{
this.contactsClass = new HashSet<contactsClass>();
}
[Key]
public int empStatusID { get; set; }
public string employmentStatus { get; set; }
public virtual ICollection<contactsClass> contactsClass { get; set; }
}
[Table("regionTbl")]
public partial class regionsClass
{
public regionsClass()
{
this.contactsClass = new HashSet<contactsClass>();
}
[Key]
public int regionID { get; set; }
public string regionName { get; set; }
public virtual ICollection<contactsClass> contactsClass { get; set; }
}
[Table("tradesTbl")]
public class tradesClass
{
[Key]
public int tradeID { get; set; }
public string tradeName { get; set; }
public List<contactsClass> contactsClass { get; set; }
}
[Table("ticketsTbl")]
public class ticketsClass
{
[Key]
public int ticketID { get; set; }
public string ticketName { get; set; }
public List<contactsClass> contactsClass { get; set; }
}
//
//DbContext for dataModel
public partial class dataEntityModel : DbContext
{
public dataEntityModel()
: base("name=dataEntityModel")
{
}
public virtual DbSet<contactsClass> contactClasses { get; set; }
public virtual DbSet<empStatusClass> empStatClasses { get; set; }
public virtual DbSet<regionsClass> regionClasses { get; set; }
public virtual DbSet<tradesClass> tradeClasses { get; set; }
public virtual DbSet<ticketsClass> ticketClasses { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<contactsClass>().HasMany(x => x.ticketsClass).WithMany(x => x.contactsClass);
modelBuilder.Entity<contactsClass>().HasMany(x => x.tradesClass).WithMany(x => x.contactsClass);
}
}
}
这是控制器
namespace reBase.Controllers
{
public class contactsClassesController : Controller
{
private dataEntityModel db = new dataEntityModel();
// GET: contactsClasses
public ActionResult Index()
{
var contactClasses = db.contactClasses.Include(c => c.empStatusClass).Include(c => c.regionsClass);
return View(contactClasses.ToList());
}
// GET: contactsClasses/Details/5
public ActionResult Details(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
contactsClass contactsClass = db.contactClasses.Find(id);
if (contactsClass == null)
{
return HttpNotFound();
}
return View(contactsClass);
}
// GET: contactsClasses/Create
public ActionResult Create()
{
ViewBag.empStatusID = new SelectList(db.empStatClasses, "empStatusID", "employmentStatus");
ViewBag.regionID = new SelectList(db.regionClasses, "regionID", "regionName");
ViewBag.ticketsClass = new SelectList(db.ticketClasses, "ticketID", "ticketName");
ViewBag.tradesClass = new SelectList(db.tradeClasses, "tradeID", "tradeName");
return View();
}
// POST: contactsClasses/Create
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "ID,FirstName,LastName,MobNo,LandLine,EmailAddress,HourlyRate,empStatusID,regionID,isOnSite")] contactsClass contactsClass)
{
if (ModelState.IsValid)
{
db.contactClasses.Add(contactsClass);
db.SaveChanges();
return RedirectToAction("Index");
}
ViewBag.empStatusID = new SelectList(db.empStatClasses, "empStatusID", "employmentStatus", contactsClass.empStatusID);
ViewBag.regionID = new SelectList(db.regionClasses, "regionID", "regionName", contactsClass.regionID);
ViewBag.ticketsClass = new SelectList(db.ticketClasses, "ticketID", "ticketName", contactsClass.ticketsClass);
ViewBag.tradesClass = new SelectList(db.tradeClasses, "tradeID", "tradeName", contactsClass.tradesClass);
return View(contactsClass);
}
// GET: contactsClasses/Edit/5
public ActionResult Edit(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
contactsClass contactsClass = db.contactClasses.Find(id);
if (contactsClass == null)
{
return HttpNotFound();
}
ViewBag.empStatusID = new SelectList(db.empStatClasses, "empStatusID", "employmentStatus", contactsClass.empStatusID);
ViewBag.regionID = new SelectList(db.regionClasses, "regionID", "regionName", contactsClass.regionID);
ViewBag.ticketsClass = new SelectList(db.ticketClasses, "ticketID", "ticketName", contactsClass.ticketsClass);
ViewBag.tradesClass = new SelectList(db.tradeClasses, "tradeID", "tradeName", contactsClass.tradesClass);
return View(contactsClass);
}
// POST: contactsClasses/Edit/5
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit([Bind(Include = "ID,FirstName,LastName,MobNo,LandLine,EmailAddress,HourlyRate,empStatusID,regionID,isOnSite")] contactsClass contactsClass)
{
if (ModelState.IsValid)
{
db.Entry(contactsClass).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
ViewBag.empStatusID = new SelectList(db.empStatClasses, "empStatusID", "employmentStatus", contactsClass.empStatusID);
ViewBag.regionID = new SelectList(db.regionClasses, "regionID", "regionName", contactsClass.regionID);
ViewBag.ticketsClass = new SelectList(db.ticketClasses, "ticketID", "ticketName", contactsClass.ticketsClass);
ViewBag.tradesClass = new SelectList(db.tradeClasses, "tradeID", "tradeName", contactsClass.tradesClass);
return View(contactsClass);
}
// GET: contactsClasses/Delete/5
public ActionResult Delete(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
contactsClass contactsClass = db.contactClasses.Find(id);
if (contactsClass == null)
{
return HttpNotFound();
}
return View(contactsClass);
}
// POST: contactsClasses/Delete/5
[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
public ActionResult DeleteConfirmed(int id)
{
contactsClass contactsClass = db.contactClasses.Find(id);
db.contactClasses.Remove(contactsClass);
db.SaveChanges();
return RedirectToAction("Index");
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
db.Dispose();
}
base.Dispose(disposing);
}
}
}
我只学了几个月,所以我道歉,如果这显然是明显的,但我试图避免在这里提出问题,我尝试了无数的事情让这个工作。
您可以提供的任何帮助都将受到大力赞赏。
提前谢谢大家。
答案 0 :(得分:1)
首先,Model.ticketsClass是Collection 您不能使用editorfor集合 加上Model.ticketsClass只是现有的关系,如果出于显示目的你可以这样做,请注意你当前使用的find不包含现有的关系使用select include而是做这样的事情
@foreach(var TicketClass in Model.ticketclass)
{
@Html.Display(TicketClass.ticketName)
}
如果您希望用户查看所有可用的故障单类并进行相应的编辑 我建议你做这样的事情,把所有的类作为viewbag中的ticketClass列表传递,并做这样的事情
@foreach(var TicketClass in (List<TicketClass>)ViewBag.ticketclasses)
{
<!-- the if condition inside the checkbox is to check if the relationship already exist -->
<input type="checkbox" value="true" name="TicketClass_@TicketClass.ticketID" title="@TicketClass.ticketName" @(if(Model.ticketsClass.where(f => f.ticketId == TicketClass.ticketId).FirstOrDefault() != null){"Checked"}) />
}
然后在您的控制器中执行某些操作以获取所有提交的故障单类并删除旧故障单 例子
// first remove all existing relationships
// then get submitted classes to the form using Formcollection
foreach (var item in formcollection.AllKeys.Where(x => x.Contains("TicketClass_")))
{
/// add the relationship again
}
当然有很多方法可以实现逻辑,这是其中之一
答案 1 :(得分:0)
好的,所以我设法让它运转起来。
请参阅下面的代码并与我原来的问题进行比较。
在contactsClass的控制器中需要很多额外的东西。
contactsClass Controller
namespace reBase.Controllers
{
public class contactsClassesController : Controller
{
private dataEntityModel db = new dataEntityModel();
// GET: contactsClasses
public ActionResult Index()
{
var contactClasses = db.contactClasses.Include(c => c.empStatusClass).Include(c => c.regionsClass);
return View(contactClasses.ToList());
}
// GET: contactsClasses/Details/5
public ActionResult Details(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
contactsClass contactsClass = db.contactClasses.Find(id);
if (contactsClass == null)
{
return HttpNotFound();
}
return View(contactsClass);
}
// GET: contactsClasses/Create
public ActionResult Create()
{
ViewBag.TeamID = new SelectList(db.ticketClasses, "ticketID", "ticketName");
var contact = new contactsClass();
contact.tickets = new List<ticketsClass>();
populateAssignedTicketData(contact);
ViewBag.empStatusID = new SelectList(db.empStatClasses, "empStatusID", "employmentStatus");
ViewBag.regionID = new SelectList(db.regionClasses, "regionID", "regionName");
return View();
}
// POST: contactsClasses/Create
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "ID,FirstName,LastName,MobNo,LandLine,EmailAddress,HourlyRate,empStatusID,regionID,isOnSite")] contactsClass contactsClass)
{
if (ModelState.IsValid)
{
db.contactClasses.Add(contactsClass);
db.SaveChanges();
return RedirectToAction("Index");
}
ViewBag.empStatusID = new SelectList(db.empStatClasses, "empStatusID", "employmentStatus", contactsClass.empStatusID);
ViewBag.regionID = new SelectList(db.regionClasses, "regionID", "regionName", contactsClass.regionID);
populateAssignedTicketData(contactsClass);
return View(contactsClass);
}
// GET: contactsClasses/Edit/5
public ActionResult Edit(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
//contactsClass contactsClass = db.contactClasses.Find(id);
contactsClass contactsClass = db.contactClasses
.Include(p => p.tickets)
.Where(i => i.ID == id)
.Single();
if (contactsClass == null)
{
return HttpNotFound();
}
ViewBag.empStatusID = new SelectList(db.empStatClasses, "empStatusID", "employmentStatus", contactsClass.empStatusID);
ViewBag.regionID = new SelectList(db.regionClasses, "regionID", "regionName", contactsClass.regionID);
populateAssignedTicketData(contactsClass);
return View(contactsClass);
}
private void populateAssignedTicketData(contactsClass contactsClass)
{
var allTickets = db.ticketClasses;
var contactTicket = new HashSet<int>(contactsClass.tickets.Select(b => b.ticketID));
var viewModelAvailable = new List<contactTicketVM>();
var viewModelSelected = new List<contactTicketVM>();
foreach (var ticket in allTickets)
{
if (contactTicket.Contains(ticket.ticketID))
{
viewModelSelected.Add(new contactTicketVM
{
ticketID = ticket.ticketID,
ticketName = ticket.ticketName,
//Assigned = true
});
}
else
{
viewModelAvailable.Add(new contactTicketVM
{
ticketID = ticket.ticketID,
ticketName = ticket.ticketName,
//Assigned = false
});
}
}
ViewBag.selOpts = new MultiSelectList(viewModelSelected, "ticketID", "ticketName");
ViewBag.availOpts = new MultiSelectList(viewModelAvailable, "ticketID", "ticketName");
}
// POST: contactsClasses/Edit/5
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(int? id, [Bind(Include = "ID,FirstName,LastName,MobNo,LandLine,EmailAddress,HourlyRate,empStatusID,regionID,isOnSite")] contactsClass contactsClass, string[] selectedOptions)
{
if (ModelState.IsValid)
{
db.Entry(contactsClass).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
var contactToUpdate = db.contactClasses
.Include(p => p.tickets)
.Where(i => i.ID == id)
.Single();
if (TryUpdateModel(contactToUpdate, "",
new string[] { "ID", "FirstName", "LastName", "MobNo", "LandLine", "EmailAddress", "HourlyRate", "isOnSite", "empStatusID", "regionID" }))
{
try
{
updateContactTickets(selectedOptions, contactToUpdate);
db.Entry(contactToUpdate).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
catch (RetryLimitExceededException /* dex */)
{
//Log the error (uncomment dex variable name and add a line here to write a log.
ModelState.AddModelError("", "Unable to save changes. Try again, and if the problem persists, see your system administrator.");
}
}
ViewBag.empStatusID = new SelectList(db.empStatClasses, "empStatusID", "employmentStatus", contactsClass.empStatusID);
ViewBag.regionID = new SelectList(db.regionClasses, "regionID", "regionName", contactsClass.regionID);
populateAssignedTicketData(contactToUpdate);
return View(contactToUpdate);
}
private void updateContactTickets(string[] selectedOptions, contactsClass contactToUpdate)
{
if (selectedOptions == null)
{
contactToUpdate.tickets = new List<ticketsClass>();
return;
}
var selectedOptionsHS = new HashSet<string>(selectedOptions);
var contactTickets = new HashSet<int>
(contactToUpdate.tickets.Select(b => b.ticketID));
foreach (var ticket in db.ticketClasses)
{
if (selectedOptionsHS.Contains(ticket.ticketID.ToString()))
{
if (!contactTickets.Contains(ticket.ticketID))
{
contactToUpdate.tickets.Add(ticket);
}
}
else
{
if (contactTickets.Contains(ticket.ticketID))
{
contactToUpdate.tickets.Remove(ticket);
}
}
}
}
// GET: contactsClasses/Delete/5
public ActionResult Delete(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
contactsClass contactsClass = db.contactClasses.Find(id);
if (contactsClass == null)
{
return HttpNotFound();
}
return View(contactsClass);
}
// POST: contactsClasses/Delete/5
[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
public ActionResult DeleteConfirmed(int id)
{
contactsClass contactsClass = db.contactClasses.Find(id);
db.contactClasses.Remove(contactsClass);
db.SaveChanges();
return RedirectToAction("Index");
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
db.Dispose();
}
base.Dispose(disposing);
}
}
}
这是我的编辑视图
@model reBase.Models.contactsClass
@{
ViewBag.Title = "Edit";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>Edit</h2>
@using (Html.BeginForm())
{
@Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>contactsClass</h4>
<hr />
@Html.ValidationSummary(true, "", new { @class = "text-danger" })
@Html.HiddenFor(model => model.ID)
<div class="form-group">
@Html.LabelFor(model => model.FirstName, htmlAttributes: new {
@class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.FirstName, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.FirstName, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.LastName, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.LastName, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.LastName, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.MobNo, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.MobNo, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.MobNo, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.LandLine, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.LandLine, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.LandLine, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.EmailAddress, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.EmailAddress, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.EmailAddress, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.HourlyRate, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.HourlyRate, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.HourlyRate, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.empStatusID, "empStatusID", htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.DropDownList("empStatusID", null, htmlAttributes: new { @class = "form-control" })
@Html.ValidationMessageFor(model => model.empStatusID, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.regionID, "regionID", htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.DropDownList("regionID", null, htmlAttributes: new { @class = "form-control" })
@Html.ValidationMessageFor(model => model.regionID, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.isOnSite, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
<div class="checkbox">
@Html.EditorFor(model => model.isOnSite)
@Html.ValidationMessageFor(model => model.isOnSite, "", new { @class = "text-danger" })
</div>
</div>
</div>
<div class="row">
<div class="col-md-2"> </div>
<div class="form-group col-md-4">
<label class="control-label">Current Tickets</label>
@Html.ListBox("selectedOptions",
(MultiSelectList)ViewBag.selOpts, new { @class = "form-control" })
</div>
<div class="form-group col-md-1">
<div class="form-group">
<button type="button" id="btnRight" class="btn btn-warning btn-lg">
<span class="glyphicon glyphicon-arrow-right" aria-hidden="true"></span>
</button>
</div>
<div class="form-group">
<button type="button" id="btnLeft" class="btn btn-success btn-lg">
<span class="glyphicon glyphicon-arrow-left" aria-hidden="true"></span>
</button>
<div></div>
</div>
</div>
<div class="form-group col-md-4">
<label class="control-label">Assign Tickets</label>
@Html.ListBox("availOptions", (MultiSelectList)ViewBag.availOpts, new { @class = "form-control" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" id="btnSubmit" value="Save" class="btn btn-default" />
</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")
}
还添加了视图模型
namespace reBase.ViewModels
{
public class contactTicketVM
{
public int ticketID { get; set; }
public string ticketName { get; set; }
public bool Assigned { get; set; }
}
}
谢谢大家对此事的帮助