Deleting a record in a table MVC 4 - asp.net-mvc

Im having some trouble when I try to delete a record from a table. I get the error:
The number of primary key values passed must match number of primary key values defined on the entity.
The table has a composite primary key. They are cabinCrewId and flightId.
Controller:
public ActionResult Delete(string name)
{
using (A1Context db = new A1Context())
{
var id = from person in db.person
from flightcabincrew in db.flightcabincrew
from cabincrew in db.cabincrew
where person.name == name
where person.id == cabincrew.person
where cabincrew.person == flightcabincrew.cabinCrewId
select new { flightcabincrew.cabinCrewId, flightcabincrew.flightId };
FlightCabinCrew fcc = db.flightcabincrew.Find(id);
if (fcc == null)
{
return HttpNotFound();
}
else
{
return View(fcc);
}
}
}
Post:
[HttpPost]
public ActionResult Delete(FlightCabinCrew fcc)
{
using (A1Context db = new A1Context())
{
db.Entry(fcc).State = System.Data.EntityState.Deleted;
db.SaveChanges();
}
return View();
}
and part of the view concerned:
#model IEnumerable<Assignment2.Models.FlightCrewGrid>
#{
WebGrid grid = new WebGrid(Model);
}
<h2>#ViewBag.Title</h2>
#grid.GetHtml(columns: grid.Columns(
grid.Column("PersonName", "Crew Member"),
grid.Column("FlightDay", "Flight Day"),
grid.Column("FromAirport", "From"),
grid.Column("ToAirport", "To"),
grid.Column("Model", "Model"),
grid.Column("startDate", "Start Date"),
grid.Column(header: "Delete", format: (item) => Html.ActionLink("Delete", "Delete", new { id=item.PersonName})))
Thanks in advance for any guidance.

Maybe you didn't declare a primary key for the entity. You do this by marking the primary key column with the [Key] attribute.
[Key]
public int cabinCrewId { get; set; }
[Key]
public int flightId { get; set; }

public ActionResult Demodelete(int id)
{
Employee emptbl = new Employee();
emptbl.EmpId = id;
dbc.Entry(emptbl).State = EntityState.Deleted;
dbc.SaveChanges();
return View();
}

Related

DropDownListFor value cannot be null

I am new to MVC. I am using a DropDownListFor to populate a number of Customer fields when a Company is selected. I am using the following code for the DropDownListFor:
#Html.DropDownListFor(model => model.CustomerId, new SelectList(ViewBag.Customers, "CustomerId", "Company"), "---Select one---", new { htmlAttributes = new { #class = "company" } });
#Html.HiddenFor(model => model.Company)
This code retrieves the Customer data:
[HttpPost]
public ActionResult GetCustomer(int custId)
{
var data = db.Customers.Find(custId);
return Json(data);
}
The relevant fields in the ViewModel (from the Customer table) are:
public int CustomerId { get; set; }
public string Company { get; set; }
The code in the Create method that creates the ViewBag:
public ActionResult Create()
{
QuoteViewModel qvm = new QuoteViewModel();
qvm.QuoteDetail = new List<QuoteDetail>();
var customers = db.Customers.ToList();
ViewBag.Customers = customers;
return View(qvm);
}
And here is the code for the POST:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(QuoteViewModel qvm)
{
if (ModelState.IsValid)
{
Quote quote1 = new Quote();
quote1.CustomerId = qvm.CustomerId;
...
db.Quotes.Add(quote1);
customer.CustomerId = qvm.CustomerId;
...
db.Entry(customer).State = EntityState.Modified;
bool saveFailed;
do
{
saveFailed = false;
try
{
db.SaveChanges();
}
catch (DbUpdateConcurrencyException ex)
{
saveFailed = true;
var objContext = ((IObjectContextAdapter)db).ObjectContext;
// Get failed entry
var entry = ex.Entries.Single();
// Now call refresh on ObjectContext
objContext.Refresh(RefreshMode.ClientWins, entry.Entity);
}
} while (saveFailed);
return RedirectToAction("Index");
}
return View(qvm);
}
The population of the fields works fine, but when I attempt to Create the view model I get an error "Value cannot be null" on the DropDownListFor. I have researched others having this issue but cannot find an answer that applies to this case. Any help would be much appreciated.
The error is because in the POST method you return the view (ModelState is invalid), but have not set the value of ViewBag.Customers as you did in the GET method, so it null and you cannot create a SelectList from a null collection.
Your need assign ViewBag.Customers as you did in the GET method before your return View(qvm); statement.
As a side note, since you using a view model, that view model should contain a property (say) public IEnumerable<SelectListItem> CustomerList { get; set; } and you set that in the controller methods, and in the view
#Html.DropDownListFor(model => model.CustomerId, Model.CustomerList, "---Select one---", new { #class = "company" });
Are you making a full page POST request when a Company is selected?
If you are, you need to fill ViewBag.Customers because of ViewBag's lifetime.
http://www.dotnettricks.com/learn/mvc/viewdata-vs-viewbag-vs-tempdata-vs-session

Inserting Many-To-Many data in a database

I'm trying to add data to a Many-To-Many relationship.
Here's my controller
[HttpPost]
public ActionResult AddSkillsPost()
{
int Teacher_ID = Convert.ToInt32(Session["Teacher_ID"]);
var SkillsArray = Request.Form["chk_group[]"];
if(SkillsArray != null)
{
foreach(var skill in SkillsArray)
{
int Skill_ID = Convert.ToInt32(skill);
var SkillToBeModified = (from s in db.Skills
where s.ID == Skill_ID
select new Skill { ID = s.ID, SkillName = s.SkillName, Teachers = s.Teachers });
var Teacher = (from t in db.Teachers
where t.ID == Teacher_ID
select new Teacher { ID = t.ID, FirstName = t.FirstName, LastName = t.LastName,
Email = t.Email, Campus = t.Campus, Skills = t.Skills });
SkillToBeModified.Teachers.Add(Teacher);
db.Entry(SkillToBeModified).State = EntityState.Modified;
db.SaveChanges();
}
}
return RedirectToAction("MyProfile");
}
So I'm trying to add a teacher to a certain skill. However, I'm having a problem with this line
SkillToBeModified.Teachers.Add(Teacher);
I get the error
'IQueryable' does not contain a definition for 'Teachers' and
no extension method 'Teachers' accepting a first argument of type
'IQueryable' could be found (are you missing a using directive
or an assembly reference?)
I'm assuming this is a syntax mistake (something with the query?), but I can't figure out the correct way to write it.
Here's my model for Skills
[Table("Skills")]
public class Skill
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int ID { get; set; }
[Required]
public string SkillName { get; set; }
public virtual List<Teacher> Teachers { get; set; }
public Skill()
{
this.Teachers = new List<Teacher>();
}
}
and here's how my DB looks like
Looking forward to any reply's
EDIT: the form,
<form name="addSkillsForm" action="AddSkillsPost" method="post">
#foreach (var skill in Model.Skills)
{
<input type="checkbox" name="chk_group[]" value="#skill.ID" />#skill.SkillName< br />
}
<input type="submit" value="Update Skills" />
</form>
I'm using a check box form where users can check multiple items, maybe I'm not handeling them coorectly in my POST?
If your DB looks like the picture, you should be able to just do this.
[HttpPost]
public ActionResult AddSkillsPost()
{
int teacher_ID = Convert.ToInt32(Session["Teacher_ID"]);
var SkillsArray = Request.Form["chk_group[]"];
if (SkillsArray != null)
{
foreach (var skill in SkillsArray.Split(','))
{
int skill_ID = Convert.ToInt32(skill);
db.TeacherSkills.Add(new TeacherSkill() { Teacher_ID = teacher_ID, Skill_ID = skill_ID });
db.SaveChanges();
}
}
return RedirectToAction("MyProfile");
}
however if you're adding teacher to a skill then you'd do this.
[HttpPost]
public ActionResult AddSkillsPost()
{
var teacher_ID = Convert.ToInt32(Session["Teacher_ID"]);
var SkillsArray = Request.Form["chk_group[]"];
if (SkillsArray != null)
{
var teacher = db.Teachers.Find(teacher_ID);
foreach (var skill in SkillsArray.Split(','))
{
var skill_ID = Convert.ToInt32(skill);
var skillToBeModified = db.Skills.Find(skill_ID);
skillToBeModified.Teachers.Add(teacher);
db.Entry(skillToBeModified).State = EntityState.Modified;
db.SaveChanges();
}
}
return RedirectToAction("MyProfile");
}

ASP.NET MVC webgrid post issue - Viewmodel is NULL

