Map two entities from one table in ASP.NET - c#

I am working on a library management website. As user of the application, I want to be able to create new employees, for example ceo, manager and regular employee. I have done that and it is working.
But I want to be able to the employees to manage each other depending on their role, for example I want the:
CEO to manage managers but not employees
Managers to manage other managers and employees
No one can manage the CEO
To do that I have tried to map managerID against the id of the employee (I don't know if its a good idea):
public partial class Employees
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)] // For autoincrement
//public int EmployeeId { get; set; }
//[Required]
//[Index]
//public int TheManagerId { get; set; } // Manager ID Foreign Key
//[Required]
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public Nullable<decimal> Salary { get; set; }
public Nullable<bool> IsCEO { get; set; }
public Nullable<bool> IsManager { get; set; }
public Nullable<int> ManagerId { get; set; }
}
And this is how my Create.cshtml looks like:
#model LibraryProject.Employees
#{
ViewBag.Title = "Create";
}
<h2>Create</h2>
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>Employees</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(model => model.FirstName, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.FirstName, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.FirstName, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.LastName, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.LastName, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.LastName, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Salary, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Salary, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Salary, "Your input should be an integer between 1-10.", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.IsCEO, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
<div class="checkbox">
#Html.EditorFor(model => model.IsCEO)
#Html.ValidationMessageFor(model => model.IsCEO, "", new { #class = "text-danger" })
</div>
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.IsManager, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
<div class="checkbox">
#Html.EditorFor(model => model.IsManager)
#Html.ValidationMessageFor(model => model.IsManager, "", new { #class = "text-danger" })
</div>
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.ManagerId, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.ManagerId, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.ManagerId, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</div>
</div>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
#using (Html.BeginForm())
{
if (!string.IsNullOrEmpty(ViewBag.ErrorMessage5))
{
<div>
<p>
<span style="color:red;">#ViewBag.ErrorMessage5</span>
</p>
</div>
}
<div class="form-horizontal" />
}
And this is how my Employee controller looks like:
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Linq;
using System.Net;
using System.Web;
using System.Web.Mvc;
using LibraryProject;
namespace LibraryProject.Controllers
{
public class EmployeesController : Controller
{
private LibraryDbEntities db = new LibraryDbEntities();
// GET: Employees
public ActionResult Index()
{
// Linq queries to show all the employees separately, is used to not mixed them up.
var getCeo = from employeCEO in db.Employees
where employeCEO.IsCEO == true
select employeCEO;
var getEmployee = from employee in db.Employees
where employee.IsCEO == false && employee.IsManager == false
select employee;
var getManager = from employeeManager in db.Employees
where employeeManager.IsManager == true && employeeManager.IsCEO == false
select employeeManager;
IEnumerable<Employees> list = getCeo.Concat(getEmployee).Concat(getManager);
return View(list.ToList());
}
public ActionResult CEO()
{
// linq query used to display ceo in a separate view
var getCeo = from employeCEO in db.Employees
where employeCEO.IsCEO == true
select employeCEO;
return View(getCeo);
}
public ActionResult TheManager()
{
// linq query used to display manager in a separate view
var getManager = from employeeManager in db.Employees
where employeeManager.IsManager == true && employeeManager.IsCEO == false
select employeeManager;
return View(getManager);
}
public ActionResult RegularEmployee()
{
// linq query used to display employee in a separate view
var getEmployee = from employee in db.Employees
where employee.IsCEO == false && employee.IsManager == false
select employee;
return View(getEmployee);
}
// GET: Employees/Details/5
public ActionResult Details(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Employees employees = db.Employees.Find(id);
if (employees == null)
{
return HttpNotFound();
}
return View(employees);
}
// GET: Employees/Create
public ActionResult Create()
{
ViewBag.Employees = new SelectList(db.Category, "Id", "Employees");
return View();
}
// POST: Employees/Create
// To protect from overposting attacks, enable the specific properties you want to bind to, for
// more details see https://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "Id,FirstName,LastName,Salary,IsCEO,IsManager,ManagerId")] Employees employees)
{
if (ModelState.IsValid)
{
//salary coefficient for the employees
decimal salaryCeo = 2.725M;
decimal salaryManager = 1.725M;
decimal employeeSalary = 1.125M;
var ceo = db.Employees.Count(x => x.IsCEO == true);
//Checks if there is a ceo
if (ceo == 0)
{
employees.Salary = employees.Salary * salaryCeo; // calculate ceo salary
db.Employees.Add(employees);
db.SaveChanges();
return RedirectToAction("Index");
}
else if (ceo == 1 && employees.IsCEO == true) // check if there is a ceo, if yes show errormessage
{
ViewBag.ErrorMessage5 = "There is already a CEO in the database! You cannot create a second one!";
}
else if(employees.IsCEO == false && employees.IsManager == false) // check if the employee is ceo or manager, if false its a regular employee
{
employees.Salary = employees.Salary * employeeSalary; // calculate regular employees salary
db.Employees.Add(employees);
db.SaveChanges();
return RedirectToAction("Index");
}
else if (employees.IsCEO == false && employees.IsManager == true) // manager
{
employees.Salary = employees.Salary * salaryManager; // manager salary
db.Employees.Add(employees);
db.SaveChanges();
return RedirectToAction("Index");
}
}
return View(employees);
}
// GET: Employees/Edit/5
public ActionResult Edit(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Employees employees = db.Employees.Find(id);
if (employees == null)
{
return HttpNotFound();
}
return View(employees);
}
// POST: Employees/Edit/5
// To protect from overposting attacks, enable the specific properties you want to bind to, for
// more details see https://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit([Bind(Include = "Id,FirstName,LastName,Salary,IsCEO,IsManager,ManagerId")] Employees employees)
{
if (ModelState.IsValid)
{
db.Entry(employees).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
return View(employees);
}
// GET: Employees/Delete/5
public ActionResult Delete(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Employees employees = db.Employees.Find(id);
if (employees == null)
{
return HttpNotFound();
}
return View(employees);
}
// POST: Employees/Delete/5
[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
public ActionResult DeleteConfirmed(int id)
{
Employees employees = db.Employees.Find(id);
db.Employees.Remove(employees);
db.SaveChanges();
return RedirectToAction("Index");
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
db.Dispose();
}
base.Dispose(disposing);
}
}
}
I KNOW IT IS SOME CODE THERE... BUT I HOPE SOMEONE IS OUT THERE TO HELP.
THANKS.

But I want to be able to the employees to manage each other depending on their role, for example I want the:
CEO to manage managers but not employees
Managers to manage other
managers and employees No one can manage the CEO
I think what you want to achieve is Authorize, not the relationship in table.
For how to Customize a Authorize Attribute, You can refer to this thread.

Related

ASP.Net MVC Update entity met with "The entity could not be updated."

I'm fairly new to coding, and am trying to tie up the finishing touches to my personal MVC project. I have done breakpoints to see double-check that the types of the values I'm passing through are matching up, which I believe they are, but it's hard for me to navigate the breakpoints and understand what information I should be looking at.
When I do breakpoints, it skips the final If-statement shown below:
if (service.UpdatePromotion(model))
{
TempData["SaveResult"] = "The promotion has been updated!";
return RedirectToAction("Index");
}
If there is any other information needing to be posted, I'll update here if I can or in the comments. I really appreciate anyone who looks this over.
Controller
// GET: Edit
public ActionResult Edit(int id)
{
var service = CreatePromotionService();
var detail = service.GetPromotionById(id);
var model = new PromotionEdit
{
PromotionId = detail.PromotionId,
PromotionName = detail.PromotionName,
DateFounded = detail.DateFounded,
Website = detail.Website
};
return View(model);
}
// POST: Edit
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(int id, PromotionEdit model)
{
if (!ModelState.IsValid) return View(model);
if (model.PromotionId != id)
{
ModelState.AddModelError("", "ID Mismatch");
return View(model);
}
var service = CreatePromotionService();
if (service.UpdatePromotion(model))
{
TempData["SaveResult"] = "The promotion has been updated!";
return RedirectToAction("Index");
}
ModelState.AddModelError("", "The promotion could not be updated.");
return View(model);
}
Services
public PromotionDetail GetPromotionById(int id)
{
using (var ctx = new ApplicationDbContext())
{
var entity = ctx.Promotions
.Single(e => e.PromotionId == id
&& e.OwnerId == _userId);
return new PromotionDetail
{
PromotionId = entity.PromotionId,
PromotionName = entity.PromotionName,
DateFounded = entity.DateFounded.Date,
Website = entity.Website,
CreatedUtc = entity.CreatedUtc
};
}
}
public bool UpdatePromotion(PromotionEdit model)
{
using (var ctx = new ApplicationDbContext())
{
var entity = ctx.Promotions.Single(e =>
e.PromotionId == model.PromotionId
&& e.OwnerId == _userId);
entity.PromotionName = model.PromotionName;
entity.IsStarred = model.IsStarred;
entity.DateFounded = model.DateFounded.Date;
entity.Website = model.Website;
return ctx.SaveChanges() == 1;
}
}
Model
public class PromotionDetail
{
[Display(Name = "Promotion ID")]
public int PromotionId { get; set; }
[Display(Name = "Promotion Name")]
public string PromotionName { get; set; }
[Display(Name = "Date Founded")]
public DateTime DateFounded { get; set; }
[Display(Name = "Website")]
public string Website { get; set; }
[Display(Name = "Date Created")]
public DateTimeOffset CreatedUtc { get; set; }
}
public class PromotionEdit
{
public int PromotionId { get; set; }
[Display (Name = "Promotion Name")]
public string PromotionName { get; set; }
public bool IsStarred { get; set; }
public DateTime DateFounded { get; set; }
public string Website { get; set; }
}
View
#model Models.PromotionEdit
#{
ViewBag.Title = "Edit";
}
<h2>Updating Promotion</h2>
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
#Html.HiddenFor(model => model.PromotionId)
<div class="form-group">
#Html.LabelFor(model => model.PromotionName, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.PromotionName, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.PromotionName, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.DateFounded, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.DateFounded, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.DateFounded, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Website, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Website, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Website, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Save" class="btn btn-default" />
</div>
</div>
</div>
}
<div id="linkColor">
#Html.ActionLink("Back to List", "Index")
</div>
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
Shout-out to curious.netter in the comments. I was being lazy with the update, not changing anything and clicking Submit. Since there were no changes to apply, the entity would not update, which would skip the last If statement.

