Updating 'Parent' entity instead of creating it - c#

I'm listing a series of items and i want top implement an option where you click and it add a child object for that entity, let me explain:
public class SupportItem
{
[Display(Name = "Categoría")]
[ConcurrencyCheck, Required]
public string Type { get; set; }
[Key, HiddenInput(DisplayValue = false)]
public int SupportItemId { get; set; }
[Display(Name = "Nombre")]
[ConcurrencyCheck,Required]
public string Name { get; set; }
[ConcurrencyCheck]
[Display(Name = "Descripción Corta")]
[DataType(DataType.MultilineText)]
[Required]
public string Description { get; set; }
[HiddenInput(DisplayValue = false)]
public virtual SupportItem Father { get; set; }
[Display(Name = "Descripción detallada")]
[DataType(DataType.MultilineText)]
[Required]
public string LongDescription { get; set; }
[HiddenInput(DisplayValue = false)]
public bool Children { get; set; }
}
Now as u can see, this entity has a Father which is of type SupporItem. Now what I want to do is to list them all and add an option which will let you easily add a child for that item you select, heres the view definition:
#model IEnumerable<Domain.Entities.SupportItem>
#{
ViewBag.Title = "IndexSupportItems";
Layout = "~/Views/Shared/_AdminLayout.cshtml";
}
<h2>Index Support Items</h2>
<p>
#Html.ActionLink("Crear nuevo item principal", "Create")
</p>
<table class="Grid">
<tr>
<th>
Tipo
</th>
<th>
Nombre
</th>
<th>
Descripción
</th>
<th>
Acciones
</th>
</tr>
#foreach (var item in Model)
{
<tr>
<td>#item.Type</td>
#if(item.Children)
{
<td>#Html.ActionLink(item.Name,"ListChildren", new{item.SupportItemId})</td>
}
else
{<td>#item.Name</td>
}
<td>#item.Description</td>
<td>
#Html.ActionLink("Delete","DeleteSupportItem", new{item.Father.SupportItemId})<br />
#Html.ActionLink("Add subitem sub-item","AddSubitem", new{item.SupportItemId})<br />
#Html.ActionLink("Edit","EditSupportItem", new{item.SupportItemId})
</td>
</tr>
}
</table>
Now as you can see, the action link for doing this points to a method called AddSubitem, which is implemented as follows:
public ViewResult AddSubitem(int supportItemId)
{
SupportItem child = new SupportItem() { Father = repo.GetSupportItemFromId(supportItemId) };
return View(child);
}
As you can see, I recieve a supportItemId which is the id from the parent entitity (the one to whom i want to add the new child), find it on my database context and create the new object and point the Father object i just found. After doing that the view it returns is this:
#model Domain.Entities.SupportItem
#{
ViewBag.Title = "AddSubitem";
}
<h2>AddSubitem</h2>
#using (Html.BeginForm()) {
#Html.ValidationSummary(true)
<fieldset>
<legend>Support Item</legend>
<div class="editor-label">
#Html.LabelFor(model => model.Type)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Type)
#Html.ValidationMessageFor(model => model.Type)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Name)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Name)
#Html.ValidationMessageFor(model => model.Name)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Description)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Description)
#Html.ValidationMessageFor(model => model.Description)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.LongDescription)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.LongDescription)
#Html.ValidationMessageFor(model => model.LongDescription)
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
In this view, the user will set some of the variables such as name and description and then submit the object so I can persist it to the database, the problem is the object I get from this view has its fathers id as its own id and the Father attribute is null thus i end up updating the Father object to which i want to add a child with this method:
public bool SaveSupportItem(SupportItem supportItem)
{
bool retorno = false;
if (supportItem.SupportItemId == 0)
{
context.SupportItems.Add(supportItem);
supportItem.Father.Children = true;
retorno = true;
}
else
{
SupportItem itemDB = context.SupportItems.Find(supportItem.SupportItemId);
if (itemDB != null)
{
itemDB.Name = supportItem.Name;
itemDB.Type = supportItem.Type;
itemDB.LongDescription = supportItem.LongDescription;
itemDB.Description = supportItem.Description;
retorno = true;
}
}
context.SaveChanges();
return retorno;
}
What am I doing wrong here? why can't I create a new object?
Thanks for taking the time and reading this, any help will be really appreciated!

Well, try this:
Add this to your SupportItem class
public class SupportItem
{
[Key]
[HiddenInput(DisplayValue = false)]
[ForeignKey("Father"), DatabaseGenerated(DatabaseGeneratedOption.None)]
public int SupportItemId { get; set; }
public virtual Father Father { get; set; }
...................
...................
}
Then change:
#Html.ActionLink("Add subitem sub-item","AddSubitem", new{item.SupportItemId})<br />
to
#Html.ActionLink("Add subitem sub-item","AddSubitem", "Controller Name here" new{SupportItemId = #Model.FatherId})<br />
Also because we need FatherId here new{SupportItemId = #Model.FatherId}, the ActionLink needs to be in lets say Father view e.g in Father Details where only single Father is current or something as you have to associate the supportItem with to specific father.
Your controller might look like this, assuming that you are using a ViewModel:
[HttpGet]
public ActionResult CreateSuppo(int supportItemId)
{
var model = new CreateSupportItemViewModel ();
model.SupportItemId= supportItemId;
return View(model);
}
[HttpPost]
public ActionResult Create(CreateSupportItemViewModel viewModel)
{
if(ModelState.IsValid)
{
var father= db.Fathers.Single(f => f.FatherId == viewModel.SupportItemId);
var supportItem= new SupportItem();
supportItem.Name = viewModel.Name;
....................
.................
father.SupportItems.Add(supportItem);
db.SaveChanges();
}
return View(viewModel);
}

Related

How can I pass model with enumerable object to View? [duplicate]

This question already has answers here:
ASP.NET MVC 4 - for loop posts model collection properties but foreach does not
(2 answers)
Closed 8 years ago.
I am new in ASP.MVC4 and I am facing with problem to pass object from view to controller:
Let me explain my problem from beginning:
My class which is used by is for example: UserAndRolesModel
public class UserAndRolesModel
{
public user User { get; set; }
public IEnumerable<UserAndRoles> AsignedRoles { get; set; }
}
As You can see class UserAndRolesModel persists of 2 objects: user and Enumerable
public class user
{
[HiddenInput(DisplayValue=false)]
public virtual int user_id { get; set; }
[Required(ErrorMessage = "Please provide name")]
[Display(Name = "Name")]
public virtual string user_name { get; set; }
[Display(Name = "Is active?")]
public virtual bool user_active { get; set; }
}
public class UserAndRoles
{
public string RoleName { get; set; }
public bool IsAssigned { get; set; }
}
My controller action is simple, it assign user to UserWithRoles.User and creates tempList with UserAndRoles objects.
public ActionResult Edit(int userid=0)
{
//object which will be passed to View
UserAndRolesModel UserWithRoles = new UserAndRolesModel();
//user
UserWithRoles.User = repoUsers.Users.FirstOrDefault(x => x.user_id == userid);
//roles
IList<UserAndRoles> tempList = new List<UserAndRoles>();
UserAndRoles temp1 = new UserAndRoles();
temp1.RoleName="Admin";
temp1.IsAssigned=true;
UserAndRoles temp2 = new UserAndRoles();
temp2.RoleName="User";
temp2.IsAssigned=false;
tempList.Add(temp1);
tempList.Add(temp2);
//assign tempList to model
UserWithRoles.AsignedRoles = tempList;
return View(UserWithRoles);
)
At this stage I am successfully passing to View:
UserWithRoles.User.user_id=1;
UserWithRoles.User.user_name="UserName1";
UserWithRoles.User.user_active=true;
UserWithRoles.AsignedRoles[1].RoleName = "Admin";
UserWithRoles.AsignedRoles[1].IsAssigned = true ;
UserWithRoles.AsignedRoles[2].RoleName = "User";
UserWithRoles.AsignedRoles[2].IsAssigned = false;
I am able to display above View properly:
#model Models.UserAndRolesModel
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
<fieldset>
<div class="editor-field">
#Html.EditorFor(model => model.User.user_id)
#Html.ValidationMessageFor(model => model.User.user_id)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.User.user_name)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.User.user_name)
#Html.ValidationMessageFor(model => model.User.user_name)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.User.user_active)
</div>
<div class="editor-field">
#Html.CheckBoxFor(model => model.User.user_active)
#Html.ValidationMessageFor(model => model.User.user_active)
</div>
<br /> ROLES below is piece of code which makes me cry<br />
#foreach (var item in Model.AsignedRoles)
{
<div class="editor-field">
<div class="editor-field">
#Html.LabelFor(model => item.RoleName)
#Html.CheckBoxFor(model => item.IsAssigned)
</div>
</div>
}
<p>
<input type="submit" value="Save" />
</p>
</fieldset>
}
When i Click submit all data regarding user was passed properly but IEnumerable AsignedRoles is always null.
Here is my controller method on post:
[HttpPost]
public ActionResult Edit(UserAndRolesModel UserWithRoles)
{
if (ModelState.IsValid)
{
if (UserWithRoles.AsignedRoles==null)
Console.WriteLine("I am still crying");
else
Console.WriteLine("Got it!");
}
return View(UserWithRoles);
}
In View I tried to use other loops for example:
#for (int i = 0; i < Model.AsignedRoles.Count(); i++)
{
<div class="editor-field">
#Html.LabelFor(model => item[i].IsAssigned)
#Html.CheckBoxFor(model => item[i].IsAssigned)
</div>
}
But above also does not pass IEnumerable.
Can anyone help me to resolve this issue? How can I pass back to controller UserAndRolesModelwhich contains IEnumerable?
I will be very grateful. Advance thanks for the help!
You do need the for loop, but the one you tried you have referenced item[i], yet item[i] no longer exists. Try this, note that I have also added a HiddenFor for RoleName otherwise that won't get passed back:
#for (int i = 0; i < Model.AsignedRoles.Count(); i++)
{
<div class="editor-field">
#Html.LabelFor(model => model.AssignedRoles[i].IsAssigned)
#Html.CheckBoxFor(model => model.AssignedRoles[i].IsAssigned)
#Html.HiddenFor(model => model.AssignedRoles[i].RoleName)
</div>
}

Create Item and add images for Item in one step

I am trying to learn ASP.net by making an e-commerce site. I am trying to set up the ability to create Items and assign Images to the item being created via File Upload.
I managed to get the multiple file upload working, but only to the content/Images folder. I cant figure out out to marry this to the creation of Items so you can assign multiple images to an Item all in the creation of the item.
It would be a fair to say I dont know where to go from here and would appreciate any help.
Item Model Class: Table in the database to store each item. Is referenced from the Images Table with a 1 to many relationship.
public class Item
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int ItemId { get; set; }
public int CategoryId { get; set; }
public int DesignerId { get; set; }
public int ImageId { get; set; }
[Required]
[MaxLength(250)]
public string ItemName { get; set; }
[Required]
[Range(0,9999)]
public decimal ItemPrice { get; set; }
[MaxLength(1000)]
public string ItemDescription { get; set; }
[Range(4,22)]
public int ItemSize { get; set; }
[Column("CategoryId")]
public virtual List<Category> Category { get; set; }
public virtual List<OrderDetail> OrderDetails { get; set; }
public virtual List<Image> Images { get; set; }
}
Image Model Class: Stores the URL for each Image in the content Directory of the site. Can have many images for each Item.
public class Image
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int ImageId { get; set; }
[Required]
public string ImageURL { get; set; }
[Required]
public string ItemId { get; set; }
//Files Being Uploaded by the User
public IEnumerable<HttpPostedFileBase> Files { get; set; }
[Column("ItemId")]
public virtual List<Item> Item { get; set; }
}
Store Manager Controller
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(Item item,HttpPostedFileBase file)
{
if (ModelState.IsValid)
{
//The below successfully saves the file to the content folder when separated into the Index Action.
foreach (var f in item.Files)
{
if (file.ContentLength > 0)
{
var fileName = Path.GetFileName(f.FileName);
var path = Path.Combine(Server.MapPath("~/Content/ItemImages/"+item), fileName);
file.SaveAs(path);
}
}
// The below also works when I dont have the Above in the Action.
db.Items.Add(item);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(item);
}
Create Item View
#model Project.Models.Item
#{
ViewBag.Title = "Create";
}
<h2>Create</h2>
#using (Html.BeginForm()) {
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
<fieldset>
<legend>Item</legend>
<div class="editor-label">
#Html.LabelFor(model => model.ItemName)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.ItemName)
#Html.ValidationMessageFor(model => model.ItemName)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.ItemPrice)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.ItemPrice)
#Html.ValidationMessageFor(model => model.ItemPrice)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.ItemDescription)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.ItemDescription)
#Html.ValidationMessageFor(model => model.ItemDescription)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.ItemColour)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.ItemColour)
#Html.ValidationMessageFor(model => model.ItemColour)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.ItemSize)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.ItemSize)
#Html.ValidationMessageFor(model => model.ItemSize)
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
}
#using (Html.BeginForm(null, null, FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<div>
<table>
<tr>
<td>Files</td>
<td><input type="file" name="Files" id="Files" multiple/></td>
</tr>
<tr>
<td></td>
<td><input type="submit" name="submit" value="Upload" /></td>
</tr>
</table>
</div>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
So it looks like you're pretty close.
You just have to add the images to the item before adding it to the database.
Since you're using EF, it should be something similar to this
//in your action
//add the images to the item
item.Images.Add(new Image { ImageUrl = ... });
//you should be able to just insert the whole entity graph here
db.Items.Add(item);
db.SaveChanges();
Something like that I think is what you're looking for.
Also in your model constructor normally I think you want to initalize those lists so you don't get null reference execeptions when doing something like the above
public class Item
{
public Item()
{
this.Images = new List<Image>();
}
//...
}

Parent Child tables, adding child records for existing parent record add new parent records wrongly and then add child record

In EF I have two tables (parent is Office- child is Employee), I m adding records to Employee with reference of existing Office record but I guess because of my wrong configuration EF is behaving wearied.
Instead of using Office table's existing record, it add a new records in Office and use new record's id as a foreign key in child records and then create child records.
Here are my Models:
public class Office
{
public int OfficeId{ get; set; }
public string Name { get; set; }
public virtual IEnumerable<Employee> Employees{ get; set; }
}
public class Employee
{
public int EmployeeID{ get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public DateTime DOB { get; set; }
[NotMapped]
public int Age { get { return DOB.YearsFromUtcDateTillToday(); } }
[NotMapped]
public string FullName { get { return string.Concat(FirstName, ' ', LastName); } }
public virtual Office Office { get; set; }
}
View is strongly typed of Employee here is view code:
#model Employee
#{
ViewBag.Title = "AddEmployee";
Layout = "~/Views/Shared/_Layout.cshtml";
}
#using (Html.BeginForm(MVC.CodeTest.AddEmployee(),FormMethod.Post)) {
#Html.ValidationSummary(true)
#Html.HiddenFor(model=>model.Office.OfficID)
<fieldset>
<div class="editor-label">
#Html.LabelFor(model => model.FirstName)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.FirstName)
#Html.ValidationMessageFor(model => model.FirstName)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.LastName)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.LastName)
#Html.ValidationMessageFor(model => model.LastName)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.DOB)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.DOB)
#Html.ValidationMessageFor(model => model.DOB)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.GPA)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.GPA)
#Html.ValidationMessageFor(model => model.GPA)
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
My Controller Actions are the following:
public virtual ActionResult AddEmployee(int officeId)
{
Employee st = new Employee();
st.Office=new Office();
st.Office.OfficeID= officeId;
return View(st);
}
[HttpPost]
public virtual ActionResult AddEmployee(Employee objEmployee)
{
bool success= classEmployeeService.AddEmployee(objEmployee);
if (success)
{
return RedirectToAction("Index",objEmployee.Office.OfficeId);
}
else
{
ModelState.AddModelError("", "Error! Business rule violation, can't repeat surname");
}
return View(objEmployee);
}
My Finding:
In first action (without HttpPost) OfficeId is correct, 1 in this case
Checking html I came to know it is correct
But When pressing Save button 2nd action with HttpPost is executed OfficeId value is wrong, it is new Office record id (18, 19 or next record)
Please guide and help me.
As i see you've an problem with your Model Design. The Employee class should has a property to represent the foreign key of OfficeID.
public class Employee
{
public int EmployeeID{ get; set; }
public int OfficeID{ get; set; } // This what you need
// ...... the rest of class properties
}
Then just assign the Office Id to this property not to the Navigation property "Office"
Employee st = new Employee();
st.OfficeID= officeId;
And never use st.Office=new Office(); because this will add this object to the DbContext StateManager as "Added" and it'll add it as new record to the Database.

