I have a ViewModel which is joined by three Entities to get data from all entities into one view form. Although i succeeded to implement the same. But i have no idea how to Edit and Save data back to the database. My model classes are joined by one to one relationship.
My Models are:
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; }
}
My ViewModel is:
public class DoctorViewModel
{
public Doctor Doctor { get; set; }
public DoctorAddress DoctorAddress { get; set; }
public DoctorCharge DoctorCharge { get; set; }
}
My Controller is:
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());
}
My View is:
@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>}
My Controller Class is:
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);
}
Please help me how do i do. Thanks in advance.
First of all, it's really good that you are using
ViewModels
but for this particular case, it's probably not necessary, yourCreate
view could look like this:Then your
Doctor
controller:If you want to keep your ViewModel then it could look like this:
For this answer I'm using Tom Dykstra’s Tutorial Guide on Implementing Basic CRUD Functionality with the Entity Framework in ASP.NET MVC Application in ViewModel context.
The tutorial uses TryUpdateModel(TModel, String, String[]) method call to update a single
Student
model inEdit
method.TryUpdateModel
method returnstrue
if update was successful, otherwise it returnsfalse
. Above the first parameter forTryUpdateModel
method call is theStudent
model (studentToUpdate
). The 2nd parameter is a prefix for looking values in the value provider (empty string""
). 3rd parameter is list of properties that are updated:”LastName", "FirstMidName", "EnrollmentDate"
To make the above work for
DoctorViewModel
, the second parameter (prefix) needs to be used too. For example forDoctor
model:The prefix
"Doctor"
is needed forTryUpdateModel
method call, because whenDoctorViewModel
is used, it cannot findDoctor
model’s parameters otherwise. For example the below Watch window shows how the form values are shown in Visual Studio in debug mode for edit method:in
Edit
view the code below:creates the following html:
Here’s code for
Edit
method forDoctorViewModel
It’s also a good idea to add ValidateAntiForgeryToken attribute to the code to prevent cross-site request forgery.
Update
I also made some small changes to model classes by adding attributes. This enables models with relationship to be found more easily:
Therefore models below have
[Key]
or[Key, ForeignKey("Doctor")]
attributesAny feedback in relation ViewModel updates is welcomed. Recently I faced similar problem in my own project, and this was the approach I used to solve this issue. I guess there are alternative ways to handle this issue.
Here, for creating: