asp.net MVC 4 Telerik Grid Ajax issue - c#

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();

Related

ASP.NET Core 2.0/Razor Pages - How can I persist data in a NonFactors MVC6 grid between requests?

I'm using the NonFactors MVC6.Grid. I'm pretty much just using the base grid:
#(Html
.Grid(Model.Parts)
.Build(columns =>
{
columns.Add(model => model.PartNumber).Titled("Part Number");
columns.Add(model => model.Description).Titled("Description");
columns.Add(model => model.ProductCode).Titled("Product Code");
columns.Add(model => model.Warehouse).Titled("Warehouse");
})
.Filterable()
.Sortable()
.Pageable(pager =>
{
pager.RowsPerPage = 20;
})
)
As you can see, the grid is bound to the Parts property of the model:
[BindProperty]
public List<PartModel> Parts { get; set; } = new List<PartModel>();
The problem I'm having is that when I sort or filter on the MVC6.Grid, it does a POST since the data doesn't persist between requests, the grid ends up trying to sort on nothing.
Parts is populated by a search function. Is the only way to do this is re-populate parts when the grid performs a post? And if that's the case, is there a way to tie into the post event?
Ideally, it would be great if the grid could sort and filter local data without posting.
I use this also and you're doing essentially what I have done (I'm using it with Razor Pages). In my case, the paging (or sorting) does a get and I hooked into the Razor pages OnGet() where I dump the list back out (I'm using Dapper for the querying).
Code behind
public void OnGet()
{
using (var conn = SiteUtilities.DbConnection())
{
this.Articles = conn.Query<Article>("select * from article order by title");
}
}
public IEnumerable<Article> Articles { get; set; }
Razor Page
<div class="table-responsive">
#(Html
.Grid(Model.Articles)
.Build(columns =>
{
columns.Add(model => model.title).Titled("title").Encoded(false).RenderedAs(model => $"<a href='/{model.href}'>{model.title}</a>");
columns.Add(model => model.href).Titled("href");
columns.Add(model => model.update_time).Titled("Last Updated").RenderedAs(m => SiteUtilities.UtcToEasternTime(m.update_time));
columns.Add(model => model.username).Titled("Last Updated By");
columns.Add(model => model.locked).Titled("Locked").RenderedAs(model => model.locked ? "True" : "False");
columns.Add(model => model.views).Titled("Views").RenderedAs(model => model.views.ToString());
})
.Filterable()
.Sortable()
.Pageable()
.Css("table table-sm table-striped table-hover")
)
</div>
I've been researching the plumbing of this over the last few days as well. He just put out a version 3 and it has more examples on his demo site, if you're still interested you might give that a look.

Render partial view in MVC using action result, ObjectContext disposed

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.

Nhibernate, after insert, selecting the table results are old

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

Get DropDownList item, make database query and send the results to another webpage

I have controller that get list of objects from my database and return this list:
public ActionResult Index()
{
var list = db.MyObjects.Where(x => x.family == "Web").ToArray();
list = list.Distinct(new MyObjectByProtocolComparer())
.OrderBy(x => x.fileName)
.ToArray();
ViewBag.Files = list;
return View();
}
Index.cshtml:
This return list is inserted into DropDownList:
#using (Html.BeginForm())
{
<div>
#Html.DropDownList(
"File", new SelectList(ViewBag.Files,
"protocol_site", "protocol_site"),
"Select webmail site",
new { style = "vertical-align:middle;" }
)
<button type="submit">Select</button>
</div>
}
After choose one item from and hit the button my other controller method is get the DropDownList item name and make new database query:
[HttpPost]
public ActionResult Index(string File)
{
var list = db.MyObjects.Where(x => x.protocol == File).ToArray();
ViewBag.Files = list;
return View();
}
What happen now is that the new query is inserted again into my DropDownList but i want this list to send to another page and from this page i wand to show this over ListView.
how can i do that ?
If you want to send it to another view, you'd better redirect to a new action instead of displaying your form again !
[HttpPost]
public ActionResult Index(string File)
{
// Some validation logic
return RedirectToAction("ShowList", new { protocol = File });
}
public ActionResult ShowList(string protocol)
{
var list = db.MyObjects.Where(x => x.protocol == protocol).ToArray();
ViewBag.Files = list;
return View();
}
The view called ShowList will display your items as a listView if it is what you defined.
EDIT :
As you want to display your list in the same view, you have to give a different name to your list, because ViewBag.Files is already used by your drop down list.
Also, as you want to update your list based on your current selection in the drop down list, i suggest you to use Ajax helpers. Here's a good link about this : http://geekswithblogs.net/blachniet/archive/2011/08/03/updating-partial-views-with-unobtrusive-ajax-in-mvc-3.aspx
Basically, your view (index.cshtml) should use an Ajax form, and prepare a empty div containing your list. The action called by your form would return a partial view, inserted in that div, without refreshing the whole view.

ASP.NET MVC 3 - multiple checkbox list

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

Categories