Cant seem the get my dropdown menu to work, spent hours looking through this and a tutorial, but I cant seem to get it right

I'm trying to get a dropdown menu along side my other text inputs, I've been tracking a music store tutorial for this specific feature, but I cant seem to get mine to work. I've been revising my code and comparing for hours but I cant see my errors, If anyone can help it would be greatly appreciated.
Here is my controller code:
// GET: /Default1/Create
public ActionResult Create()
{
ViewBag.CardTypeId = new SelectList(db.CardTypee, "CardTypeId", "Type");
return View();
}
//
// POST: /Default1/Create
[HttpPost]
public ActionResult Create(Card card)
{
if (ModelState.IsValid)
{
db.Cards.Add(card);
db.SaveChanges();
return RedirectToAction("Index");
}
ViewBag.CardTypeId = new SelectList(db.CardTypee, "CardTypeId", "Type", card.CardTypeId);
return View(card);
}
My models that I have:
Card.cs
namespace ActualPayment.Models
{
public class Card
{
public int Id { get; set; }
public CardType CardType { get; set; }
public int CardTypeId { get; set; }
public string Name { get; set; }
public string CardNumber { get; set; }
public int SortCode { get; set; }
public int SecurityCode { get; set; }
public int ExpirationDate { get; set; }
}
}
CardType.cs
namespace ActualPayment.Models
{
public partial class CardType
{
[Key] public int CardTypeId { get; set; }
public string Type { get; set; }
}
}
CardTypes.cs
namespace ActualPayment.Models
{
public class CardTypes : DropCreateDatabaseIfModelChanges<CardPayment>
{
protected override void Seed(CardPayment context)
{
var cardType = new List<CardType>
{
new CardType { Type = "Visa/Delta/Electron" },
new CardType { Type = "Master Card/Euro Card" },
new CardType { Type = "American Express" },
new CardType { Type = "Solo/Maestro" },
new CardType { Type = "Maestro" },
};
}
}
}
CardPayments.cs
namespace ActualPayment.Models
{
public class CardPayment : DbContext
{
public DbSet<CardType> CardTypee { get; set; }
public DbSet<Card> Cards { get; set; }
}
}
And my view:
#model ActualPayment.Models.Card
#{
ViewBag.Title = "Create";
}
<h2>Create</h2>
<script src="#Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"> </script>
<script src="#Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
#using (Html.BeginForm()) {
#Html.ValidationSummary(true)
<fieldset>
<legend>Card</legend>
<div class="editor-label">
#Html.LabelFor(model => model.CardTypeId, "CardType")
</div>
<div class="editor-field">
#Html.DropDownList("CardTypeId", String.Empty)
#Html.ValidationMessageFor(model => model.CardTypeId)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Name)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Name)
#Html.ValidationMessageFor(model => model.Name)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.CardNumber)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.CardNumber)
#Html.ValidationMessageFor(model => model.CardNumber)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.SortCode)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.SortCode)
#Html.ValidationMessageFor(model => model.SortCode)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.SecurityCode)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.SecurityCode)
#Html.ValidationMessageFor(model => model.SecurityCode)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.ExpirationDate)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.ExpirationDate)
#Html.ValidationMessageFor(model => model.ExpirationDate)
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
Seems like there's nothing wrong with the code.
Chrome capture for posted values
value at action
Did you mean the CardTypeId is not getting populated??

Create and Index in same view using partial view

