Delete page not showing selected record - linq

This is homework, an ASP.NET MVC and Web forms Web application using a repository (with data hard coded and no database) to rate doctors. The user should be able to edit and delete records, but when the application is run, and the "Delete" link is pressed for one of the records, the Delete page does not show the details of that record. Why not?
Here are the Delete methods:
public ActionResult Delete(string DoctorPicture)
{
repo.Remove(DoctorPicture);
return View("Delete");
}
[HttpPost]
public ActionResult Delete(string DoctorPicture, FormCollection collection)
{
try
{
// TODO: Add delete logic here
repo.Remove(DoctorPicture);
return View("Delete");
}
catch
{
return View();
}
}
From repo.Remove(DoctorPicture); it goes here in TestDoctorRepository, and doctor is null. Is it supposed to be?
public void Remove(string DoctorPicture)
{
var doctor = from d in doctors where d.DoctorPicture == DoctorPicture select d;
doctors.Remove(doctor.FirstOrDefault());
}
This is what my list of doctors looks like. Is my path for the images posing a problem?
public TestDoctorRepository()
{
doctors = new List<Doctor> {
new Doctor { DoctorPicture = "Images/0cropped.jpg", DoctorName = "Michael Shores", DoctorSpecialty = "Opthamology", times = 0, rating = 0, rated = true, avg=0, fave = true },
//more doctors
};
}
public Doctor GetDoctorByDoctorPicture(string DoctorPicture)
{
var selectedDoctor = from d in doctors
where d.DoctorPicture == DoctorPicture
select d;
return selectedDoctor.FirstOrDefault();
}
Delete View:
#model MidtermApplication.Models.Doctor
#{
ViewBag.Title = "Delete";
}
<h2>Delete</h2>
<h3>Are you sure you want to delete this?</h3>
<fieldset>
<legend>Doctor</legend>
<div class="display-label">
#Html.DisplayNameFor(model => model.DoctorPicture)
</div>
<div class="display-field">
#Html.DisplayFor(model => model.DoctorPicture)
</div>
<div class="display-label">
#Html.DisplayNameFor(model => model.DoctorName)
</div>
<div class="display-field">
#Html.DisplayFor(model => model.DoctorName)
</div>
<div class="display-label">
#Html.DisplayNameFor(model => model.DoctorSpecialty)
</div>
<div class="display-field">
#Html.DisplayFor(model => model.DoctorSpecialty)
</div>
<div class="display-label">
#Html.DisplayNameFor(model => model.rating)
</div>
<div class="display-field">
#Html.DisplayFor(model => model.rating)
</div>
<div class="display-label">
#Html.DisplayNameFor(model => model.times)
</div>
<div class="display-field">
#Html.DisplayFor(model => model.times)
</div>
<div class="display-label">
#Html.DisplayNameFor(model => model.fave)
</div>
<div class="display-field">
#Html.DisplayFor(model => model.fave)
</div>
<div class="display-label">
#Html.DisplayNameFor(model => model.rated)
</div>
<div class="display-field">
#Html.DisplayFor(model => model.rated)
</div>
</fieldset>
#using (Html.BeginForm()) {
<p>
<input type="submit" value="Delete" /> |
#Html.ActionLink("Back to List", "Index")
</p>
}

Related

HttpPost method in controller not coordinating with HttpGet method

I tried to insert a breakpoint before each action and I was stuck at a point when ClassId value in HttpGet method takes the actual(correct)Id of the class which needs to be deleted but ClassId value in HttpPost method does not match with the ClassId value of the HttpGet method, infact value of ClassId in HttpPost returns null due to which I run into an exception error that object has null value. It would be really great if any one can acknowledge me that how that error can be removed. Thanks. Below is the code for the controller and the corresponding view respectively.
Controller Code
[HttpGet]
public IActionResult Delete(int ClassId)
{
return View(db.Class.Include(x => x.Student).First(c => c.ClassId == ClassId));
}
[ActionName("Delete")]
[HttpPost]
public IActionResult DeletePost(int ClassId)
{
var r = db.Class.First(a => a.ClassId == ClassId);
var student = r.StudentId.ToString();
db.Remove(r);
db.SaveChanges();
return RedirectToAction("Details", "Student", new { id = student });
}
View Code
#model DemoProject.Models.Class
#{
ViewData["Title"] = "Delete Class";
}
<h3>Are you sure you want to delete this?</h3>
<div>
<hr />
<dl class="dl-horizontal">
<dt>
#Html.DisplayNameFor(model => model.ClassName)
</dt>
<dd>
#Html.DisplayFor(model => model.ClassName)
</dd>
<dt>
#Html.DisplayNameFor(model => model.Title)
</dt>
<dd>
#Html.DisplayFor(model => model.Title)
</dd>
<dt>
#Html.DisplayNameFor(model => model.Text)
</dt>
<dd>
#Html.DisplayFor(model => model.Text)
</dd>
</dl>
<form asp-action="Delete">
<div class="form-actions no-color">
<input type="submit" value="Delete" class="btn btn-danger" />
<div class="row">
<a asp-action="Details" asp-controller="Student" asp-route-id="#Model.Student.StudentId">Back</a>
</div>
</div>
</form>
</div>
You have two options:
As #stephen.vakil said, add a hidden field for the ClassId property to your view within the <form> element.
View with Hidden Field
#model ModelBinding.Models.Class
#{
ViewData["Title"] = "Delete Class";
}
<h3>Are you sure you want to delete this?</h3>
<div>
<hr/>
<dl class="dl-horizontal">
<dt>
#Html.DisplayNameFor(model => model.ClassName)
</dt>
<dd>
#Html.DisplayFor(model => model.ClassName)
</dd>
<dt>
#Html.DisplayNameFor(model => model.Title)
</dt>
<dd>
#Html.DisplayFor(model => model.Title)
</dd>
<dt>
#Html.DisplayNameFor(model => model.Text)
</dt>
<dd>
#Html.DisplayFor(model => model.Text)
</dd>
</dl>
<form asp-action="Delete">
<div class="form-actions no-color">
#Html.HiddenFor(model => model.ClassId)
<input type="submit" value="Delete" class="btn btn-danger"/>
<div class="row">
<a asp-action="Details" asp-controller="Student" asp-route-id="#Model.Student.StudentId">Back</a>
</div>
</div>
</form>
</div>
Add asp-route-id="#Model.ClassId" to your <form> tag and change the ClassId parameter name of your DeletePost method to id.
View with asp-route-id
#model ModelBinding.Models.Class
#{
ViewData["Title"] = "Delete Class";
}
<h3>Are you sure you want to delete this?</h3>
<div>
<hr/>
<dl class="dl-horizontal">
<dt>
#Html.DisplayNameFor(model => model.ClassName)
</dt>
<dd>
#Html.DisplayFor(model => model.ClassName)
</dd>
<dt>
#Html.DisplayNameFor(model => model.Title)
</dt>
<dd>
#Html.DisplayFor(model => model.Title)
</dd>
<dt>
#Html.DisplayNameFor(model => model.Text)
</dt>
<dd>
#Html.DisplayFor(model => model.Text)
</dd>
</dl>
<form asp-action="Delete" asp-route-id="#Model.ClassId">
<div class="form-actions no-color">
<input type="submit" value="Delete" class="btn btn-danger"/>
<div class="row">
<a asp-action="Details" asp-controller="Student" asp-route-id="#Model.Student.StudentId">Back</a>
</div>
</div>
</form>
</div>
Controller with Renamed Action Parameter
[HttpGet]
public IActionResult Delete(int classId)
{
return View(db.Class.Include(x => x.Student).First(c => c.ClassId == classId));
}
[ActionName("Delete")]
[HttpPost]
public IActionResult DeletePost(int id)
{
var r = db.Class.First(a => a.ClassId == id);
var student = r.StudentId.ToString();
db.Remove(r);
db.SaveChanges();
return RedirectToAction("Details", "Student", new { id = student });
}
Unless you just can't use <hidden> fields for some reason, option 1 is the superior choice.

Previous content of partial view not deleting after return from ajax call

I'm trying to update partialview after ajax call, the partial view is updating but the previous content not deleted from screen.
I have now the prevoious one and the current results on the screen.
That's my code:
public ActionResult FindMovies(string text)
{
ViewBag.ShowButton = Rented;
FindMovie(text);
if (movies.Count == 0)
ViewBag.Movies = "null";
else
ViewBag.Movies = "notNull";
return View(movies);
}
public ActionResult Rent(int id)
{
if (Rented.Equals("no"))
{
movieRent = db.Movies.Find(id);
movieRent.UserRent = userId;
movieRent.Rented = true;
db.Entry(movieRent).State = EntityState.Modified;
db.SaveChanges();
Rented = "yes";
movies.Find(x => x.ID == id).UserRent = userId;
movies.Find(x => x.ID == id).Rented = true;
}
return PartialView("MovieList", movies);
}
That's the view:
<div class="center">
#{Html.RenderPartial("MovieList", Model);}
</div>
and its the partialview:
#model IEnumerable<MvcMovies.Models.Movies>
<ul class="result">
#foreach (var item in Model)
{
<li>
<table>
<tr>
<th>
<figure>
<img src="#Url.Content(#item.Path)"
width="100" height="100" alt="movie logo" />
</figure>
</th>
<th>
<article>
<div class="editor-label">
#Html.DisplayFor(modelItem => item.Name)
</div>
<div class="editor-label">
#Html.DisplayFor(modelItem => item.Year)
</div>
<div class="editor-label">
#Html.DisplayFor(modelItem => item.StageManager)
</div>
<div class="editor-label">
#Html.DisplayFor(modelItem => item.Ganre)
</div>
<div class="editor-label">
#Html.DisplayFor(modelItem => item.Summary)
</div>
<div class="rent" id="rent">
#if (item.Rented.Equals(true))
{
<label>Rented</label>
}
else
{
#Ajax.ActionLink("Rent",
"Rent",
"Subscription",
new { id = item.ID },
new AjaxOptions()
{
UpdateTargetId = "rent",
OnComplete = "onAjaxComplete",
HttpMethod = "post",
})
}
</div>
</article>
</th>
</tr>
</table>
</li>
}
</ul>
Thanks.