Here are my model classes:
public class SensorTest
{
public int SerialNo { get; set; }
public string SensorName { get; set; }
public string TestName { get; set; }
public List<string> ImpactSide { get; set; }
}
public class SensorTestsViewModel
{
public List<SensorTest> SensorTestList { get; set; }
}
Controller action methods:
GET:
[HttpGet]
public ActionResult SensorTests()
{
SensorTestsViewModel obj = new SensorTestsViewModel();
obj.SensorTestList = new List<SensorTest>();
SensorTest sensortest;
sensortest = new SensorTest();
sensortest.SerialNo = 1;
sensortest.SensorName = "FLAT 13 KMH";
sensortest.TestName = "";
obj.SensorTestList.Add(sensortest);
sensortest = new SensorTest();
sensortest.SerialNo = 1;
sensortest.SensorName = "CURB IMPACT 40KMH";
sensortest.TestName = "";
obj.SensorTestList.Add(sensortest);
return View(obj);
}
POST:
[HttpPost]
[ActionName("SensorTests")]
public ActionResult SensorTests_Post(SensorTestsViewModel sensortests)
{
//SensorTestsViewModel model = new SensorTestsViewModel();
//UpdateModel(model);
return View(sensortests);
}
View code:
#model Safety.Models.SensorTestsViewModel
#using (Html.BeginForm("SensorTests", "Safety"))
{
var grid = new WebGrid(Model.SensorTestList, canSort: false, canPage: false);
int rowNum = 0;
<div>
#grid.GetHtml(columns:
grid.Columns
(
grid.Column("SerialNo", format: item => rowNum = rowNum + 1),
grid.Column("SensorName"),
grid.Column("TestName", format: (item) => Html.TextBox("TestName[" + (rowNum - 1).ToString() + "].TestName", (object)item.TestName))
), mode: WebGridPagerModes.Numeric)
</div>
<input type="submit" value="Submit" />
}
See the Viewmodel is null during POST. I have tried UpdateModel as well. My requirement is I need to post whole viewmodel data to controller and do the necessary actions from there. Not sure what I am missing? Can someone Please suggest?
First, take a look at this example: post items of webgrid asp.net mvc3
Try making the textbox name like this: "SensorTestList[someIndexHere].SensorName"

Finding Roles MVC 4 Simple Membership

My Action
[Authorize(Roles = "Admin")]
public ActionResult Index()
{
using (var ctx = new _dbContext())
{
return View(ctx.UserProfiles.OrderBy(x => x.UserId).ToList());
}
}
I want to display roles with UserId and UserName how can i do that??
Update:
View Model
public class AccountIndexViewModel
{
public int UserId { get; set; }
public string UserName { get; set; }
public string Roles { get; set; }
}
View
#using GoldCalculator.Models
#model IEnumerable<AccountIndexViewModel>
#foreach (var user in Model)
{
<tr>
<td>#user.UserId</td>
<td>#user.UserName</td>
<td>#user.Roles</td>
<td> #Html.ActionLink("X", "Delete", new { id = #user.UserName }, new { #class = "deletebtn"})</td>
</tr>
}
The output is System.String[]
Assuming you have enabled roles in your application and that you have already created some roles:
using WebMatrix.WebData;
///blah blah blah...
///inside some action:
var roles = (SimpleRoleProvider)Roles.Provider;
var allRoles = roles.GetAllRoles();
Getting role for specific user:
var userRoles = roles.GetRolesForUser("admin#user.com");
Answering you new question, try this:
var model = ctx.UserProfiles.OrderBy(x => x.UserId);
var newModel = from ab in model
select new
{
UserName = ab.UserName,
UserId = ab.UserId,
Role = roles.GetRolesForUser(ab.UserName)
};
You are assigning value to variable that already has been declared and apparently data types don't match.

MVC DropDownList SelectedValue not displaying correctly