Ok I give up after several hours of troubleshooting, but I am sure you all will see a solution right away. I have three models Person, Course and CoursePreference. The CoursePreference model has two foreign keys PersonId and CourseId.
What I want to do:
I want to create a view where the user can add course preferences in a top Create section, and when they click Add, the form would post and refresh the List in the same view. Essentially I am combining Index and Create in one view. So I created an Index View and a partial view called _CreatePartial in the CoursePreference folder.
The problem:
The view displays fine, but with two problems. 1) The CoursePreferenceId field shows a dropdownlist. I want it to be a hidden field since it's an identity. I copied the code exactly from the scaffolded Create View, which hides the Id correctly. Dont know why it's not working in the _CreatePartial view? 2) Most importantly, my _CreatePartial will not add any course preference. It looks as if the form is posting but no record is added.
What gives?
Here are the models, controllers and views:
---------------------------
Models (stripped down versions)
---------------------------
public class CoursePreference
{
public int CoursePreferenceId { get; set; }
public Nullable<int> CourseId { get; set; }
public Nullable<int> PersonId { get; set; }
public virtual Course Course { get; set; }
public virtual Person Person { get; set; }
}
public class Person
{
public int PersonId { get; set; }
public string LastName { get; set; }
public string FirstName { get; set; }
public virtual ICollection<CoursePreference> CoursePreferences { get; set; }
}
public class Course
{
public int CourseId { get; set; }
public Nullable<int> ProgramId { get; set; }
public string Name { get; set; }
public virtual ICollection<CoursePreference> CoursePreferences { get; set; }
}
------------------
Controllers
------------------
public ActionResult _CreatePartial()
{
ViewBag.CourseId = new SelectList(db.Courses, "CourseId", "Name");
ViewBag.PersonId = new SelectList(db.People, "PersonId", "LastName");
return View("_CreatePartial");
}
public ActionResult Index()
{
ViewBag.CourseId = new SelectList(db.Courses, "CourseId", "Name");
ViewBag.PersonId = new SelectList(db.People, "PersonId", "LastName");
var coursepreferences = db.CoursePreferences.Include(c => c.Course).Include(c => c.Person);
return View(coursepreferences.ToList());
}
---------------------------
Index View
---------------------------
#model IEnumerable<MyProj.Models.CoursePreference>
#{ ViewBag.Title = "Index";
}
<h4>Add Course Preferences</h4>
<div>
#Html.Partial("~/Views/CoursePreference/_CreatePartial.cshtml", new MyProj.Models.CoursePreference())
</div>
<br />
<table class="table">
<tr>
<th>
#Html.DisplayNameFor(model => model.Course.Name)
</th>
<th>
#Html.DisplayNameFor(model => model.Person.LastName)
</th>
<th></th>
</tr>
#foreach (var item in Model) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.Course.Name)
</td>
<td>
#Html.DisplayFor(modelItem => item.Person.LastName)
</td>
<td>
#Html.ActionLink("Edit", "Edit", new { id=item.CoursePreferenceId }) |
#Html.ActionLink("Details", "Details", new { id=item.CoursePreferenceId }) |
#Html.ActionLink("Delete", "Delete", new { id=item.CoursePreferenceId })
</td>
</tr>
}
</table>
---------------------------
_CreatePartial View
---------------------------
#model MyProj.Models.CoursePreference
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>CoursePreference</h4>
<hr />
#Html.ValidationSummary(true)
<div class="form-group">
#Html.LabelFor(model => model.CoursePreferenceId, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.CoursePreferenceId)
#Html.ValidationMessageFor(model => model.CoursePreferenceId)
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.CourseId, "CourseId", new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownList("CourseId", String.Empty)
#Html.ValidationMessageFor(model => model.CourseId)
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.PersonId, "PersonId", new { #class = "control-label col-md-2" }
<div class="col-md-10">
#Html.DropDownList("PersonId", String.Empty)
#Html.ValidationMessageFor(model => model.PersonId)
</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>
Nothing is saved because you don't have a controller method to handle the post. Implement this in your controller:
[HttpPost]
public ActionResult Index(CoursePreference pref)
{
// Insert code to fetch database context into variable "db"
db.CoursePreferences.Add(pref);
db.SaveChanges();
return RedirectToAction("Index");
}
As for the hidden ID-field, you should use:
#Html.HiddenFor(model => model.CoursePreferenceId)
-not EditorFor or LabelFor.

Categories