Display message using view bag without refreshing view

I have a view A From ControllerA Which has two buttons 1. Create 2. Update
Upon clicking update or Create its opening a new partial viewB As popup from another controller B.
What iam trying to get is If a record is created successfully in b I am now closing the popup. Apart from closing the popup I want to display a message in view A.
I am trying like this:
Controller B
public ActionResult Create(FormCollection args)
{
var obj = new ProjectManagernew();
var res = new ProjectViewModelNew();
try
{
UpdateModel(res);
if (obj.AddUpdateOrderField(res))
{
ViewBag.RecordAdded = true;
ViewBag.Message = "Project Added Successfully";
}
return View(res);
}
catch (Exception)
{
//ModelState.AddRuleViolations(res.GetRuleViolations());
return View(res);
}
}
And in the view A:
#if(ViewBag.Message!=null)
{
#ViewBag.Message
}
View B:
#model DreamTrade.Web.BL.ViewModels.ProjectViewModelNew
#{
ViewBag.Title = "Create";
Layout = "~/Views/Shared/_Layout_Popup.cshtml";
}
#if (ViewBag.RecordAdded != null && (bool)ViewBag.RecordAdded)
{
<script type="text/javascript">
parent.$.nmTop().close();
$('#jqgprojectnew').text("Record added successfully");//jqgprojectnew is the name of grid in view A
</script>
}
<h2>Create</h2>
#using (Html.BeginForm()) {
#Html.ValidationSummary(true)
<fieldset>
<legend>Project</legend>
#Html.HiddenFor(model => model.ProjectID)
<div class="editor-label">
#Html.LabelFor(model => model.ProjectDetail)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.ProjectDetail)
#Html.ValidationMessageFor(model => model.ProjectDetail)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.ProjectRef)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.ProjectRef)
#Html.ValidationMessageFor(model => model.ProjectRef)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.ProjectName)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.ProjectName)
#Html.ValidationMessageFor(model => model.ProjectName)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.StatusList)
</div>
<div class="editor-field">
#Html.DropDownListFor(model => model.ProjectStatusId,new SelectList(Model.StatusList,"SourceStatusId","Description"),"Please Select")
#Html.ValidationMessageFor(model => model.ProjectStatusId)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.CustomerList)
</div>
<div class="editor-field">
#Html.DropDownListFor(model => model.Id,new SelectList(Model.CustomerList,"Id","Name"),"Please Select")
#Html.ValidationMessageFor(model => model.Id)
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
<div>
Back to list
</div>
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
please let me know where iam doing wrong
Include a label field where you want to show the message.
<label id=mylabel></label>// Add this before jqgrid
Modify the code to:
#if (ViewBag.RecordAdded != null && (bool)ViewBag.RecordAdded)
{
<script type="text/javascript">
parent.$.nmTop().close();
$('#mylabel').text("Record added successfully");
</script>
}

Required data annotation is not working on a DropDownlist inside my asp.net mvc3