ASP.Net MVC Unable to edit user because od the [Compare(Password)] in the class User

I have table named Korisnik (on my language, on english its User) and i added an Edit ActionResult in my Controller , but it wont work because of the [Compare("Lozinka")] that is comparing the password from the database and the added property PotvrdiLozinku, in other words i must enter the Confirm password in order to Submit the changes
namespace ProjekatFinalni.Models
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
public partial class Korisnik
{
public int KorisnikID { get; set; }
[DisplayName("Korisnicko ime:")]
[Required(ErrorMessage ="Molimo vas unesite korisnicko ime.")]
public string Korisnickoime { get; set; }
[DisplayName("Lozinka:")]
[DataType(DataType.Password)]
[Required(ErrorMessage = "Molimo vas unesite lozinku.")]
public string Lozinka { get; set; }
[DisplayName("Admin:")]
public bool DaLiJeAdmin { get; set; }
[DisplayName("Gost:")]
public bool Gost { get; set; }
[DisplayName("Pravo za unos:")]
public bool PravoUnosa { get; set; }
[DisplayName("Potvrdi lozinku:")]
[DataType(DataType.Password)]
[Compare("Lozinka",ErrorMessage ="Lozinke se ne poklapaju.")]
public string PotvrdiLozinku { get; set; }
public string LoginErrorPoruka { get; set; }
}
This is the Edit ActionResult in my controller
public ActionResult Edit(int id)
{
using (BazaProjekatEntities4 dbModel = new BazaProjekatEntities4())
{
return View(dbModel.Korisniks.Where(x => x.KorisnikID == id).FirstOrDefault());
}
}
[HttpPost]
public ActionResult Edit(int id,Korisnik k)
{
try
{
using (BazaProjekatEntities4 dbModel = new BazaProjekatEntities4())
{
dbModel.Entry(k).State = EntityState.Modified;
dbModel.SaveChanges();
}
return RedirectToAction("Izlistaj");
}
catch
{
return View();
}
}
And this is the Edit.cshtml
#model ProjekatFinalni.Models.Korisnik
#{
ViewBag.Title = "Edit";
}
<h2>Edit</h2>
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>Korisnik</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
#Html.HiddenFor(model => model.KorisnikID)
<div class="form-group">
#Html.LabelFor(model => model.Korisnickoime, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Korisnickoime, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Korisnickoime, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Lozinka, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Lozinka, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Lozinka, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.PotvrdiLozinku, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.PotvrdiLozinku, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.PotvrdiLozinku, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.DaLiJeAdmin, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
<div class="checkbox">
#Html.EditorFor(model => model.DaLiJeAdmin)
#Html.ValidationMessageFor(model => model.DaLiJeAdmin, "", new { #class = "text-danger" })
</div>
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Gost, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
<div class="checkbox">
#Html.EditorFor(model => model.Gost)
#Html.ValidationMessageFor(model => model.Gost, "", new { #class = "text-danger" })
</div>
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.PravoUnosa, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
<div class="checkbox">
#Html.EditorFor(model => model.PravoUnosa)
#Html.ValidationMessageFor(model => model.PravoUnosa, "", new { #class = "text-danger" })
</div>
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Sacuvaj" class="btn btn-default" />
</div>
</div>
</div>
}
Only want to edit the permissions(Admin, Gost and PravoUnosa
EDIT( Added the registration form that i used)
[HttpPost]
public ActionResult DodajiliIzmeni(Korisnik korisnikmodel)
{
using (BazaProjekatEntities4 Modelkorisnik = new BazaProjekatEntities4())
{
if(Modelkorisnik.Korisniks.Any(x=> x.Korisnickoime == korisnikmodel.Korisnickoime))
{
ViewBag.DuplicateMessage = "Korisnicko ime vec postoji.";
return View("DodajiliIzmeni", korisnikmodel);
}
Modelkorisnik.Korisniks.Add(korisnikmodel);
Modelkorisnik.SaveChanges();
}
ModelState.Clear();
ViewBag.SuccessMessage = "Registracija je uspela";
return RedirectToAction("Index", "Login");
}
You should create a view model specific for the view, which has the properties and validation attributes on them as needed by the view and use that to transfer data between your view and action method.
public class EditUserVm
{
public int Id { get; set; }
[DisplayName("Korisnicko ime:")]
public string UserName { get; set; }
[DisplayName("Admin:")]
public bool Admin { get; set; }
[DisplayName("Gost:")]
public bool Gost { get; set; }
[DisplayName("Pravo za unos:")]
public bool PravoUnosa { get; set; }
}
Now you will use this view model for your GET and POST action methods. In your GET action method, first create an object of this view model, then get your Korisniks object for the Id passed in, Read and map the property values to the view model object and pass it to the view.
public ActionResult Edit(int id)
{
using (var dbModel = new BazaProjekatEntities4())
{
var user = dbModel.Korisniks.FirstOrDefault(x => x.KorisnikID == id);
// to do: If user is NULL, return a "Not found" view to user ?
var vm = new EditUserVm { Id = id };
vm.UserName = user.UserName;
vm.Admin = user.Admin;
vm.Gost = user.Gost;
vm.PravoUnosa = user.PravoUnosa;
return View(vm);
}
}
Now makes sure your view is strongly typed to this view model because we are passing an object of the EditUserVm class to it.
#model YourNamespaceGoesHere.EditUserVm
#using (Html.BeginForm())
{
#Html.HiddenFor(a=>a.Id)
<label>#Model.UserName</label>
#Html.LabelFor(a=>a.Admin)
#Html.CheckBoxFor(a=>a.Admin)
#Html.LabelFor(a=>a.Gost)
#Html.CheckBoxFor(a=>a.Gost)
#Html.LabelFor(a=>a.PravoUnosa)
#Html.CheckBoxFor(a=>a.PravoUnosa)
<button type="submit" >Save</button>
}
Now you will use the same view model as the action method parameter. Inside the method, we will read again the User entity from the database and udpate only the field we want to
[HttpPost]
public ActionResult Edit(EditUserVm model)
{
var db = new BazaProjekatEntities4();
var user = db.Korisniks.FirstOrDefault(x => x.KorisnikID == model.Id);
// to do : Do a null check on user to be safe :)
// Map the property values from view model to entity object
user.Admin = model.Admin;
user.Gost = model.Gost;
user.PravoUnosa = model.PravoUnosa;
db.Entry(k).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
In short, create a view model with properties absolutely needed by the view/ your code and use that to transfer data between your action method and view.
The solution was very simple and it could be from the start, i just need to add the user.PotvrdiLozinku = user.Lozinka; that will tell it that the Confirm password is equal to Password (For the [Compare] that is in the User class. :)
[HttpPost]
public ActionResult Edit(EditUserVm model)
{
var db = new BazaProjekatEntities4();
var user = db.Korisniks.FirstOrDefault(x => x.KorisnikID == model.Id);
// to do : Do a null check on user to be safe :)
// Map the property values from view model to entity object
user.Admin = model.Admin;
user.PotvrdiLozinku = user.Lozinka; // this line was missing
user.Gost = model.Gost;
user.PravoUnosa = model.PravoUnosa;
db.Entry(k).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}

ASP.NET MVC 5 DropDownList from another model

I'm just getting started with MVC. I'm building a project in asp.net mcv 5 using entity framework. I have researched many threads but I didn't find anything that would help solve my problem. I have two models:
Resource:
public class Resource
{
[Key]
public int Id { get; set; }
[Required]
public string Name { get; set; }
public string Comments { get; set; }
[Required]
public ResourceType Type { get; set; }
public bool IsActive { get; set; }
}
ResourceType:
public class ResourceType
{
[Key]
public int Id { get; set; }
[Required]
public string Name { get; set; }
}
And the problem is: In View > Resource > Create I want to add DropDownList for object ResourceType Type with values from class ResourceType string Name
Create.cshtml:
#model NetAudit.Models.Resource
#{
ViewBag.Title = "Create Resource";
}
<h2>Create</h2>
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>Resource</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(model => model.Name, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Name, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Name, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Comments, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Comments, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Comments, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Type, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
HERE
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.IsActive, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
<div class="checkbox">
#Html.EditorFor(model => model.IsActive)
#Html.ValidationMessageFor(model => model.IsActive, "", new { #class = "text-danger" })
</div>
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Dodaj" class="btn btn-default" />
</div>
</div>
</div>
}
<div>
#Html.ActionLink("Back to list", "Index")
</div>
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
RecourceType controller:
using System.Data.Entity;
using System.Linq;
using System.Net;
using System.Web.Mvc;
using NetAudit.Models;
namespace NetAudit.Controllers
{
public class ResourceTypesController : BaseController
{
private readonly ApplicationDbContext _db = new ApplicationDbContext();
[Authorize]
public ActionResult Index()
{
return View(_db.ResourceTypes.ToList());
}
[Authorize]
public ActionResult Details(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
var resourceType = _db.ResourceTypes.Find(id);
if (resourceType == null)
{
return HttpNotFound();
}
return View(resourceType);
}
[Authorize]
public ActionResult Create()
{
return View();
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(ResourceType resourceType)
{
if (ModelState.IsValid)
{
_db.ResourceTypes.Add(resourceType);
_db.SaveChanges();
return RedirectToAction("Index");
}
return View(resourceType);
}
[Authorize]
public ActionResult Edit(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
var resourceType = _db.ResourceTypes.Find(id);
if (resourceType == null)
{
return HttpNotFound();
}
return View(resourceType);
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(ResourceType resourceType)
{
if (ModelState.IsValid)
{
_db.Entry(resourceType).State = EntityState.Modified;
_db.SaveChanges();
return RedirectToAction("Index");
}
return View(resourceType);
}
[Authorize]
public ActionResult Delete(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
var resourceType = _db.ResourceTypes.Find(id);
if (resourceType == null)
{
return HttpNotFound();
}
return View(resourceType);
}
[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
public ActionResult DeleteConfirmed(int id)
{
var resourceType = _db.ResourceTypes.Find(id);
if (resourceType == null)
{
return HttpNotFound();
}
_db.ResourceTypes.Remove(resourceType);
_db.SaveChanges();
return RedirectToAction("Index");
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
_db.Dispose();
}
base.Dispose(disposing);
}
}
}
Resource controller:
using System.Data.Entity;
using System.Linq;
using System.Net;
using System.Web.Mvc;
using NetAudit.Models;
namespace NetAudit.Controllers
{
public class ResourceTypesController : BaseController
{
private readonly ApplicationDbContext _db = new ApplicationDbContext();
[Authorize]
public ActionResult Index()
{
return View(_db.ResourceTypes.ToList());
}
[Authorize]
public ActionResult Details(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
var resourceType = _db.ResourceTypes.Find(id);
if (resourceType == null)
{
return HttpNotFound();
}
return View(resourceType);
}
[Authorize]
public ActionResult Create()
{
return View();
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(ResourceType resourceType)
{
if (ModelState.IsValid)
{
_db.ResourceTypes.Add(resourceType);
_db.SaveChanges();
return RedirectToAction("Index");
}
return View(resourceType);
}
[Authorize]
public ActionResult Edit(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
var resourceType = _db.ResourceTypes.Find(id);
if (resourceType == null)
{
return HttpNotFound();
}
return View(resourceType);
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(ResourceType resourceType)
{
if (ModelState.IsValid)
{
_db.Entry(resourceType).State = EntityState.Modified;
_db.SaveChanges();
return RedirectToAction("Index");
}
return View(resourceType);
}
[Authorize]
public ActionResult Delete(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
var resourceType = _db.ResourceTypes.Find(id);
if (resourceType == null)
{
return HttpNotFound();
}
return View(resourceType);
}
[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
public ActionResult DeleteConfirmed(int id)
{
var resourceType = _db.ResourceTypes.Find(id);
if (resourceType == null)
{
return HttpNotFound();
}
_db.ResourceTypes.Remove(resourceType);
_db.SaveChanges();
return RedirectToAction("Index");
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
_db.Dispose();
}
base.Dispose(disposing);
}
}
}
I spent a lot of time looking for a solution to this problem. I would appreciate your feedback on this.
I think the best way to get what you want is to create a ViewModel, this allows you create a view with various classes.
Under your solution create a new folder named ViewModels. Create a new class and name it CreateResourceViewModel.
public class CreateResourceViewModel
{
public Resource Resource {get;set;}
public SelectList ResourceType {get;set;} //this will create the list of resourcetypes
public int IdResourceType {get;set;} //this will be used to select the id of resourceType you are selecting.
public CreateResourceViewModel (Resource resource,List<ResourceType>resourceType) //create a constructor
{
this.Resource = resource;
//here you will set the list as a new selectList, stating where the list will come from. the Id de valuevaluefield, and the name is the valuetextfield
this.ResourceType= new SelectList(resourceType,"Id","Name");
}
public CreateResourceViewModel(){} //you need this second constructor
}
Now you need a Create ActionResult that accepts a ViewModel in your resource Controller
// GET: Locals/Create
public ActionResult Create()
{
Resource resource = new Resource();
List<ResourceType> resourceType;
using (yourcontext db = new yourcontext())
{
resourceType = db.ResourceType.ToList(); //fill your list with the resourceTypes that are in your database
}
CreateResourceViewModel vm = new CreateResourceViewModel(resource,resourceType); //create a new viewmodel and give it the parameters necesary that we created
return View(vm);
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(CreateResourceViewModel vm)
{
using (yourcontext db = new yourcontext())
{
if (ModelState.IsValid)
{
try {
vm.Resource.Type = db.ResourceTpe.Find(vm.IdResourceType); //using the ID selected in the view find it in the database
db.Resources.Add(vm.Resource);
db.SaveChanges();
return RedirectToAction("Index");
}
catch (Exception e)
{
e.Message();
}
}
return View(vm);
}
}
Now onto the view for the ViewModel
#model yourSolution.ViewModels.CreateResourceViewModel
#{
ViewBag.Title = "Create";
}
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>Resource</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(model => model.Name, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Name, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Name, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Comments, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Comments, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Comments, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.ResourceType, htmlAttributes: new { #class = "control-label col-md-2" })
//this is what you need to create a dropdownlist with all the resourceTypes
<div class="col-md-10">
#Html.DropDownListFor(model => model.IdResourceType, Model.ResourceType,"--Select--" )
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.IsActive, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
<div class="checkbox">
#Html.EditorFor(model => model.IsActive)
#Html.ValidationMessageFor(model => model.IsActive, "", new { #class = "text-danger" })
</div>
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Dodaj" class="btn btn-default" />
</div>
</div>
</div>
}
<div>
#Html.ActionLink("Back to list", "Index")
</div>
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
Hope this helps!!
First of you have a mistake to put Resource Controller here (both of Resource and ResourceType are ResourceType). fix it first.
Put in the Here section this code to render a select element from ViewBag.Types:
#Html.DropDownListFor(m => m.Type.Id, (SelectList)ViewBag.Types, new
{
#class = "form-control"
});
Before it you must fill ViewBag.Types in the action, Change the first Create action of ResourceController to this:
[Authorize]
public ActionResult Create()
{
ViewBag.Types = new SelectList(_db.ResourceTypes.ToList(), "Id", "Name", "0");
return View();
}
It will be worked.

MVC Dropdown list from a froma different Model

I'm trying to create a dropdown on my View that populates all the usernames specified in a different table.
I've tried the tuple route but it doesn't seem to be working for me.
Also looked into adding a model containing both models (Users and Tasks)
View
#model Tuple<Task,User>
#{
ViewBag.Title = "Create";
}
<h2>Create</h2>
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>Task</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(model => model.Item1.Name, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Item1.Name, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Item1.Name, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Item1.Details, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Item1.Details, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Item1.Details, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Item1.StartDate, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Item1.StartDate, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Item1.StartDate, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Item1.EndDate, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Item1.EndDate, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Item1.EndDate, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Item1.AssignedTo, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownListFor()
#Html.ValidationMessageFor(model => model.Item1.AssignedTo, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</div>
</div>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
Controller
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Linq;
using System.Net;
using System.Web;
using System.Web.Mvc;
using Base.Models;
using PagedList;
namespace Base.Controllers
{
public class UsersController : Controller {
private WebDBEntities db = new WebDBEntities();
// GET: Users
public ActionResult Index(string sortOrder,string currentFilter, string searchString,int? page) {
ViewBag.NameSortParam = string.IsNullOrEmpty(sortOrder) ? "name_desc" : "";
ViewBag.SurnameSortParam = sortOrder == "Surname" ? "surname_desc" : "Surname";
ViewBag.TeamSortParam = sortOrder == "Team" ? "team_desc" : "Team";
if(searchString != null) {
page = 1;
} else {
searchString = currentFilter;
}
ViewBag.CurrentFilter = searchString;
var users = from u in db.Users select u;
if (!string.IsNullOrEmpty(searchString)) {
users = users.Where(u => u.Name.Contains(searchString) || u.Surname.Contains(searchString));
}
switch (sortOrder) {
case "name_desc":
users = users.OrderByDescending(u => u.Name);
break;
case "Team":
users = users.OrderBy(u => u.Team);
break;
case "team_desc":
users = users.OrderByDescending(u => u.Team);
break;
case "Surname":
users = users.OrderBy(u => u.Surname);
break;
case "surname_desc":
users = users.OrderByDescending(u => u.Surname);
break;
default:
users = users.OrderBy(u => u.Name);
break;
}
int pageSize = 10;
int pageNumber = (page ?? 1);
return View(users.ToPagedList(pageNumber,pageSize));
}
// GET: Users/Details/5
public ActionResult Details(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
User user = db.Users.Find(id);
if (user == null)
{
return HttpNotFound();
}
return View(user);
}
// GET: Users/Create
public ActionResult Create()
{
return View();
}
// POST: Users/Create
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "ID,Name,Surname,Team,UserName")] User user)
{
if (ModelState.IsValid)
{
user.UserName = string.Format("{0}{1}", user.Name.Substring(0, 1), user.Surname);
db.Users.Add(user);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(user);
}
// GET: Users/Edit/5
public ActionResult Edit(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
User user = db.Users.Find(id);
if (user == null)
{
return HttpNotFound();
}
return View(user);
}
// POST: Users/Edit/5
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit([Bind(Include = "ID,Name,Surname,Team,UserName")] User user)
{
if (ModelState.IsValid)
{
db.Entry(user).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
return View(user);
}
// GET: Users/Delete/5
public ActionResult Delete(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
User user = db.Users.Find(id);
if (user == null)
{
return HttpNotFound();
}
return View(user);
}
// POST: Users/Delete/5
[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
public ActionResult DeleteConfirmed(int id)
{
User user = db.Users.Find(id);
db.Users.Remove(user);
db.SaveChanges();
return RedirectToAction("Index");
}
public ActionResult ViewUserTasks(string Username) {
return View("UserTasks",db.Tasks.Where(uu => uu.AssignedTo == Username));
}
public ActionResult GetAllUsers() {
List<string> users = new List<string>();
foreach (var item in db.Users) {
users.Add(item.UserName.ToString())
}
return View(users);
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
db.Dispose();
}
base.Dispose(disposing);
}
}
}
Any assistance would be great, thanks in advance.

ASP.NET MVC multiple models single set of Create, View, Edit and Delete pages

I have a problem figuring out how to implement the Create, Edit and Delete pages for a case where there are multiple Models that I want to display in a single set of Views.
I'm using Visual Studio 2013 and MVC 5. And I also use the latest Entity Framework 6.1.1.
So far I've got the Models:
public class CompositeModel
{
public int ID { get; set; }
public MediaPlan MediaPlanModel { get; set; }
public ContactInfo ContactInfoModel { get; set; }
public MediaPlanDate MediaPlanDateModel { get; set; }
[Timestamp]
public byte[] RowVersion { get; set; }
}
public class MediaPlan
{
public int ID { get; set; }
public string Client { get; set; }
public string Product { get; set; }
public string AE { get; set; }
public string Supervisor { get; set; }
public string Traffic { get; set; }
}
public class ContactInfo
{
public int ID { get; set; }
public string CompanyName { get; set; }
public string CompanyContact { get; set; }
public string CompanyAddress { get; set; }
public string CompanyPhoneNumber { get; set; }
public string CompanyEmail { get; set; }
}
public class MediaPlanDate
{
public int ID { get; set; }
public string Client { get; set; }
public string Product { get; set; }
public string AE { get; set; }
public string Supervisor { get; set; }
public string Traffic { get; set; }
}
Using Code First approach the database was created correctly.
I did auto-generate the CompositeModelsController.cs:
public class CompositeModelsController : Controller
{
private MprContext db = new MprContext();
// GET: CompositeModels
public ActionResult Index()
{
//var compositeModel = new CompositeModel();
//compositeModel.MediaPlanModel = new MediaPlan();
//compositeModel.ContactInfoModel = new ContactInfo();
//compositeModel.MediaPlanDateModel = new MediaPlanDate();
//return View(compositeModel.ToList());
return View(db.Composites.ToList());
}
// GET: CompositeModels/Details/5
public ActionResult Details(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
CompositeModel compositeModel = db.Composites.Find(id);
if (compositeModel == null)
{
return HttpNotFound();
}
return View(compositeModel);
}
// GET: CompositeModels/Create
public ActionResult Create()
{
return View();
}
// POST: CompositeModels/Create
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "ID,RowVersion")] CompositeModel compositeModel)
{
if (ModelState.IsValid)
{
db.Composites.Add(compositeModel);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(compositeModel);
}
// GET: CompositeModels/Edit/5
public ActionResult Edit(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
CompositeModel compositeModel = db.Composites.Find(id);
if (compositeModel == null)
{
return HttpNotFound();
}
return View(compositeModel);
}
// POST: CompositeModels/Edit/5
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit([Bind(Include = "ID,RowVersion")] CompositeModel compositeModel)
{
if (ModelState.IsValid)
{
db.Entry(compositeModel).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
return View(compositeModel);
}
// GET: CompositeModels/Delete/5
public ActionResult Delete(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
CompositeModel compositeModel = db.Composites.Find(id);
if (compositeModel == null)
{
return HttpNotFound();
}
return View(compositeModel);
}
// POST: CompositeModels/Delete/5
[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
public ActionResult DeleteConfirmed(int id)
{
CompositeModel compositeModel = db.Composites.Find(id);
db.Composites.Remove(compositeModel);
db.SaveChanges();
return RedirectToAction("Index");
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
db.Dispose();
}
base.Dispose(disposing);
}
}
I did not expect it to work and it doesn't.
I was able to get the Index to work.
I also created Editor Templates:
#model Online_Mpr.Models.MediaPlan
<h2>MediaPlan</h2>
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>MediaPlan</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
#Html.HiddenFor(model => model.ID)
<div class="form-group">
#Html.LabelFor(model => model.Client, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Client, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Client, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Product, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Product, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Product, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.AE, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.AE, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.AE, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Supervisor, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Supervisor, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Supervisor, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Traffic, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Traffic, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Traffic, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Save" class="btn btn-default" />
</div>
</div>
</div>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
And so forth for the other Models.
Then I have the Create View:
#model Online_Mpr.Models.CompositeModel
#{
ViewBag.Title = "Create";
}
<h2>Create</h2>
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>CompositeModel</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
#Html.EditorFor(model => model.MediaPlanModel)
#Html.EditorFor(model => model.MediaPlanDateModel)
#Html.EditorFor(model => model.ContactInfoModel)
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</div>
</div>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
I was planning to do similar thing for the Edit View.
When I go to the Create View it displays the edit boxes for all the elements but how do I get to code the controller that will create the records in the database.
Preferably I would like to have just one "Create" button in the Create View that would create all four records.
Any help is appreciated as I scoured the internet for info about similar cases and could not find any.
Also if you could provide code samples. They don't have to be elaborate but the core thought will lead me on.
Thanks,
-Arek
Your CompositeModel is essentially a view model. This class shouldn't have an Id property and should n't actually be tied to Entity Framework in any way (don't add a DbSet for it). All it needs to do is contain properties for the other model instances that you want to edit. You should also add a constructor to this class that news up all other models inside:
public class CompositeModel
{
public CompositeModel()
{
MediaPlanModel = new MediaPlan();
ContactInfoModel = new ContactInfo();
MediaPlanDateModel = new MediaPlanDate();
}
...
}
Then in post version of your Create action. You'll simply save each sub-model individually:
[HttpPost]
public ActionResult Create(CompositeModel model)
{
if (ModelState.IsValid)
{
db.MediaPlans.Add(model.MediaPlanModel);
db.ContactInfos.Add(model.ContactInfoModel);
db.MediaPlanDates.Add(model.MediaPlanDateModel)
db.SaveChanges();
return RedirectToAction("Index");
}
return View(model);
}
For your edit version:
[HttpPost]
public ActionResult Edit(CompositeModel model)
{
if (ModelState.IsValid)
{
db.Entry(model.MediaPlanModel).State = EntityState.Modified;
db.Entry(model.ContactInfoModel).State = EntityState.Modified;
db.Entry(model.MediaPlanDateModel).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
return View(model);
}

Categories