I have two tables employee and employee course in a one-to-many relation.
Needs: update name in table employee and courseid in employeecourse table in edit view
Problem: when click submit button in edit view it delete all data and save only selected
Courses from drop down courses just now
If no changes happen to courses by(add or remove courses) when click submit
Button it delete all
code logic
I try to using logic to delete all data when click submit then save all data
after changes
meaning submit button do two task
delete courses exist before for the employee i edit view
add the courses after all changes done in edit view for this employee
see image below
code
model class EditEmployeeVm
public class EditEmployeeVm
{
public int Id { set; get; }
public string Name { get; set; }
public List<SelectListItem> Courses { get; set; }
public int[] CourseIds { set; get; }
public List<CourseVm> ExistingCourses { set; get; }
}
public class CourseVm
{
public int Id { set; get; }
public string Name { set; get; }
}
in edit function get i pass data to edit view
public ActionResult Edit(int id)
{
var vm = new EditEmployeeVm { Id = id };
var emp = db.Employees.FirstOrDefault(f => f.Id == id);
vm.Name = emp.Name;
vm.ExistingCourses = db.EmployeeCourses
.Where(g => g.EmployeeId == id)
.Select(f => new CourseVm
{
Id = f.Id,
Name = f.Course.CourseName
}).ToList();
vm.CourseIds = vm.ExistingCourses.Select(g => g.Id).ToArray();
vm.Courses = db.Courses.Select(f => new SelectListItem
{
Value = f.Id.ToString(),
Text = f.CourseName
}).ToList();
return View(vm);
}
[HttpPost]
public ActionResult Edit(EditEmployeeVm model)
{
**//i need to save name employee changes in employee table and all courses changes in emloyeecourse table
//what is wrong here**
var emp = db.Employees
.Include(e => e.EmployeeCourses)
.FirstOrDefault(f => f.Id == model.Id);
foreach (var eec in emp.EmployeeCourses.ToList())
{
db.EmployeeCourses.Remove(eec);
}
foreach (var couseid in model.CourseIds)
{
db.EmployeeCourses.Add(new EmployeeCourse { CourseId = couseid, EmployeeId = emp.Id });
}
db.SaveChanges();
return View();
}
update
public ActionResult Edit(EditEmployeeVm model)
{
var emp = db.Employees.FirstOrDefault(f => f.Id == model.Id);
foreach (var couseid in model.CourseIds)
{
db.EmployeeCourses.Add(new EmployeeCourse { CourseId = couseid, EmployeeId = emp.Id });
db.SaveChanges();
}
return View();
}
I Try in code above under update section
i can add data and save when click submit button
but problem when click remove button to course by jquery
it remove it but it not save changes of remove in database
so that when open edit view again i see item i removed before
how to solve that when click submit button to save item removed in database
Related
Problem
update changes (name) in employee table
and changes in courses in table EmployeeCourse in database
in Edit function[HTTP post]
Detailes
I have 3 tables Employee,Course,EmployeeCourse
so that when i select employee then edit in courses selected
for this employee by add courses or remove courses
and change in (name)
will save in two tables employee and employee course table
details found in image link
update courses in employee courses and employee data for employee table
code
public class EditEmployeeVm
{
public int Id { set; get; }
public string Name { get; set; }
public List<SelectListItem> Courses { get; set; }
public int[] CourseIds { set; get; }
public List<CourseVm> ExistingCourses { set; get; }
}
public class CourseVm
{
public int Id { set; get; }
public string Name { set; get; }
}
in edit function get i pass data to edit view
public ActionResult Edit(int id)
{
var vm = new EditEmployeeVm { Id = id };
var emp = db.Employees.FirstOrDefault(f => f.Id == id);
vm.Name = emp.Name;
vm.ExistingCourses = db.EmployeeCourses
.Where(g => g.EmployeeId == id)
.Select(f => new CourseVm
{
Id = f.Id,
Name = f.Course.CourseName
}).ToList();
vm.CourseIds = vm.ExistingCourses.Select(g => g.Id).ToArray();
vm.Courses = db.Courses.Select(f => new SelectListItem
{
Value = f.Id.ToString(),
Text = f.CourseName
}).ToList();
return View(vm);
}
[HttpPost]
public ActionResult Edit(EditEmployeeVm model)
{
what code i write here to update changes in two tables
employee and employeecourse
course id as array
}
you can do it with checkbox if the employee is taking a course mark the checkbox like this
<div class="panel panel-default">
<div class="panel-heading">Asignaturas</div>
<div class="panel-body">
<ul class="list-group">
#foreach (var c in cursos)
{
var tomado = false;
foreach (var c2 in Model.Cursos)
{
if (c.id == c2.id)
{
tomado = true;
break;
}
}
<li class="list-group-item">
<label><input type="checkbox" #(tomado ? "checked" : "") name="cursos" value="#c.id" /> #c.Nombre</label>
</li>
}
</ul>
</div>
</div>
I leave the blog where you can see more detailed
Here
and as for the name you can do a partial view and edit it with ajax
when click edit link in index page
it give me error
The model item passed into the dictionary is of type 'System.Data.Entity.DynamicProxies.Employee_2EF71CC17A29BA91B02BC5CDB0EE5AF82D363EEF7E174A21C9546772913AA929', but this dictionary requires a model item of type 'WebCourse.Models.Customemployee'.
I have custom model Customemployee
namespace WebCourse.Models Customemployee
{
public class Customemployee
{
//represent employee table in database
public string Name { get; set; }
public int Salary { get; set; }
public string Email { get; set; }
public int DistrictId { get; set; }
//represent employee course table in database
public List<EmployeeCourse> Courses { get; set; }
//represent employee language table in database
public List<EmployeeLangage> Langs { get; set; }
}
}
and my controller empcourse
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using WebCourse.Models;
using System.Data.Entity;
namespace WebCourse.Controllers
{
public class empcourseController : Controller
{
mycourseEntities db = new mycourseEntities();
// GET: empcourse
public ActionResult Index()
{
var query = db.Employees.ToList().Select(p => new EmpInfo
{
Id = p.Id,
Name = p.Name,
Salary = Convert.ToInt32( p.Salary),
Email = p.Email,
DistrictName = p.Destrict.DistrictName,
CityName = p.Destrict.City.CityName,
CountryName = p.Destrict.City.Country.CountryName,
CourseNames = p.EmployeeCourses.Select(t => t.Course.CourseName).ToList(),
LanguageName = p.EmployeeLangages.Select(t => t.Language.LnaguageName).ToList(),
levelName = p.EmployeeLangages.Select(t => t.Level.LevelName).ToList(),
CourseName = string.Join(",", p.EmployeeCourses.Select(t => t.Course.CourseName).ToList())
});
return View(query);
}
public ActionResult Create()
{
ViewBag.CountryId = new SelectList(db.Countries, "Id", "CountryName");
ViewBag.LanaguageId = new SelectList(db.Languages.ToList(), "Id", "LnaguageName");
ViewBag.LevelId = new SelectList(db.Levels.ToList(), "Id", "LevelName");
ViewBag.CourseId = new SelectList(db.Courses.ToList(), "Id", "CourseName");
return View();
}
public ActionResult Edit(int id)
{
//how to pass data from index view to edit view
Employee old = db.Employees.Find(id);
return View(old);
}
[HttpPost]
public ActionResult Create(Customemployee cemp)
{
using (mycourseEntities db = new mycourseEntities())
{
Employee E = new Employee { Name = cemp.Name, Salary = cemp.Salary, Email = cemp.Email, DistrictId = cemp.DistrictId };
foreach (var i in cemp.Courses)
{
E.EmployeeCourses.Add(i);
db.SaveChanges();
}
foreach (var i in cemp.Langs)
{
E.EmployeeLangages.Add(i);
db.SaveChanges();
}
db.Employees.Add(E);
db.SaveChanges();
}
return View();
}
public JsonResult getcitybyid(int id)
{
db.Configuration.ProxyCreationEnabled = false;
return Json(db.Cities.Where(a => a.CountryId == id), JsonRequestBehavior.AllowGet);
}
public JsonResult getdistrictbyid(int id)
{
db.Configuration.ProxyCreationEnabled = false;
return Json(db.Destricts.Where(a => a.CityId == id), JsonRequestBehavior.AllowGet);
}
}
}
the error show here in code
public ActionResult Edit(int id)
{
//how to pass data from index view to edit view
Employee old = db.Employees.Find(id);
return View(old);
}
How to pass data from index view that show data to edit view
From the error message, it looks like your Edit view is strontly typed to Customemployee type. That means you should be passing an object of Customemployee class from your Edit action method to this view. But your current code is sending an object of Employee type.
So update your Edit action method to send the correct object to the view.
public ActionResult Edit(int id)
{
Employee old = db.Employees.Find(id);
if(old!=null)
{
var vm = new CustomEmployee();
vm.Name = old.Name;
vm.Email = old.Email;
// Assign other property values as needed.
return View(vm);
}
return Content("No employees found for the Id passed");
// to do : Ideally return a "NotFound" view
}
I trying to create a drop down list and bind it to the values fetched from database.
How can I do this. I have done following till now. I want the value of the items of the dropdown ie c.ID in following code to be bind with the Currency_ID of the CountryVM.
public CountryVM()
{
[DisplayName("Country ID")]
[Required]
public string ID { get; set; }
[Required]
[DisplayName("Description")]
public string Description { get; set; }
[DisplayName("Currency Id")]
public Nullable<int> Currency_ID { get; set; }
}
//Controller
DAL library = new DAL();
var items = library.GetAllCurrency(Library.Filter.CURRENCY_SYMBOL);
IEnumerable<SelectListItem> list = items.Select(c => new SelectListItem { Text = c.CURRENCY_SYMBOL, Value = c.ID.ToString() });
ViewBag.curr_symbol = list;
return View();
//In View I am trying to access my DropDown as follows :
#Html.DropDownListFor(model => model.Currency_ID,"curr_symbol" )// how to write this.
Do like this in view:
#
{
SelectList CurrencyList = (SelectList)ViewBag.curr_symbol;
}
#Html.DropDownListFor(model => model.Currency_ID,CurrencyList)
and in action:
IEnumerable<SelectListItem> list = items.Select(c => new SelectListItem { Text = c.CURRENCY_SYMBOL, Value = c.ID.ToString() }).ToList();
or:
var list = (from c in items
select new SelectListItem {Text = c.CURRENCY_SYMBOL,
Value = c.ID.ToString() }).ToList();
Update:
As you told in discussion that it is throwing exception on form post so what you need is to fill the List again and put it in ViewBag in post action as from ViewBag it is removed.
So as I wanted to have a deeper understanding. I added a little bit more functionality to the MSFT tutorial on MVC4 that you can find here (http://www.asp.net/mvc/tutorials/mvc-4/getting-started-with-aspnet-mvc4/intro-to-aspnet-mvc-4)
The model is very simple. You have movies and directors. Every movie has 1 director max.
I want the user to be able to assign a director to a movie from a drop down list and save it but somehow the movie gets saved with a null Director_ID field in the database.
Here are my simple models:
public class Movie
{
public int ID { get; set; }
[Required]
public string Title { get; set; }
public DateTime ReleaseDate { get; set; }
[Required]
public string Genre { get; set; }
public decimal Price { get; set; }
public string Ranking { get; set; }
public Director Director { get; set; }
}
public class Director
{
public int ID { get; set; }
public string Name { get; set; }
}
When the movie table gets generated it comes with a Director_ID field. Sweet!
I would like the user to select a director while editing a movie form a drop down list so
in the movie edit view I managed to bind a drop down list to a list of all directors obtained form the database
<div class="editor-field">
#Html.DropDownListFor(model => model.Director.ID, ViewBag.Directors as List<SelectListItem>, "All")
</div>
Controller:
//GET
public ActionResult Edit(int id = 0)
{
var DirectorsList = new List<SelectListItem>();
var DirQuery = from d in db.Directors select d;
foreach (var d in DirQuery)
{
DirectorsList.Add(new SelectListItem { Value = d.ID.ToString(), Text = d.Name });
}
ViewBag.Directors = DirectorsList;
Movie movie = db.Movies.Find(id);
if (movie == null)
{
return HttpNotFound();
}
return View(movie);
}
I get my list of all directors in my drop down. All right!
Now when I save the movie :
[HttpPost]
public ActionResult Edit(Movie movie)
{
if (ModelState.IsValid)
{
movie.Director = db.Directors.Find(movie.Director.ID);
db.Entry(movie).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
return View(movie);
}
The argument movie that the Edit method receives comes with a Director property (as I specified in the model), when I browse into it I see the two properties form director:
"ID": which comes with the proper value that the user selected form the drop down and "Name": set to null.
As you can see in the code I pick the whole director object form the database matching the drop down value and save it
The problem is that when saving the movie, the foreign key on Movies table (Director_ID) never gets updated.
What am I doing wrong? Is there any better approach for doing this?
Make Id of the Director part of your model, like
public class Movie
{
public int ID { get; set; }
[Required]
public string Title { get; set; }
public DateTime ReleaseDate { get; set; }
...
public int DirectorId { get; set; }
public virtual Director Director { get; set; }
}
Then in your controller:
//GET
public ActionResult Edit(int id = 0)
{
Movie movie = db.Movies.Find(id);
if (movie == null)
{
return HttpNotFound();
}
ViewBag.DirectorId = new SelectList(db.Directors, "DirectorId", "Name", movie.DirectorId);
...
}
And in your view:
<h2>Edit</h2>
#using (Html.BeginForm()) {
#Html.ValidationSummary(true)
<fieldset>
<legend>Movie</legend>
...
<div class="editor-label">
#Html.LabelFor(model => model.DirectorId, "Director")
</div>
<div class="editor-field">
#Html.DropDownList("DirectorId", String.Empty)
#Html.ValidationMessageFor(model => model.DirectorId)
</div>
...
I'm trying to move over to MVC from webforms, and to be honest, it's not going very well.
I need a DropDownList populated with values from my database, and I'm having a hard time understanding how to do this.
I'm thinking, that I need to create a model,using entity framework, and refer my DropDownList to that? But how do I point it to that model?
Also, if I make a model, from a database table, how do I adjust the select command, so I only get certain values, and not the entire table?
I know this is kind of a broad question, and I have no examples listed, but I've had a really hard time, finding information I could understand, with regards to my issue.
I would start from this this should get you the project created if you have not done so so you can have the model ready
http://msdn.microsoft.com/en-us/data/gg685489
in order to create a dropdownlist here is an example
ViewBag.dropdownlist = new SelectList(db.tablename, "Valuefiled", "NameGField");
where Valuefiled=name of a column in your database that you want to use for values
"NameGField"=name of a column in your database that you want to use for names
getting drop down list to view
#Html.DropDownList("dropdownlist")
How About this
Your ViewModel
public class CategoryViewModel
{
public Category Category { get; set; }
public IEnumerable<SelectListItem> CategoryTitles { get; set; }
}
Your Controller
public ActionResult Create()
{
var categoryviewmodel = new CategoryViewModel();
categoryviewmodel.Category = new Category();
var list = categoryRepository.AllCategoryTitles().ToList().Select(t => new SelectListItem
{
Text = t.CategoryName,
Value = t.CategoryID.ToString()
})
.ToList();
list.Insert(0, new SelectListItem { Value = "0", Text = "Please Selext" });
categoryviewmodel.CategoryTitles = list;
return View(categoryviewmodel);
}
Your Repository
public IQueryable<Category> AllCategoryTitles()
{
var query = context.Categories.Where(m => m.ParentCategoryID == null && m.IsActive==true);
return query;
}
Your View
#Html.DropDownListFor(model => model.CategoryParentID, Model.CategoryTitles)
You can use a viewModel. Here is an example solution with some assumptions. Refer to the dropdownlist (here in the dropdown I am listing departments of type "InBound"
Employee Model
public class EmployeeModel
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public int DeptId { get; set; }
}
Department Model
public class DepartmentModel
{
public int Id { get; set; }
public string Name { get; set; }
public string Type { get; set; }
}
ViewModel (to be passed into the view)
public class EmployeeViewModel
{
public EmployeeModel Employee { get; set; }
public IEnumerable<DepartmentModel> Departments { get; set; }
}
Controller
public ActionResult Index()
{
EmployeeViewModel vm = new EmployeeViewModel();
//This is hardcoded. However you will write your own method to pull the department details with filtering
List<DepartmentModel> departments = new List<DepartmentModel>() { new DepartmentModel { Id = 1, Name = "Accounts", Type = "InBound" }, new DepartmentModel { Id = 2, Name = "Finance", Type = "OutBound" }, new DepartmentModel { Id = 3, Name = "HR", Type = "InBound" } };
vm.Departments = departments.Where(d => d.Type == "InBound");
return View(vm);
}
View
#model Test1.ViewModels.EmployeeViewModel
#{
ViewBag.Title = "Index";
}
<h2>Index</h2>
#using (Html.BeginForm())
{
#Html.HiddenFor(model => model.Employee.Id);
<table>
<tr>
<td>#Html.LabelFor(model => model.Employee.FirstName)</td>
<td>#Html.EditorFor(model => model.Employee.FirstName)</td>
</tr>
<tr>
<td>#Html.LabelFor(model => model.Employee.LastName)</td>
<td>#Html.EditorFor(model => model.Employee.LastName)</td>
</tr>
<tr>
<td>#Html.Label("Department")</td>
<td>#Html.DropDownListFor(model => model.Employee.DeptId, new SelectList(Model.Departments, "Id", "Name"))</td>
</tr>
</table>
}