i have defined the following in my validation model class
public class Visit_Validation
{
[Display(Name = "Assign to Doctor")]
[Required(ErrorMessage= "Please select a Doctor")]
public string DoctorID { get; set; }}
Then i have created the DoctorID Selectlist as follow:-
public ActionResult Create(int patientid)
{
Visit visit = new Visit();
var allusers = Membership.GetAllUsers();
ViewBag.DoctorID = new SelectList(allusers, "Username", "Username");
return View(visit);
}
and finally i define the dropdownlist at the view as follow:-
<div class="editor-label">
#Html.LabelFor(model => model.DoctorID)
</div>
<div class="editor-field">
#Html.DropDownList("DoctorID", String.Empty)
#Html.ValidationMessageFor(model => model.DoctorID)
</div>
but the problem i am facing is that incase the user leave the DoctorID dropdownlist empty then the [Required(ErrorMessage= "Please select a Doctor")] error will not be displayed? so what might be going wrong?
BR
Update:-
here is the full view code:-
<h2>Create</h2>
#section scripts{
<script src="#Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>}
#using (Html.BeginForm()) {
#Html.ValidationSummary(true)
<fieldset>
<legend>Visit</legend>
<div class="editor-label">
#Html.LabelFor(model => model.VisitTypeID, "VisitType")
</div>
<div class="editor-field">
#Html.DropDownList("VisitTypeID", String.Empty)
#Html.ValidationMessageFor(model => model.VisitTypeID)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Date)
</div>
<div class="editor-field">
#Html.TextBoxFor(model => model.Date, new { value = "FL", disabled = "disabled" })
#Html.ValidationMessageFor(model => model.Date)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Note)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Note)
#Html.ValidationMessageFor(model => model.Note)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.DoctorID)
</div>
<div class="editor-field">
#Html.DropDownList("DoctorID", String.Empty)
#Html.ValidationMessageFor(model => model.DoctorID)
</div>
<div class="editor-label">
Visit Status
</div>
<div class="editor-field">
#Html.TextBoxFor(model => model.VisitStatu.Description, new { value = "FL", disabled = "disabled" })
</div>
<div class="editor-label">
#Html.LabelFor(model => model.CreatedBy)
</div>
<div class="editor-field">
#Html.TextBoxFor(model => model.CreatedBy, new { value = "FL", disabled = "disabled" })
#Html.ValidationMessageFor(model => model.CreatedBy)
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
}
here is the Post action method code:-
[HttpPost]
public ActionResult Create(Visit visit)
{
if (ModelState.IsValid)
{
visit.StatusID = repository.GetVisitStatusByDescription("Assinged");
visit.CreatedBy = User.Identity.Name;
visit.Date = DateTime.Now;
repository.AddVisit(visit);
repository.Save();
return RedirectToAction("Index");
}
ViewBag.DoctorID = new SelectList(Membership.GetAllUsers(), "Username", "Username");
ViewBag.StatusID = new SelectList(repository.FindAllVisitStatus(), "StatusID", "Description");
ViewBag.VisitTypeID = new SelectList(repository.FindAllVisitType(), "VisitTypeID", "Description");
return View(visit);
}
In order for validation to be triggered you need to have your POST controller action take the model as parameter:
[HttpPost]
public ActionResult Create(Visit visit)
{
...
}
or use the TryUpdateModel method:
[HttpPost]
public ActionResult Create()
{
Visit visit = new Visit();
if (!TryUpdateModel(visit))
{
// validation failed
}
...
}
When the form is submitted to this controller action the default model binder will invoke the validation rules contained in this Visit model. If your controller action never works with this model there's nothing out there that will ever interpret the data annotations that you put on it.

How do I bind relational data to a model in ASP.net MVC?

I am trying to make an editor for an object in ASP.net MVC 3. It looks something like this:
<div class="editor-label">
#Html.LabelFor(model => model.Name)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Name)
#Html.ValidationMessageFor(model => model.Name)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.foo)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.foo)
#Html.ValidationMessageFor(model => model.foo)
</div>
#if (Model.Items.Count > 0)
{
<table>
#foreach (var ii in Model.Items)
{ #Html.EditorFor(item => ii) }
</table>
}
In this example, Items is a list of another kind of object. The problem is, when the model is posted back from being edited in the view, the data changes to Model.Items aren't there, while the data changes to Name and foo work. How can I make it so that the data for Items binds correctly?
Model class:
public class HomeControllerModel
{
public string Name { get; set; }
public string foo { get; set; }
public List<string> Items { get; set; }
public HomeControllerModel()
{
Items = new List<string>();
}
}
Controller class:
public class HomeController : Controller
{
[HttpGet]
public ActionResult Index()
{
var model = new HomeControllerModel();
model.Name = "LukLed";
model.foo = "bar";
model.Items.Add("AAA");
model.Items.Add("BBB");
model.Items.Add("CCC");
return View(model);
}
[HttpPost]
public ActionResult Index(HomeControllerModel model)
{
return View(model);
}
View:
#using MvcApplication4.Controllers
#model HomeControllerModel
#{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<title>Index</title>
</head>
<body>
<div>
<form action="/Home/Index" method="post">
<div class="editor-label">
#Html.LabelFor(model => model.Name)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Name)
#Html.ValidationMessageFor(model => model.Name)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.foo)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.foo)
#Html.ValidationMessageFor(model => model.foo)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Items)
</div>
<input type="submit" value="Submit" />
</form>
</div>
</body>
</html>
You don't have to iterate through Items.

Resources