我有一个ViewModel,由三个实体连接,将所有实体的数据转换为一个视图形式。虽然我成功实现了同样的目标。但我不知道如何编辑和保存数据回数据库。我的模型类由一对一的关系加入。
我的模特是:
public class Doctor
{
public int DoctorId { get; set; }
public string Name { get; set; }
public string Speciality { get; set; }
public virtual DoctorAddress DoctorAddress { get; set; }
public virtual DoctorCharge DoctorCharge { get; set; }
public virtual DoctorAvailablity DoctorAvailablity { get; set; }
}
public class DoctorAddress
{
public string Address { get; set; }
public string City { get; set; }
public int DoctorId { get; set; }
public virtual Doctor Doctor { get; set; }
}
public class DoctorCharge
{
public decimal OPDCharge { get; set; }
public decimal IPDCharge { get; set; }
public int DoctorId { get; set; }
public virtual Doctor Doctor { get; set; }
}
我的ViewModel是:
public class DoctorViewModel
{
public Doctor Doctor { get; set; }
public DoctorAddress DoctorAddress { get; set; }
public DoctorCharge DoctorCharge { get; set; }
}
我的控制器是:
public ActionResult Index()
{
var model = from t1 in db.Doctors
join d in db.DoctorAddress on t1.DoctorId equals d.DoctorId into listi
join dc in db.DoctorCharges on t1.DoctorId equals dc.DoctorId into listj
from d in listi.DefaultIfEmpty()
from dc in listj.DefaultIfEmpty()
select new DoctorDetailsViewModel.DoctorViewModel { Doctor = t1, DoctorAddress = d, DoctorCharge = dc };
return View(model.ToList());
}
我的观点是:
@model XXX.DoctorDetailsViewModel.DoctorViewModel
@using (Html.BeginForm()) {
@Html.ValidationSummary(true)
<fieldset>
<legend>Doctor</legend>
<div class="editor-label">
Name
</div>
<div class="editor-field">
@Html.EditorFor(model => model.Doctor.Name)
</div>
<div class="editor-label">
OPD Charge
</div>
<div class="editor-field">
@Html.EditorFor(model => model.DoctorCharge.OPDCharge)
</div>
<div class="editor-label">
Address
</div>
<div class="editor-field">
@Html.EditorFor(model => model.DoctorAddress.Address)
</div> <p>
<input type="submit" value="Create" />
</p>
</fieldset>}
我的控制器类是:
public ActionResult Create()
{
return View();
}
//
// POST: /Doctor/Create
[HttpPost]
public ActionResult Create(Doctor doctor)
{
if (ModelState.IsValid)
{
db.Doctors.Add(doctor);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(doctor);
}
请帮帮我怎么办。提前谢谢。
答案 0 :(得分:4)
首先,您使用ViewModels
非常好,但对于这种特殊情况,可能没有必要,您的Create
视图可能如下所示:
@model MvcApplication1.Models.Doctor
//other fields here
<div class="editor-label">
@Html.LabelFor(model => model.DoctorAddress.Address)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.DoctorAddress.Address)
@Html.ValidationMessageFor(model => model.DoctorAddress.Address)
</div>
<div class="editor-label">
@Html.LabelFor(model => model.DoctorCharge.IPDCharge)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.DoctorCharge.IPDCharge)
@Html.ValidationMessageFor(model => model.DoctorCharge.IPDCharge)
</div>
//other fields here
然后你的Doctor
控制器:
[HttpPost]
public ActionResult Create(Doctor doctor)
{
if (ModelState.IsValid)
{
db.Doctors.Add(doctor);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(doctor);
}
Your `Edit` action could then look like this:
[HttpGet]
public ActionResult Edit(int id = 0)
{
Doctor doctor = db.Doctors.Find(id);
if (doctor == null)
{
return HttpNotFound();
}
return View(doctor);
}
[HttpPost]
public ActionResult Edit(Doctor doctor)
{
if (ModelState.IsValid)
{
db.Entry(doctor).State = EntityState.Modified;
db.Entry(doctor.DoctorAddress).State = EntityState.Modified;
db.Entry(doctor.DoctorCharge).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
return View(doctor);
}
如果你想保留你的ViewModel,那么它可能如下所示:
[HttpPost]
public ActionResult Edit(DoctorViewModel doctorViewModel)
{
if (ModelState.IsValid)
{
var doctorAddress = doctorViewModel.DoctorAddress;
var doctorCharge = doctorViewModel.DoctorCharge;
var doctor = doctorViewModel.Doctor;
db.Entry(doctorAddress).State = EntityState.Modified;
db.Entry(doctorCharge).State = EntityState.Modified;
db.Entry(doctor).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
return View(doctor);
}
答案 1 :(得分:4)
这里,创建:
[HttpPost]
public ActionResult Create(DoctorViewModel model)
{
if (ModelState.IsValid)
{
model.Doctor.DoctorAddress = model.DoctorAddress;
model.Doctor.DoctorCharge = model.DoctorCharge;
db.Doctors.Add(doctor);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(doctor);
}
答案 2 :(得分:2)
对于这个答案,我在 ViewModel 上下文中使用 Tom Dykstra的教程指南{/ 3}}。
本教程使用Implementing Basic CRUD Functionality with the Entity Framework in ASP.NET MVC Application方法调用来更新Student
方法中的单个Edit
模型。
var studentToUpdate = db.Students.Find(id);
if (TryUpdateModel(studentToUpdate, "",
new string[] { "LastName", "FirstMidName", "EnrollmentDate" })) {
//Save all changes made in this context to the underlying database
db.SaveChanges();
return RedirectToAction("Index");
}
如果更新成功,则 TryUpdateModel
方法返回true
,否则返回false
。 TryUpdateModel
方法调用的第一个参数上方是Student
模型(studentToUpdate
)。第二个参数是在值提供程序中查找值的前缀(空字符串""
)。第三个参数是已更新的属性列表:”LastName", "FirstMidName", "EnrollmentDate"
作为阻止TryUpdateModel(TModel, String, String[])的最佳做法,您希望使用的字段 可以通过编辑页面进行更新,并在TryUpdateModel中列入白名单 参数。
要为DoctorViewModel
进行上述工作,还需要使用第二个参数(前缀)。例如Doctor
模型:
Doctor doctorToUpdate = db.Doctors.Find(id);
bool doctorUpdateSuccess = TryUpdateModel(doctorToUpdate, "Doctor",
new string[] { "Name", "Speciality" });
"Doctor"
方法调用需要前缀TryUpdateModel
,因为当使用DoctorViewModel
时,它无法找到Doctor
模型的参数。例如,下面的Watch窗口显示了在编辑方法的调试模式下Visual Studio中窗体值的显示方式:
Edit
中查看以下代码:
<div class="editor-field">
@Html.EditorFor(model => model.Doctor.Name)
</div>
创建以下html:
<div class="editor-field">
<input class="text-box single-line" id="Doctor_Name"
name="Doctor.Name" type="text" value="Foo"/>
</div>
以下是Edit
DoctorViewModel
方法的代码
[HttpPost, ActionName("Edit")]
public ActionResult EditPost(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Doctor doctorToUpdate = db.Doctors.Find(id);
if (doctorToUpdate == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
bool doctorUpdateSuccess = TryUpdateModel(doctorToUpdate, "Doctor", new string[] { "Name", "Speciality" });
DoctorAddress doctorAddressToUpdate = doctorToUpdate.DoctorAddress;
if (doctorAddressToUpdate == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
bool doctorAddressUpdateSuccess = TryUpdateModel(doctorAddressToUpdate, "DoctorAddress", new string[] { "Address" });
DoctorCharge doctorChargeToUpdate = doctorToUpdate.DoctorCharge;
if (doctorChargeToUpdate == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
bool doctorChargeUpdateSuccess = TryUpdateModel(doctorChargeToUpdate, "DoctorCharge", new string[] { "OPDCharge" });
// if all models have been successfully updated
// then save changes to database
if (doctorUpdateSuccess &&
doctorAddressUpdateSuccess &&
doctorChargeUpdateSuccess)
{
db.SaveChanges();
return RedirectToAction("Index");
}
DoctorDetailsViewModel.DoctorViewModel viewModel = new DoctorDetailsViewModel.DoctorViewModel();
viewModel.Doctor = doctorToUpdate;
viewModel.DoctorAddress = doctorAddressToUpdate;
viewModel.DoctorCharge = doctorChargeToUpdate;
return View(viewModel);
}
将属性添加到代码中以阻止ValidateAntiForgeryToken也是一个好主意。
<强>更新强>
我还通过添加属性对模型类进行了一些小的更改。这使得能够更容易地找到具有关系的模型:
DoctorAddress doctorAddressToUpdate = doctorToUpdate.DoctorAddress;
DoctorCharge doctorChargeToUpdate = doctorToUpdate.DoctorCharge;
因此,以下模型具有[Key]
或[Key, ForeignKey("Doctor")]
属性
public class Doctor
{
[Key]
public int DoctorId { get; set; }
public string Name { get; set; }
public string Speciality { get; set; }
public virtual DoctorAddress DoctorAddress { get; set; }
public virtual DoctorCharge DoctorCharge { get; set; }
public virtual DoctorAvailability DoctorAvailablity { get; set; }
}
public class DoctorAddress
{
public string Address { get; set; }
public string City { get; set; }
[Key, ForeignKey("Doctor")]
public int DoctorId { get; set; }
public virtual Doctor Doctor { get; set; }
}
public class DoctorCharge
{
public decimal OPDCharge { get; set; }
public decimal IPDCharge { get; set; }
[Key, ForeignKey("Doctor")]
public int DoctorId { get; set; }
public virtual Doctor Doctor { get; set; }
}
欢迎任何与ViewModel相关的反馈。最近我在自己的项目中遇到了类似的问题,这就是我用来解决这个问题的方法。我想有其他方法可以解决这个问题。