I tried searching and didn't find anything that fixed my problem. I have a DropDownList on a Razor view that will not show the the item that I have marked as Selected in the SelectList. Here is the controller code that populates the list:
var statuses = new SelectList(db.OrderStatuses, "ID", "Name", order.Status.ID.ToString());
ViewBag.Statuses = statuses;
return View(vm);
Here is the View code:
<div class="display-label">
Order Status</div>
<div class="editor-field">
#Html.DropDownListFor(model => model.StatusID, (SelectList)ViewBag.Statuses)
#Html.ValidationMessageFor(model => model.StatusID)
</div>
I walk through it and even in the view it has the correct SelectedValue however the DDL always shows the first item in the list regardless of the selected value. Can anyone point out what I am doing wrong to get the DDL to default to the SelectValue?
The last argument of the SelectList constructor (in which you hope to be able to pass the selected value id) is ignored because the DropDownListFor helper uses the lambda expression you passed as first argument and uses the value of the specific property.
So here's the ugly way to do that:
Model:
public class MyModel
{
public int StatusID { get; set; }
}
Controller:
public class HomeController : Controller
{
public ActionResult Index()
{
// TODO: obviously this comes from your DB,
// but I hate showing code on SO that people are
// not able to compile and play with because it has
// gazzilion of external dependencies
var statuses = new SelectList(
new[]
{
new { ID = 1, Name = "status 1" },
new { ID = 2, Name = "status 2" },
new { ID = 3, Name = "status 3" },
new { ID = 4, Name = "status 4" },
},
"ID",
"Name"
);
ViewBag.Statuses = statuses;
var model = new MyModel();
model.StatusID = 3; // preselect the element with ID=3 in the list
return View(model);
}
}
View:
#model MyModel
...
#Html.DropDownListFor(model => model.StatusID, (SelectList)ViewBag.Statuses)
and here's the correct way, using real view model:
Model
public class MyModel
{
public int StatusID { get; set; }
public IEnumerable<SelectListItem> Statuses { get; set; }
}
Controller:
public class HomeController : Controller
{
public ActionResult Index()
{
// TODO: obviously this comes from your DB,
// but I hate showing code on SO that people are
// not able to compile and play with because it has
// gazzilion of external dependencies
var statuses = new SelectList(
new[]
{
new { ID = 1, Name = "status 1" },
new { ID = 2, Name = "status 2" },
new { ID = 3, Name = "status 3" },
new { ID = 4, Name = "status 4" },
},
"ID",
"Name"
);
var model = new MyModel();
model.Statuses = statuses;
model.StatusID = 3; // preselect the element with ID=3 in the list
return View(model);
}
}
View:
#model MyModel
...
#Html.DropDownListFor(model => model.StatusID, Model.Statuses)
Make Sure that your return Selection Value is a String and not and int when you declare it in your model.
Example:
public class MyModel
{
public string StatusID { get; set; }
}
Create a view model for each view. Doing it this way you will only include what is needed on the screen. As I don't know where you are using this code, let us assume that you have a Create view to add a new order.
Create a new view model for your Create view:
public class OrderCreateViewModel
{
// Include other properties if needed, these are just for demo purposes
// This is the unique identifier of your order status,
// i.e. foreign key in your order table
public int OrderStatusId { get; set; }
// This is a list of all your order statuses populated from your order status table
public IEnumerable<OrderStatus> OrderStatuses { get; set; }
}
Order status class:
public class OrderStatus
{
public int Id { get; set; }
public string Name { get; set; }
}
In your Create view you would have the following:
#model MyProject.ViewModels.OrderCreateViewModel
#using (Html.BeginForm())
{
<table>
<tr>
<td><b>Order Status:</b></td>
<td>
#Html.DropDownListFor(x => x.OrderStatusId,
new SelectList(Model.OrderStatuses, "Id", "Name", Model.OrderStatusId),
"-- Select --"
)
#Html.ValidationMessageFor(x => x.OrderStatusId)
</td>
</tr>
</table>
<!-- Add other HTML controls if required and your submit button -->
}
Your Create action methods:
public ActionResult Create()
{
OrderCreateViewModel viewModel = new OrderCreateViewModel
{
// Here you do database call to populate your dropdown
OrderStatuses = orderStatusService.GetAllOrderStatuses()
};
return View(viewModel);
}
[HttpPost]
public ActionResult Create(OrderCreateViewModel viewModel)
{
// Check that viewModel is not null
if (!ModelState.IsValid)
{
viewModel.OrderStatuses = orderStatusService.GetAllOrderStatuses();
return View(viewModel);
}
// Mapping
// Insert order into database
// Return the view where you need to be
}
This will persist your selections when you click the submit button and is redirected back to the create view for error handling.
I hope this helps.
For me, the issue was caused by big css padding numbers ( top & bottom padding inside the dropdown field). Basically, the item was being shown but not visible because it was way down. I FIXED it by making my padding numbers smaller.
I leave this in case it helps someone else. I had a very similar problem and none of the answers helped.
I had a property in my ViewData with the same name as the selector for the lambda expression, basically as if you would've had ViewData["StatusId"] set to something.
After I changed the name of the anonymous property in the ViewData the DropDownList helper worked as expected.
Weird though.
My solution was this...
Where the current selected item is the ProjectManagerID.
View:
#Html.DropDownList("ProjectManagerID", Model.DropDownListProjectManager, new { #class = "form-control" })
Model:
public class ClsDropDownCollection
{
public List<SelectListItem> DropDownListProjectManager { get; set; }
public Guid ProjectManagerID { get; set; }
}
Generate dropdown:
public List<SelectListItem> ProjectManagerDropdown()
{
List<SelectListItem> dropDown = new List<SelectListItem>();
SelectListItem listItem = new SelectListItem();
List<ClsProjectManager> tempList = bc.GetAllProductManagers();
foreach (ClsProjectManager item in tempList)
{
listItem = new SelectListItem();
listItem.Text = item.ProjectManagerName;
listItem.Value = item.ProjectManagerID.ToString();
dropDown.Add(listItem);
}
return dropDown;
}
Please find sample code below.
public class Temp
{
public int id { get; set; }
public string valueString { get; set; }
}
Controller
public ActionResult Index()
{
// Assuming here that you have written a method which will return the list of Temp objects.
List<Temp> temps = GetList();
var tempData = new SelectList(temps, "id", "valueString",3);
ViewBag.Statuses = tempData;
return View();
}
View
#Html.DropDownListFor(model => model.id, (SelectList)ViewBag.Statuses)
#Html.ValidationMessageFor(model => model.id)

Resources