I am trying to populate a partial view using the following in my view:
#{Html.RenderAction("AppointmentsView", "Appointment", new { id = Model.PatientId });}
My action result is as follows:
public ActionResult AppointmentsView(int id)
{
using (var context = new WaysToWellnessDB())
{
IEnumerable<AppointmentDiary> appointments = context.AppointmentDiaries.Where(a => a.PatientId == id).ToList();
var accountUsers = context.AccountUsers.Select(rr => new SelectListItem { Value = rr.AccountUserId.ToString(), Text = rr.FirstName + " " + rr.LastName }).ToList();
ViewBag.AccountUsers = accountUsers;
var location = context.Locations.Select(rr => new SelectListItem { Value = rr.LocationId.ToString(), Text = rr.LocationDesc }).ToList();
ViewBag.Location = location;
return PartialView("/Views/Patient/Appointment/_ViewAppointments.cshtml", appointments);
}
}
My partial view is as follows:
#foreach (var item in Model)
{
<tr>
<td>#Html.DisplayFor(x => item.DateTimeScheduled)</td>
<td>#Html.DisplayFor(x => item.AppointmentLength)</td>
<td>#Html.DisplayFor(x => item.AccountUser.FirstName) #Html.DisplayFor(x => item.AccountUser.LastName)</td>
<td>#Html.DisplayFor(x => item.Location.LocationDesc)</td>
<td>#Html.DropDownListFor(x => item.AttendedStatusId, (IEnumerable<SelectListItem>)ViewBag.AppointmentStatus, null, htmlAttributes: new { #class = "form-control", #id = "appointmentStatusId", onchange = "alert(this.options[this.selectedIndex].value);" })</td>
</tr>
}
This is falling down, saying the following:
The ObjectContext instance has been disposed and can no longer be used for operations that require a connection.
I tried using .Inlcude in my linq query, but this hasn't worked.. any thoughts on why this isn't working?
The answer as posted by Alexander Derck was that I needed to include System.Data.Entity in my using statements at the top, then the following worked.
public ActionResult AppointmentsView(int id)
{
using (var context = new WaysToWellnessDB())
{
IEnumerable<AppointmentDiary> appointments = context.AppointmentDiaries.Include(p => p.AccountUser).Include(p => p.AttendedStatus).Include(p => p.Location).Where(a => a.PatientId == id).ToList();
return PartialView("/Views/Patient/Appointment/_ViewAppointments.cshtml", appointments);
}
}
You have implemented "using" block, which disposes the object once done executing the "using" block. So when you are trying to access the virtual properties "item.AccountUser.FirstName", as the context object has already disposed, it is throwing "The ObjectContext instance has been disposed" error.
As posted by Alexander Derck, using include will resolve this issue because you are including all the required virtual properties in advance when the context object is still alive.
hope this explains.
Related
I get the below excption:
Exception of type 'System.InvalidOperationException' occurred in System.Core.dll but was not handled in user code
Additional information: The sequence does not contain Elements.
at line
var kategoria = db.Kategorie.Include("Kursy").Where(k => k.NazwaKategorii.ToUpper() == nazwaKategori.ToUpper()).Single();
My KursyController.cs:
using SklepInternetowy1.DAL;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace SklepInternetowy1.Controllers
{
public class KursyController : Controller
{
private KursyContext db = new KursyContext();
// GET: Kursy
public ActionResult Index()
{
return View();
}
public ActionResult Lista(string nazwaKategori)
{
var kategoria = db.Kategorie.Include("Kursy").Where(k => k.NazwaKategorii.ToUpper() == nazwaKategori.ToUpper()).Single();
var kursy = kategoria.Kursy.ToList();
return View(kursy);
//return View();
}
public ActionResult Szczegoly(string id)
{
var kurs = db.Kursy.ToList();
return View(kurs);
//return View();
}
[ChildActionOnly]
public ActionResult KetagorieMenu()
{
var kategorie = db.Kategorie.ToList();
return PartialView("_KategorieMenu", kategorie);
}
}
}
My Lista.cs
#{
ViewBag.Title = "Lista";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<div id="strona">
#Html.Action("KetagorieMenu")
<img src="../Content/Images/dommaly.png" width="5%" height="5%" />
<a href="link">
Start > ASP.NET
</a>
#Html.Partial("_KursyList")
My _KategorieMenu.cshtml:
#model IEnumerable<SklepInternetowy1.Models.Kategoria>
#using SklepInternetowy1.Infrastructure
<tabela>
<wiersz>
#foreach (var kategoria in Model)
{
<komorka>
<a href="#Url.Action("Lista","Kursy", new { nazwaKategori = kategoria.NazwaKategorii.ToString() })"
style="background-image: url(#Url.IkonyKategoriiSciezka(kategoria.NazwaPlikuIkony)); ">
#kategoria.NazwaKategorii
</a>
</komorka>
}
</wiersz>
My _KursyList.cshtml:
#model IEnumerable<SklepInternetowy1.Models.Kurs>
#using SklepInternetowy1.Infrastructure
<div id="zawartosc">
<tabela>
<wiersz>
#foreach (var kurs in Model)
{
<komorka>
<a class="dodajDoKoszykaLink" href="#Url.Action("DodajDoKoszyka","Koszyk",new {id = kurs.KursID})">
</a>
#if (kurs.Bestseller)
{
}
<a class="kursSzczegolyLink" href="#Url.Action("Szczegoly","Kursy",new {id =kurs.KursID})">
<img class="kurs" src="#Url.ObrazkiSciezka(kurs.NazwaPlikuObrazka)" width="66%" height="66%" />
<h1>
#kurs.TytulKursu - #kurs.AutorKursu
</h1>
</a>
</komorka>
}
</wiersz>
</tabela>
How to solve this problem?
In this line:
var kategoria = db.Kategorie
.Include("Kursy")
.Where(k => k.NazwaKategorii.ToUpper() == nazwaKategori.ToUpper())
.Single();
You're calling .Single(), which means you're asserting that there is always exactly one record returned in the result. The error is telling you that no records were returned in the result, so the call to .Single() fails.
Since it's possible for no records to be returned in the result, instead use .SingleOrDefault() and check the result for null. Something like this:
var kategoria = db.Kategorie
.Include("Kursy")
.Where(k => k.NazwaKategorii.ToUpper() == nazwaKategori.ToUpper())
.SingleOrDefault();
if (kategoria == null)
{
// no record was found.
// handle that situation in whatever way makes sense for your system.
}
If it's also possible that multiple records can be returned then you'd need to check for that as well, since both .Single() and .SingleOrDefault() will throw an error for multiple results (as their names imply, really). Things like .FirstOrDefault() or additional .Where() clauses, etc. can be helpful to find the record you want in that case.
Using MS VS 2012, C#.net, Nhibernate.
Im inserting a new row.
[HttpPost]
public ActionResult AddQuestion(ModuleAddQuestionModel model)
{
if (!_moServices.Authoriser.Authorise(AcademyPermissions.AccessDeveloperArea))
return new HttpUnauthorizedResult();
if (model == null)
return HttpNotFound();
int modelId = 0;
var module = _moduleService.GetModule(model.ModuleId);
// if null
if(model != null)
{
modelId = model.ModuleId;
}
var addQuestion = new Question()
{
Text = model.Question,
QuestionType = model.QuestionType,
Published = model.Published,
Country = module.Country,
Module = module
};
_moduleService.SaveQuestion(addQuestion);
return RedirectToAction(
"Edit",
"Module",
new { Id = modelId }
);
}
redirect calls
public ActionResult Edit(int Id) {
if (!_moServices.Authoriser.Authorise(AcademyPermissions.AccessDeveloperArea))
return new HttpUnauthorizedResult();
var module = _moduleService.GetModule(Id);
if(module == null)
return HttpNotFound();
var model = new ModuleEditModel {
Id = module.Id,
Name = module.Name,
Questions = module.Questions
.Where(x => !x.Deleted)
.Select(x => new ModuleEditModel.ModuleQuestionModel {
Id = x.Id,
Question = x.Text
}).ToList(),
Videos = module.Videos.Select(x => new ModuleEditModel.ModuleVideoModel {
Id = x.Id,
Title = x.Name
}).ToList()
};
return View(model);
}
the view displays the results, it should display a list that has the new row, but doesn't, even after f5. I suspect it was caching, but we don't have any caching involved for this whole procedure. Next step was to look into Nhibernate and caching.
the has the 2 relevent methods
public Module GetModule(int id) {
_moduleRepository.Flush();
return _moduleRepository.Get(id);
}
public void SaveQuestion(Question question) {
if (question.Id > 0)
UpdateQuestion(question);
else
InsertQuestion(question);
}
public void InsertQuestion(Question question) {
_questionRepository.Create(question);
_questionRepository.Flush();
_signals.Trigger(ModuleSignalChanged);
}
the .flush command was recently added by me to see if that would help clear the results, but didn't change anything.
looked into Isession.Clear(); but as i understand in our cms this lives outside the scope.
Im wondering what the issue is here, was i on the right tract? is this a NHibernate caching issue? Can anyone offer a solution?
If you require any additional information let me know.
ADDITIONAL INFO:
Yes the insert does populate the Database (MS SQL server 2008)
It appears after a few minutes, if one refreshes the page, the new record is displayed.
Heres the answer
var addQuestion = new Question()
{
Text = model.Question,
QuestionType = model.QuestionType,
Published = model.Published,
Country = module.Country,
Module = module
};
module.Questions.Add(addQuestion);
_moduleService.UpdateModule(module);
Instead of trying to insert a question, i updated the module instead that question is a child element of. This i assume cascades due to the relationship which forces nhibernate to clear cache and check the DB.
I cant confirm this, but this appears to at least solve this problem, if anyone can enlighten me as to why the previous method hasn't worked, ill swap my confirmed answer
This is now fixed. A combination of Ish's suggestion below plus adding calls to #HiddenFor in the view resolved the problem.
I have an ASP.NET MVC 5 web application where users can mark a defect as resolved. I want to display a list of potentially related defects, with check-boxes that users can tick to indicate that yes, this is the same defect, and should also be marked as resolved.
So I have a View Model with a property that is a collection, each member of which contains a defect object property and Boolean IsSameDefect property. This all works fine in the GET action method and in the view. I can display the related defects and tick the boxes.
The problem arises in the POST action when I want to update the data. At this point the property (the collection of potentially related defects) is null. I'm having a hard time trying to figure out how to pass this data back to the controller?
Code as requested ...
// GET: /DefectResolution/Create
public ActionResult Create(int ciid)
{
int companyId = User.CompanyID();
DefectResolutionCreateViewModel drcvm = new DefectResolutionCreateViewModel(ciid, companyId);
return View(drcvm);
}
// POST: /DefectResolution/Create
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(DefectResolutionCreateViewModel drcvm)
{
DefectResolutions currentResolution = drcvm.DefectResolution;
currentResolution.CreatedOn = System.DateTime.Now;
currentResolution.UserID = User.UserID();
if (ModelState.IsValid)
{
unitOfWork.DefectResolutionRepository.Insert(currentResolution);
if (currentResolution.ResolutionStatusID == 2)
{
//code breaks here as drcvm.RelatedUnresolvedDefects is null
foreach (var relatedDefect in drcvm.RelatedUnresolvedDefects)
{
if (relatedDefect.IsSameDefect)
{
DefectResolutions relatedResolution = new DefectResolutions();
relatedResolution.ChecklistID = relatedDefect.RelatedChecklist.ChecklistID;
relatedResolution.CreatedOn = System.DateTime.Now;
relatedResolution.ResolutionNote = currentResolution.ResolutionNote;
relatedResolution.ResolutionStatusID = currentResolution.ResolutionStatusID;
relatedResolution.UserID = User.UserID();
}
}
}
unitOfWork.Save();
return RedirectToAction("Index", new { ciid = currentResolution.ChecklistID });
}
return View(drcvm);
}
In the view ...
#model Blah.ViewModels.DefectResolution.DefectResolutionCreateViewModel
#{
ViewBag.Title = "Create Defect Resolution";
var relatedDefects = Model.RelatedUnresolvedDefects;
}
... and later in the view ...
#for (int i = 0; i < relatedDefects.Count(); i++ )
{
<tr>
<td>
#Html.EditorFor(x => relatedDefects[i].IsSameDefect)
</td>
</tr>
}
I followed Ish's suggestion below, and modified the code to refer to Model.RelatedUnresolvedDefects directly instead of using a variable as I had been doing. This does get me a bit further. The view model's RelatedUnresolvedDefects property is no longer null. But only RelatedUnresolvedDefects.IsSameDefect has a value. RelatedUnresolvedDefects.RelatedChecklist is null. Here's the controller code again showing where it now breaks ...
// POST: /DefectResolution/Create
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(DefectResolutionCreateViewModel drcvm)
{
DefectResolutions currentResolution = drcvm.DefectResolution;
currentResolution.CreatedOn = System.DateTime.Now;
currentResolution.UserID = User.UserID();
if (ModelState.IsValid)
{
unitOfWork.DefectResolutionRepository.Insert(currentResolution);
if (currentResolution.ResolutionStatusID == 2)
{
//prior to change, code used to break here
foreach (var relatedDefect in drcvm.RelatedUnresolvedDefects)
{
if (relatedDefect.IsSameDefect)
{
DefectResolutions relatedResolution = new DefectResolutions();
//code now breaks here because relatedDefect.RelatedChecklist is null
relatedResolution.ChecklistID = relatedDefect.RelatedChecklist.ChecklistID;
relatedResolution.CreatedOn = System.DateTime.Now;
relatedResolution.ResolutionNote = currentResolution.ResolutionNote;
relatedResolution.ResolutionStatusID = currentResolution.ResolutionStatusID;
relatedResolution.UserID = User.UserID();
}
}
}
unitOfWork.Save();
return RedirectToAction("Index", new { ciid = currentResolution.ChecklistID });
}
return View(drcvm);
}
Without knowing your code.I suggest you to use for loop instead of foreach while rendering the defects in View (.cshtml).
Editing Answer based on your code.
Following statement in the view creating problem
var relatedDefects = Model.RelatedUnresolvedDefects;
You should directly iterate over the Model.RelatedUnresolvedDefects property in the loop.
#for (int i = 0; i < Model.RelatedUnresolvedDefects.Count(); i++ )
{
<tr>
<td>
#Html.EditorFor(x => Model.RelatedUnresolvedDefects[i].IsSameDefect)
</td>
</tr>
}
I read tutorial "Creating an Entity Framework Data Model for an ASP.NET MVC Application" from http://www.asp.net/ and wanted to use multiple checkbox list from part 6 - http://www.asp.net/mvc/tutorials/getting-started-with-ef-using-mvc/updating-related-data-with-the-entity-framework-in-an-asp-net-mvc-application
In this tutorial, it is only possible to access these checkbox options (to assign courses to each instrucor) from edit page of instructor. I want to render these checkboxes on the create page, but couldn't adjust codes I've found in this tutorial.
These are parts of the codes that are used to display and use checkboxes for new inputs to database.
HttpGet Edit method
public ActionResult Edit(int id)
{
Instructor instructor = db.Instructors
.Include(i => i.OfficeAssignment)
.Include(i => i.Courses)
.Where(i => i.InstructorID == id)
.Single();
PopulateAssignedCourseData(instructor);
return View(instructor);
}
private void PopulateAssignedCourseData(Instructor instructor)
{
var allCourses = db.Courses;
var instructorCourses = new HashSet<int>(instructor.Courses.Select(c => c.CourseID));
var viewModel = new List<AssignedCourseData>();
foreach (var course in allCourses)
{
viewModel.Add(new AssignedCourseData
{
CourseID = course.CourseID,
Title = course.Title,
Assigned = instructorCourses.Contains(course.CourseID)
});
}
ViewBag.Courses = viewModel;
}
HttpPost Edit method
[HttpPost]
public ActionResult Edit(int id, FormCollection formCollection, string[] selectedCourses)
{
var instructorToUpdate = db.Instructors
.Include(i => i.OfficeAssignment)
.Include(i => i.Courses)
.Where(i => i.InstructorID == id)
.Single();
if (TryUpdateModel(instructorToUpdate, "", null, new string[] { "Courses" }))
{
try
{
if (String.IsNullOrWhiteSpace(instructorToUpdate.OfficeAssignment.Location))
{
instructorToUpdate.OfficeAssignment = null;
}
UpdateInstructorCourses(selectedCourses, instructorToUpdate);
db.Entry(instructorToUpdate).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
catch (DataException)
{
//Log the error (add a variable name after DataException)
ModelState.AddModelError("", "Unable to save changes. Try again, and if the problem persists, see your system administrator.");
}
}
PopulateAssignedCourseData(instructorToUpdate);
return View(instructorToUpdate);
}
private void UpdateInstructorCourses(string[] selectedCourses, Instructor instructorToUpdate)
{
if (selectedCourses == null)
{
instructorToUpdate.Courses = new List<Course>();
return;
}
var selectedCoursesHS = new HashSet<string>(selectedCourses);
var instructorCourses = new HashSet<int>
(instructorToUpdate.Courses.Select(c => c.CourseID));
foreach (var course in db.Courses)
{
if (selectedCoursesHS.Contains(course.CourseID.ToString()))
{
if (!instructorCourses.Contains(course.CourseID))
{
instructorToUpdate.Courses.Add(course);
}
}
else
{
if (instructorCourses.Contains(course.CourseID))
{
instructorToUpdate.Courses.Remove(course);
}
}
}
}
And the view
<div class="editor-field">
<table>
<tr>
#{
int cnt = 0;
List<ContosoUniversity.ViewModels.AssignedCourseData> courses = ViewBag.Courses;
foreach (var course in courses) {
if (cnt++ % 3 == 0) {
#: </tr> <tr>
}
#: <td>
<input type="checkbox"
name="selectedCourses"
value="#course.CourseID"
#(Html.Raw(course.Assigned ? "checked=\"checked\"" : "")) />
#course.CourseID #: #course.Title
#:</td>
}
#: </tr>
}
</table>
</div>
So, I want to insert multiple choices (select choices) to database, but would like to display this list of checkboxes immediately on the create page, not the edit page like it was done in the tutorial. If you have another solution that is not related to this tutorial, I would also be grateful. I know that I can't use these methods because they're methods for Edit, so they're takin "id" as parameter, but I hope that I can adjust them to be used in create page of my entity.
Consider using a partial view to isolate the control you're trying to render on both pages, you just need to make sure your model lines up with what the model for your view is.
http://mvc4beginner.com/Tutorial/MVC-Partial-Views.html
i am facing an issue with mvc telerik grid
there is my view :
#(Html.Telerik().Grid(Model.EmployeeList)
.Name("EmployeeGrid")
.Columns(colums =>
{
colums.Bound(e => e.First_Name);
colums.Bound(e => e.Last_Name);
colums.Bound(e => e.Hire_Date);
colums.Bound(e => e.Home_Phone);
})
.DataBinding(dataBinding => dataBinding.Ajax().Select("_AjaxBinding", "Home"))
.Groupable()
.Sortable()
.Pageable(paging=>paging.PageSize(10))
.Filterable()
)
and there is my controller code
[AcceptVerbs(HttpVerbs.Post)]
[GridAction]
public ActionResult _AjaxBinding(GridCommand command)
{
using (var contax=new NorthwindEntities()){
int pagesize=command.PageSize;
int page=command.Page;
var EmployeeList = (from items in contax.Employees
select new
{
items.First_Name,
items.Last_Name,
items.Hire_Date,
items.Home_Phone
});
return View(new GridModel
{
Data = EmployeeList
});
}
}
on load the data is loaded correctly from database but internal server error 500 occur when i click on paging or sort data.
thanks in advance.
you are using a Linq query inside a disposable scope.but the query execution is deferred until using it (when you have left using {} scope).
and you'r context is disposed!
solution :
add .ToList at the end of query :
var EmployeeList = (from items in contax.Employees
select new
{
items.First_Name,
items.Last_Name,
items.Hire_Date,
items.Home_Phone
}).ToList();