I have a page that displays a list of courses for an individual. The page allows a user to delete a course from the selected users course list. When the delete button is clicked, that course should be deleted from the course list and the list of courses should be re-displayed. In my controller I was trying to delete the record, then call the listCourses view (view that initially lists the courses for a user) but when I click the delete button, nothing happens. Below is my code:
View to select a student:
#foreach (var stu in Model)
{
<tr>
<td class="stulisttd">
#stu.Id
</td>
<td class="stulisttd">
#stu.fname
</td>
<td class="stulisttd">
#stu.lname
</td>
<td class="thEditButton">
#using (Ajax.BeginForm("addCourses", "ManageStudentCourses", stuEditCourses))
{
#Html.TextBox("stuId", (string)stu.Id, new { #class = "listCourseText" })
<input type="submit" id="addCourses" name="addCourses" value='Add Courses' class="AllTracksButtons" />
}
</td>
<td class="thEditButton">
#using (Ajax.BeginForm("listCourses", "ManageStudentCourses", stuEditCourses))
{
#Html.TextBox("stuId", (string)stu.Id, new { #class = "listCourseText" })
<input type="submit" value="List Courses" class="AllTracksButtons" id=#stu.Id />
}
</td>
</tr>
}
View that lists the courses for user selected:
#foreach (var course in Model)
{
using (Ajax.BeginForm("deleteCourses", "ManageStudentCourses", stuListEditCourses))
{
<tr class="trCourseList">
<td>
#course.courseAbNum
#Html.TextBox("courseAbNum", (string)course.courseAbNum, new { #class = "editCourseText" })
</td>
<td>
#course.courseDesc
</td>
<td>
#course.status
</td>
<td>
#course.grade
</td>
<td>
#course.credits
</td>
<td>
<input type="submit" value="Delete" class="courseListButtons" id="displayEdit" />
</td>
</tr>
}
deleteCourses controller:
public PartialViewResult deleteCourses(string courseAbNum)
{
KuPlanEntities db = new KuPlanEntities();
var deleteCourse = (from course in db.COURSE_TAKEN
where course.courseAbNum == courseAbNum && course.Id == "000160228"
select course);
foreach (var course in deleteCourse)
{
db.COURSE_TAKEN.Remove(course);
db.SaveChanges();
}
var stuCourses = (from studCourse in db.COURSE_TAKEN
join course in db.COURSEs on studCourse.courseAbNum equals course.courseAbNum
where studCourse.Id == "000160228"
select new courseListViewModel { id = studCourse.Id, courseAbNum = studCourse.courseAbNum, status = studCourse.status, grade = studCourse.grade, courseDesc = course.courseDesc, credits = course.credits });
return PartialView("~/Views/ManageStudentCourses/listCourses.cshtml", stuCourses);
}
I think you're going to have an issue with this code
foreach (var course in deleteCourse)
{
db.COURSE_TAKEN.Remove(course);
db.SaveChanges();
}
You'll likely get the error "Collection was modified; enumeration operation may not execute."
To get around this you can use this hack
while (db.COURSE_TAKEN.Where(x => x.ID == ID).Count() != 0)
{
COURSE_TAKEN course = db.COURSE_TAKEN.Where(x => x.ID == ID).FirstOrDefault();
db.COURSE_TAKEN.Remove(course);
db.SaveChanges();
}
Hope this helps.
Related
I am getting an exception when i trying to display the values of viewbag. I have joined two tables and stored that data in viewbag using Linq.
This is my controller action method
public ActionResult HRSeparationDetails()
{
//List<trnEsSeparationDetail> separationlist = (from list in db.trnEsSeparationDetails
// select list).ToList();
ViewBag.SeparationList = (from list in db.trnEsSeparationDetails
join R in db.mstEsEmpReasonForSeparations
on list.ReasonForSeperationId equals R.intSeperationId
select new
{
intEmployeeId = list.intEmpId,
ReasonForSeparation = R.txtReasonForSeperation,
ResiganationDate = list.dtResignationDate,
RelievingDate = list.dtRequestedRelievingDate,
SeparationRemarks = list.txtRemark
}).ToList();
return View();
}
This is my viewpage
#model IEnumerable<EMPApp.Models.trnEsSeparationDetail>
#{
ViewBag.Title = "HRSeparationDetails";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>HRSeparationDetails</h2>
<div>
#if (ViewBag.SeparationList == null)
{
<div style="color:green"><h3>#ViewBag.SeparationerrorMessage</h3></div>
}
else
{
<table class="grid" cellpadding="0" cellspacing="0">
<tr>
<th>
<b>Employee Id</b>
</th>
#*<th>
<b>ReasonForSeparationId</b>
</th>*#
<th>
<b>Reason For Separation</b>
</th>
<th>
<b>Resignation Date</b>
</th>
<th>
<b>Relieving Date</b>
</th>
<th>
<b>Separation Remarks</b>
</th>
</tr>
#foreach (var item in ViewBag.SeparationList)
{
<tr>
<td>
#item.intEmployeeId
#*#{
Session["SeparationEmpId"] = item.intEmpId;
}
#Html.ActionLink(Session["SeparationEmpId"].ToString(), "EmployeeDashboard", "HRAdmin", new { id = #item.intEmpId }, null)*#
</td>
#*<td>
#item.ReasonForSeperationId
</td>*#
<td>
#item.ReasonForSeparation
</td>
<td>
#item.ResiganationDate
</td>
<td>
#item.RelievingDate
</td>
<td>
#item.SeparationRemarks
</td>
</tr>
}
</table>
}
Any help will be appreciated. Thanks..
ViewBag is a dynamic object and your setting the property to a collection of anonymous objects. In you foreach loop
#foreach (var item in ViewBag.SeparationList)
item is typeof object and object does not have a property intEmployeeId (or any of the other properties your define in the anonymous object). One way to handle this is to create a view model with the properties you want to display
public class SeparationDetailVM
{
public int intEmployeeId { get; set; }
public DateTime ResiganationDate { get; set; }
....
}
and in the controller
var details = (from list in ....
select new SeparationDetailVM
{
intEmployeeId = list.intEmpId,
ResiganationDate = list.dtResignationDate,
....
}).AsEnumerable();
return View(details); // no need for ViewBag
and in the view
#model IEnumerable<YourAssembly.SeparationDetailVM>
....
#foreach (var item in Model)
{
....
<td>#item.intEmployeeId</td>
<td>#item.ResiganationDate</td>
....
}
I have had look at a few post already here but I am none the wiser. I tried my first example of Ajax but to no avail. The Partial View is loaded into a separate page as opposed to changing the dom element in the current page.
The pupose is by clicking on the Refresh link in updates the "Last Activity Date" value of the current row only.
Please if there is an easy well of doing this can you also let me know?
View:
#model IEnumerable<RegistrationManager.User>
#{
ViewBag.Title = "Users";
}
#section scripts {
#Content.Script(Url, "jquery-unobtrusive-ajax.min.js")
}
<h2>Users</h2>
<table>
<tr>
<th>Email Address</th>
<th>Given Names</th>
<th>Surname</th>
<th>Last Activity Date</th>
<th>Refresh</th>
</tr>
#foreach (var item in Model)
{
string selectedRow = "";
if (ViewBag.UserId != null && item.UserId == ViewBag.UserId)
{
selectedRow = "selectedrow";
}
<tr class="#selectedRow" valign="top">
<td>
#item.UserName
</td>
<td>
#item.Profile.GivenNames
</td>
<td>
#item.Profile.Surname
</td>
<td>
<div id="#String.Format("LastActivityDate{0}", item.UserId)">#Html.Partial("_DateOnlyPartialView", item.LastActivityDate)</div>
</td>
<td>
#Ajax.ActionLink("Refresh", "Refresh",
new { UserId = item.UserId },
new AjaxOptions {
UpdateTargetId = "LastActivityDate" + item.UserId,
InsertionMode = InsertionMode.Replace,
HttpMethod = "GET"
})
</td>
</tr>
}
</table>
Conrtoller:
public PartialViewResult Refresh(Guid? UserId)
{
User user = _db.Users.Find(UserId);
user.RefreshLastActivityDate();
return PartialView("_DateOnlyPartialView", user.LastActivityDate);
}
Have you included/referenced all the necessary javascript files?
If you have UnobtrusiveJavaScriptEnabled then you'll need:
jQuery
jquery.unobtrusive-ajax.js
if you also use client side validation, you'll need;
jquery.validate.js
jquery.validate.unobtrusive.js
These files can all be found when you create a new MVC3 project.
there is my issue. In a controller, I have this method which export my view in a file when I click a button.
public ActionResult Export(string searchString, int searchOrder = 0)
{
var user = from m in db.Orders select m;
if (!String.IsNullOrEmpty(searchString))
{
user = user.Where(s => s.ClientID.Contains(searchString));
}
Response.AddHeader("Content-Type", "application/vnd.ms-excel");
return this.View(user);
}
My Index view :
#model IEnumerable<MyApp.Models.Order>
#{
ViewBag.Title = "Index";
}
<h2>Orders Historic</h2>
<div id="orderDiv">
#using (Html.BeginForm("Export", "Historic", FormMethod.Get))
{
<p>
Generate Order with ClientID :          
#Html.TextBox("searchString")
<input type="submit" value="GENEREMOI" />
</p>
}
</div>
And my Export view :
#model IEnumerable<KrysGroup.Models.Order>
<table cellpadding="3" cellspacing="3">
<tr>
<td width="12%" align="center">
Client Name/ID
</td>
<td width="15%" align="center">
N° Order
</td>
OTHER TD....
</tr>
#foreach (var item in Model)
{
TimeSpan result = DateTime.Now - item.OrderDate;
if (result.Days < 31)
{
<tr border="1" bgcolor="#Odd">
<td> #Html.DisplayFor(modelItem => item.Username) </td>
<td> #Html.DisplayFor(modelItem => item.OrderId) </td>
<td>
<ul style="list-style-type:none; padding:0; margin:0">
#if (item.OrderDetails != null)
{
foreach (var o in item.OrderDetails)
{
if (o.Pack == null)
{
<li> #Html.DisplayFor(modelItem => o.Product.Name) </li>
}
else
{
<li> <text>Pack</text> #Html.DisplayFor(modelItem => o.Pack.Name) </li>
}
}
}
</ul>
</td>
OTHER TD...
</table>
So, in my view, I inform in a textbox a ClientID and when I click the button, it export in a file all the fields in my table with this ClientID.
I would like to automate this action, that is to say I would like write a method or something for, when I click on the button, it executes this export() method for each clientId it meet in my table.
I hope I was clear enough, sorry for my english..
Thanks for your answers, links, tips whatever.
You can write a partial view typed to a list of Id's that loads when you click the button.
So in the controller you have a method converts what you want and returns a view that is typed to the conversion of your model.
In your main view you have a div that will be populated with a partial view after the click-event of the original button.
#Ajax.ActionLink("Name", "NameOfTheAction", "NameOfTheController",
new { id = itemId },
new AjaxOptions { HttpMethod = "Get", UpdateTargetId = "divInMainView", OnSuccess = "Do Something (js)" },
new { html-props })
How to populate is up to you, in your view
I have a table containing user information with image field and storing image in binary data.
I want to show this images on my view page in a table with user information.
my code is..
Controller
public ActionResult About()
{
var data = db.dbtable.ToList();
return View(data);
}
Get Image method // reg is object of dbtable
public FileContentResult GetImage(int id)
{
reg = db.dbtable.FirstOrDefault(i => i.RegNo == id);
if (reg != null)
{
return File(reg.Photo, "image/jpeg");
}
else
{
return null;
}
}
on view page..
#model IEnumerable<MvcMySchool.dbtable>
<table width="50">
<tr>
<th>
Registration No.
</th>
<th>
First Name
</th>
<th>
Last Name
</th>
<th>
City
</th>
<th>
Photo
</th>
</tr>
#foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.RegNo)
</td>
<td>
#Html.DisplayFor(modelItem => item.FirstName)
</td>
<td>
#Html.DisplayFor(modelItem => item.LastName)
</td>
<td>
#Html.DisplayFor(modelItem => item.City)
</td>
<td>
#*HttpContext.Current.Response.Write("<img width="75" height="75" src=#(Url.Action("GetImage", "Home", new { id = item.RegNo })) />")*#
<img width="75" height="75" src=#(Url.Action("GetImage", "Home", new { id = item.RegNo })) />
</td>
</tr>
}
</table>
It only shows the image in the first row and nothing after that.
Thanks..
May make more sense just to keep the path the image.
If you filesteam,
public FileStreamResult GetImage(int id)
{
reg = db.dbtable.FirstOrDefault(i => i.RegNo == id);
if (reg != null)
{
MemoryStream ms = new MemoryStream(reg.Photo);
return File(ms, "image/png");
}
else
{
return null;
}
}
more logical way to keep, ony way
public FileResult GetImage(int id)
{
reg = db.dbtable.FirstOrDefault(i => i.RegNo == id);
if (reg != null)
{
FileInfo fi = new FileInfo(Server.MapPath(reg.Photo));
return File(fi.OpenRead, "image/png");
}
}
for both
<tr>
<td>
<img src="/Home/GetImage/#item.RegNo" alt="" />
</td>
</tr>
I have this view
#model IEnumerable<ViewModelRound2>
... <snip> ...
#{
using (Html.BeginForm(new { round1Ring3Bids = Model }))
{
if (Model != null && Model.Count() > 0)
{
... <snip> ...
#for (var x = 0; x < Model.Count(); x++)
{
ViewModelRound2 viewModelRound2 = Model.ElementAt(x);
Bid bid = viewModelRound2.Bid;
string userName = #bid.User.Invitation.Where(i => i.AuctionId == bid.Lot.Lot_Auction_ID).First().User.User_Username;
<tr>
<td>
#userName
</td>
<td>
#bid.Bid_Value
</td>
<td>
#Html.EditorFor(c => c.ElementAt(x).SelectedForRound2)
</td>
</tr>
}
</table>
<div class="buttonwrapper2">
<input type="submit" value="Select"/>
</div>
}
}
}
I have a post method that this goes to when the submit button is hit
[HttpPost]
public ActionResult Round2Manager(IEnumerable<ViewModelRound2> round1Ring3Bids)
Problem is that the enumeration is always empty. Why is this?
Problem is that the enumeration is always empty. Why is this?
Because you are not respecting the wire format that the default model binder expects to bind collections.
The following:
#Html.EditorFor(c => c.ElementAt(x).SelectedForRound2)
generates absolutely wrong names for your input fields.
I would recommend you using editor templates to avoid those kind of problems:
#model IEnumerable<ViewModelRound2>
#using (Html.BeginForm())
{
if (Model != null && Model.Count() > 0)
{
<table>
#Html.EditorForModel()
</table>
<div class="buttonwrapper2">
<input type="submit" value="Select"/>
</div>
}
}
and then define a custom editor template for the ViewModelRound2 type (~/View/Shared/EditorTemplates/ViewModelRound2.cshtml) which will automatically be rendered for each element of this collection:
#model ViewModelRound2
# {
string userName = Model.Bid.User.Invitation.Where(
i => i.AuctionId == Model.Bid.Lot.Lot_Auction_ID
).First().User.User_Username;
}
<tr>
<td>
#userName
</td>
<td>
#Model.Bid.Bid_Value
</td>
<td>
#Html.EditorFor(c => c.SelectedForRound2)
</td>
</tr>
You will now notice how the text input fields have correct names:
name="[0].SelectedForRound2"
name="[1].SelectedForRound2"
name="[2].SelectedForRound2"
...
Compare this with your initial values.