When a user selects an item from dropdown list then that item must be removed for that user in mvc 4 - html

I am creating a user course project for learning MVC 4. In this project, when a user logs in they can see their courses and other details. A user can create or edit the courses. So I am displaying list of courses in dropdown list during create and edit. What I want is, when a user selects a course and it is added to his list of courses then that course should not be displayed in the dropdown list for that user. Some code for create is given below:
CourseController:
public ActionResult Create()
{
User user = (User)Session["User"];
var usr = db.Users.Find(user.UserId);
if (Session["User"] != null)
{
ViewBag.CourseId = new SelectList(db.Courses, "CourseId", "CourseName");
ViewBag.UserId = usr.UserId;
ViewBag.FirstName = usr.FirstName;
}
return View();
}
//
// POST: /Course/Create
[HttpPost]
public ActionResult Create(UserCourse usercourse)
{
User user = (User)Session["User"];
var usr = db.Users.Find(user.UserId);
if (Session["User"] != null)
{
if (ModelState.IsValid)
{
db.UserCourses.Add(usercourse);
db.SaveChanges();
return RedirectToAction("Index");
}
ViewBag.CourseId = new SelectList(db.Courses, "CourseId", "CourseName", usercourse.CourseId);
ViewBag.UserId = usr.UserId;//from c in db.Users.Where(u => u.UserId == usercourse.UserId) select c;
ViewBag.FirstName = usr.FirstName;
return View();
}
return View(usercourse);
}
Create.cshtml:
<div class="editor-label">
#Html.DisplayNameFor(model => model.CourseId)
</div>
<div class="editor-field">
#Html.DropDownList("CourseId", String.Empty)
#Html.ValidationMessageFor(model => model.CourseId)
</div>
<p>
<input type="submit" value="Create" />
</p>
Model class for User:
public partial class User
{
public User()
{
this.UserCourses = new HashSet<UserCourse>();
}
public int UserId { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
[Required(ErrorMessage = "Please Provide User Name", AllowEmptyStrings = false)]
public string UserName { get; set; }
[Required(ErrorMessage = "Please Provide Password", AllowEmptyStrings = false)]
[DataType(System.ComponentModel.DataAnnotations.DataType.Password)]
public string Password { get; set; }
public string Address { get; set; }
public string City { get; set; }
public string Email { get; set; }
public string PhoneNo { get; set; }
public virtual ICollection<UserCourse> UserCourses { get; set; }
}
Model class for Course:
public partial class Course
{
public Course()
{
this.UserCourses = new HashSet<UserCourse>();
}
public int CourseId { get; set; }
public string CourseName { get; set; }
public virtual ICollection<UserCourse> UserCourses { get; set; }
}
Model class for UserCourse:
public partial class UserCourse
{
public int Id { get; set; }
public Nullable<int> UserId { get; set; }
public Nullable<int> CourseId { get; set; }
public virtual Course Course { get; set; }
public virtual User User { get; set; }
}
Please reply.

[EDITED]: Try it this way:
public ActionResult Create()
{
User user = (User)Session["User"];
var usr = db.Users.Find(user.UserId);
if (Session["User"] != null)
{
var courses = db.Courses.Where(x=>!x.UserCourses.Any(y=>y.CourseId == x.CourseId && y.UserId == usr.UserId)).ToList();
ViewBag.CourseId = new SelectList(courses , "CourseId", "CourseName");
ViewBag.UserId = usr.UserId;
ViewBag.FirstName = usr.FirstName;
}
return View();
}
//
// POST: /Course/Create
[HttpPost]
public ActionResult Create(UserCourse usercourse)
{
User user = (User)Session["User"];
var usr = db.Users.Find(user.UserId);
if (Session["User"] != null)
{
if (ModelState.IsValid)
{
db.UserCourses.Add(usercourse);
db.SaveChanges();
return RedirectToAction("Index");
}
var courses = db.Courses.Where(x=>!x.UserCourses.Any(y=>y.CourseId == x.CourseId && y.UserId == usr.UserId)).ToList();
ViewBag.CourseId = new SelectList(courses, "CourseId", "CourseName", usercourse.CourseId);
ViewBag.UserId = usr.UserId;//from c in db.Users.Where(u => u.UserId == usercourse.UserId) select c;
ViewBag.FirstName = usr.FirstName;
return View();
}
return View(usercourse);
}

Related

How make dropdownlist to access data on your SelectItemList using asp.net mvc?

I am using DropDownlist in order to get country of all the world. I have attached the file(country_list.txt) using srcFilePath. The error i am getting is "There is no ViewData item of type 'IEnumerable' that has the key 'SelectedCountryId'.What could be an issue, because my EditFormTrainingRegViewModel does have this field SelectedCountry as a primary key. Its been declared as public int? SelectedCountryId {get;set;}
// List for countries.
private IEnumerable<SelectListItem> GetCountryList()
{
SelectList listcn = null;
try
{
var list = this.LoadData().Select(p => new SelectListItem
{
Value = p.Country_Id.ToString(),
Text = p.Country_Name
});
listcn = new SelectList(list, "Value", "Text");
}catch(Exception ex)
{
throw ex;
}
return listcn;
}
public ActionResult DropDownSelect()
{
EditTrainingRegFormViewModel model = new EditTrainingRegFormViewModel();
model.SelectedCountryId = 0;
this.ViewBag.CountryList = this.GetCountryList();
return this. View(model);
}
// Loading data for country list.
private List<EditTrainingRegFormViewModel> LoadData()
{
List<EditTrainingRegFormViewModel> lst = new List<EditTrainingRegFormViewModel>();
try
{
string line = string.Empty;
string srcFilePath = "Content/files/country_list.txt";
var rootPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().CodeBase);
var fullPath = Path.Combine(rootPath, srcFilePath);
string filePath = new Uri(fullPath).LocalPath;
StreamReader src = new StreamReader(new FileStream(filePath, FileMode.Open, FileAccess.Read));
// while to read the file
while((line = src.ReadLine()) !=null) {
EditTrainingRegFormViewModel infoLst = new EditTrainingRegFormViewModel();
string[] info = line.Split(',');
//Setting
infoLst.Country_Id = Convert.ToInt32(info[0].ToString());
infoLst.Country_Name = info[1].ToString();
lst.Add(infoLst);
}
src.Dispose();
src.Close();
}catch(Exception ex)
{
Console.Write(ex);
}
return lst;
}
//View
#Html.DropDownListFor(m=>m.SelectedCountryId, this.ViewBag.CountryList as SelectList, new {#class = "form-control"})
// Model class
public class EditTrainingRegFormViewModel
{
public string Title { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Position { get; set; }
public string Company { get; set; }
public string Address { get; set; }
[Display(Name = "Choose country")]
public int ? SelectedCountryId { get; set; }
public string Code { get; set; }
public string City { get; set; }
public string State { get; set; }
public string Cell_Number { get; set; }
public List<string> Dietary_requirement { get; set; }
public string Email { get; set; }
public int Country_Id { get; set; }
public string Country_Name { get; set; }
}

How to create multiple Radiobutton group in ASP.Net Core 2 and Razor?

I want to create multiple grouped Radio buttons. So, basically I have multiple questions and 3 radio buttons with answers. The problem I'm facing is how to return the selected value for the multiple radio buttons.
Controller
public IActionResult Test()
{
SafetyObservationCardForm form = new SafetyObservationCardForm();
using (IDbConnection dbConnection = Connection)
{
dbConnection.Open();
var questions = dbConnection.Query<QuestionsViewModel>("SELECT * FROM SOCQuestions ORDER BY soc_order_id");
var observationType = new List<ObservationType>
{
new ObservationType { Id = 1, Name = "Safe" },
new ObservationType { Id = 2, Name = "At Risk" },
new ObservationType { Id = 3, Name = "N/A" }
};
var rb = new List<Answer>();
foreach (var item in questions)
{
rb.Add(new Answer { Id = item.soc_question_id, ObservationTypes = observationType });
};
form.Answers = rb;
form.Questions = questions.ToList();
return View(form);
}
}
Model
public class SafetyObservationCardForm
{
public List<QuestionsViewModel> Questions { get; set; }
public string Comments { get; set; }
public string Location { get; set; }
public string Observer { get; set; }
public DateTime TimeStamp { get; set; }
public string Task { get; set; }
public ObserverType ObserverType { get; set; }
public IEnumerable<Answer> Answers { get; set; }
}
public class ObserverType
{
public bool Supervisor { get; set; }
public bool Peer { get; set; }
public bool Self { get; set; }
public bool Other { get; set; }
}
public class ObservationType
{
public int Id { get; set; }
public string Name { get; set; }
}
public class Answer
{
public int Id { get; set; }
public IEnumerable<ObservationType> ObservationTypes { get; set; }
public int SelectedObservation { get; set; }
}
}
View
Here I'm trying the loop. Answers model is null when I submit the form for some reason.
#model DBI.Safety.Models.SafetyObservationCardForm
<form asp-action="CreateTest">
#foreach (var answer in Model.Answers)
{
<input name="#answer.Id" asp-for="#answer.SelectedObservation" type="radio"
value="#answer.Id" /> #answer.ObservationTypes
}
</form>

Trying to update table in asp.net

Saving the change to a temp variable is successful as when debugging I can see the values changing, however when I actually try to save the changes to the database, the required field is not being changed.
I am trying to change the value of the field from 'Being Investigated' to 'Closed'
nemesysEntities db2 = new nemesysEntities();
report report = db2.reports.Find(investigation.report_id);
report_status rep = db2.report_status.Find(3);
report.report_status = rep;
report.report_status.description = "Closed";
report.report_status.id = 3;
db2.Entry(report).State= EntityState.Modified;
db2.SaveChanges();
The table that stores the reports is called reports, and investigation.report_id represents the id of the report being investigated. Hence by passing the report id as a value, the table should find the report in the reports table and change the value of the action status to Closed, by the below line of code, (the id of the action "closed" in the database is 3)
report_status rep = db2.report_status.Find(3);
However the required changes in the database are not being stored.
Any ideas??
This is the model of the report
namespace WebApplication2.Models
{
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Data.Entity;
using System.Data.Entity.Validation;
using System.Diagnostics;
using System.Web;
public partial class report
{
public report()
{
this.investigations = new HashSet<investigation>();
HttpCookie _userId = System.Web.HttpContext.Current.Request.Cookies["User"];
string userId="";
nemesysEntities db = new nemesysEntities();
if(_userId!=null)
{
this.user_id = Convert.ToInt32(_userId["Id"]);
user temp=db.users.Find(user_id);
this.email = temp.email;
this.phone = temp.phone;
temp.ConfirmPassword = temp.password;
int i = temp.points;
i++;
temp.points = i;
db.Entry(temp).State = EntityState.Modified;
try
{
db.SaveChanges();
}
catch (DbEntityValidationException dbEx)
{
foreach (var validationErrors in dbEx.EntityValidationErrors)
{
foreach (var validationError in validationErrors.ValidationErrors)
{
Trace.TraceInformation("Property: {0} Error: {1}", validationError.PropertyName, validationError.ErrorMessage);
}
}
}
}
else
{
this.user_id = 13;
}
this.status_id = 1;
}
public int id { get; set; }
[Display(Name = "Date of near miss")]
public System.DateTime date { get; set; }
[Display(Name = "Location")]
public string location { get; set; }
[DisplayName("Type")]
public int type_id { get; set; }
[Display(Name = "Description")]
public string description { get; set; }
public int status_id { get; set; }
public int user_id { get; set; }
[Display(Name = "Email Address")]
public string email { get; set; }
[Display(Name = "Phone Number")]
public string phone { get; set; }
public int votes { get; set; }
public virtual ICollection<investigation> investigations { get; set; }
public virtual report_status report_status { get; set; }
public virtual report_type report_type { get; set; }
public virtual user user { get; set; }
}
}
This is the model of the investigator. You can see that in one of the setters I am using the same method I am attempting to use to change the status of the report.
namespace WebApplication2.Models
{
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Data.Entity;
using System.Data.Entity.Validation;
using System.Diagnostics;
using System.Web;
public partial class investigation
{
public investigation()
{
HttpCookie _userId = System.Web.HttpContext.Current.Request.Cookies["User"];
if (_userId != null)
{
this.investigator_id = Convert.ToInt32(_userId["Id"]);
//5 is the primary key of "Being investigated" in type of action
this.action_id = 5;
this.cause = "";
this.date_of_action = new DateTime(2012, 1, 3);
}
}
public int id { get; set; }
[Display (Name="Formal Description")]
public string formal_description { get; set; }
[Display(Name = "Cause of Hazard")]
public string cause { get; set; }
[Display(Name = "Action Take")]
public int action_id { get; set; }
[Display(Name = "Date of Action")]
public System.DateTime date_of_action { get; set; }
public int investigator_id { get; set; }
int _report_id;
[Display(Name = "Report Id:")]
public int report_id
{
get
{
return _report_id;
}
set
{
_report_id = value;
nemesysEntities db = new nemesysEntities();
report report = db.reports.Find(this.report_id);
//2 is the primary key of "Being investigated" in report status
report_status rep = db.report_status.Find(2);
report.report_status = rep;
db.Entry(report).State = EntityState.Modified;
try
{
db.SaveChanges();
}
catch (DbEntityValidationException dbEx)
{
foreach (var validationErrors in dbEx.EntityValidationErrors)
{
foreach (var validationError in validationErrors.ValidationErrors)
{
Trace.TraceInformation("Property: {0} Error: {1}", validationError.PropertyName, validationError.ErrorMessage);
}
}
}
}
}
public virtual investigation_action investigation_action { get; set; }
public virtual report report { get; set; }
public virtual user user { get; set; }
}
}

How to build a Create View for a Many to Many relationship

Ok, looks like someone should run into this, but I have not found anything that helps. This is my scenario.
I have a clients and skills model. The objective is to allow clients to rate each of a set of skills, all of them.
So, here I'll paste model, viewModel, Controller and View. at the end the crucial question
MODEL
namespace ClientSkills.Models
{
public class Client
{
public int ClientId { get; set; }
public string Name { get; set; }
public ICollection<ClientSkills> Skills { get; set; }
}
public class Skill
{
public int SkillId { get; set; }
public string Name { get; set; }
public ICollection<ClientSkills> Clients { get; set; }
}
public class Rating
{
public int RatingId { get; set; }
public string Name { get; set; }
public ICollection<ClientSkills> ClientSkills { get; set; }
}
public class ClientSkills
{
[Key, Column(Order=0)]
public int ClientId { get; set; }
[Key, Column(Order = 1)]
public int SkillId { get; set; }
public int RatingId { get; set; }
public Rating Rating { get; set; }
public Skill Skill { get; set; }
public Client Client { get; set; }
}
public partial class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public DbSet<Client> Client { get; set; }
public DbSet<Skill> Skill { get; set; }
public DbSet<Rating> Rating { get; set; }
public DbSet<ClientSkills> ClientSkills { get; set; }
}
}
VIEW MODEL
namespace ClientSkills.Models
{
public class RateViewModel
{
public RateViewModel()
{
this.Skills = new List<SkillViewModel>();
}
public RateViewModel(Client client)
{
this.ClientId = client.ClientId;
this.Skills = new List<SkillViewModel>();
if (client.Skills.Count == 0)
{
var context = new ApplicationDbContext();
foreach (var skill in context.Skill)
{
var skillVM = new SkillViewModel(skill);
skillVM.SelectedRatingid = context.Rating.First(r => r.Name == "No aplica").RatingId;
Skills.Add(skillVM);
}
}
else
{
foreach (var item in client.Skills)
{
var skillVM = new SkillViewModel(item);
skillVM.SelectedRatingid = item.SkillId;
this.Skills.Add(skillVM);
}
}
}
public int ClientId { get; set; }
public List<SkillViewModel> Skills { get; set; }
}
public class SkillViewModel
{
public SkillViewModel()
{
Ratings = new List<Rating>();
}
public SkillViewModel(Skill skill)
{
var context = new ApplicationDbContext();
this.Ratings = context.Rating.ToList();
this.SkillId = skill.SkillId;
this.SkillName = skill.Name;
}
public SkillViewModel(ClientSkills item)
{
var context = new ApplicationDbContext();
this.Ratings = context.Rating.ToList();
this.SkillId = item.SkillId;
this.SkillName = item.Skill.Name;
this.SelectedRatingid = item.RatingId;
}
public List<Rating> Ratings { get; set; }
public int SelectedRatingid { get; set; }
public int SkillId { get; set; }
public string SkillName { get; set; }
}
}
CONTROLLER
namespace ClientSkills.Controllers
{
public class RateController : Controller
{
//
// GET: /Rate/Create
public ActionResult Create()
{
//first, we assume there is an already selected user
var context = new ApplicationDbContext();
var client = context
.Client
.Include(c => c.Skills)
.First(c => c.Name.ToLower() == "ricker");
var model = new RateViewModel(client);
return View(model);
}
}
}
VIEW
This View is made creating a Create view with the wizard, deleting the useless field it creates and putting the code below
<table>
<tr>
<td>Skill</td>
<td>Rate</td>
</tr>
#foreach (var item in Model.Skills)
{
<tr>
<td>
#Html.DisplayFor(model => model.Skills.First(i => i.SkillName == item.SkillName).SkillName, new { #class = "control-label col-md-2" })
</td>
<td>
#Html.DropDownListFor(x => item.SelectedRatingid, new SelectList(item.Ratings, "RatingId", "Name"), "Seleccione el valor")
</td>
</tr>
}
</table>
The problem is that in the RateViewModel(Client client) constructor in the line skillVM.SelectedRatingid = context.Rating.First(r => r.Name == "No aplica").RatingId; I set a default value for the selectedRatingId property. I need to make sure all clients has all skills rated even if they forgot or bypass one of them.
When the view is loaded, and I was sure the ratesid was well set, the skill names look ok but the drop dpwn lists does not show the selected default value.
How can I make the view to bind the selectedRatingId property to the drop down list control?
Passing selected value to SelectList:
#Html.DropDownListFor(x => item.SelectedRatingid, new SelectList(item.Ratings, "RatingId", "Name", item.SelectedRatingid), "Seleccione el valor")
As I understand it (rightly or wrongly) that last parameter is an object if it matches with one of the options values - it is selected else the first one in the options is selected.
More info about the Selectlist overload.

KeyNotFoundException on SaveChanges()

Okey so i'm trying to update information in my database from a form.
But when i call db.SaveShanges() i get KeyNotFoundException.
I'm using MVC3 and EF 4.1.
I use Controller->Service->Repositry->EF design pattern.
The callstack:
at System.Collections.Generic.Dictionary`2.get_Item(TKey key)
at System.Data.Objects.EntityEntry.UpdateComplexObjectSnapshot(StateManagerMemberMetadata member, Object userObject, Int32 ordinal, Object currentValue)
at System.Data.Objects.EntityEntry.DetectChangesInProperties(Boolean detectOnlyComplexProperties)
at System.Data.Objects.ObjectStateManager.DetectChangesInScalarAndComplexProperties(IList`1 entries)
at System.Data.Objects.ObjectStateManager.DetectChanges()
at System.Data.Objects.ObjectContext.DetectChanges()
at System.Data.Entity.Internal.InternalContext.DetectChanges(Boolean force)
at System.Data.Entity.Internal.InternalContext.GetStateEntries(Func`2 predicate)
at System.Data.Entity.Internal.InternalContext.GetStateEntries()
at System.Data.Entity.Infrastructure.DbChangeTracker.Entries()
at System.Data.Entity.DbContext.GetValidationErrors()
at System.Data.Entity.Internal.InternalContext.SaveChanges()
at System.Data.Entity.Internal.LazyInternalContext.SaveChanges()
at System.Data.Entity.DbContext.SaveChanges()
My repositrory db is a dbContext with a DbSet for the model i'm using.
public bool Save()
{
try
{
db.SaveChanges();
}
catch(Exception e)
{
return false;
}
return true;
}
My Service that calls the repository
public bool UpdateUserInformationFromSettingsModel(UserSettingsModel model)
{
int userInfoID = _profile.GetUserInformationID(model.userName);
UserInformation userInfo = _repository.Get(userInfoID);
if (userInfo == null)
{
return false;
}
userInfo.firstName = model.firstName;
userInfo.lastName = model.lastName;
userInfo.phone = model.phone;
userInfo.invoiceReciever = model.invoiceReciever;
userInfo.invoiceAddress = model.invoiceAddress;
userInfo.address = model.address;
userInfo.preferedLanguage = model.preferedLanguage;
bool saveSuccess = _repository.Save();
if(!saveSuccess)
{
return false;
}
return true;
}
My controller
[HttpPost]
public ActionResult Edit(UserSettingsModel model)
{
if(ModelState.IsValid)
{
if (_userService.UpdateUserInformationFromSettingsModel(model))
{
return RedirectToAction("Settings");
}
ModelState.AddModelError("", GuiText.editSettingsError);
}
return View(model);
}
The UserInformation Model
public class UserInformation
{
public int ID { get; set; }
public string firstName { get; set; }
public string lastName { get; set; }
public string phone { get; set; }
public string invoiceSendOption { get; set; }
public string invoiceReciever { get; set; }
public Address invoiceAddress { get; set; }
public Address address { get; set; }
public string preferedLanguage { get; set; }
public string confirmCode { get; set; }
public UserSiteSettings siteSettings { get; set; }
public UserInformation()
{
firstName = "";
lastName = "";
phone = "";
invoiceSendOption = "";
invoiceReciever = "";
invoiceAddress = new Address();
address = new Address();
preferedLanguage = "";
confirmCode = "";
siteSettings = new UserSiteSettings();
}
The UserSettingsModel
public class UserSettingsModel
{
public string userName { get; set; }
[Display(Name = "name", ResourceType=typeof(GuiText))]
public string firstName { get; set; }
public string lastName { get; set; }
[Display(Name = "phone", ResourceType = typeof(GuiText))]
public string phone { get; set; }
[Display(Name = "invoiceInfo", ResourceType = typeof(GuiText))]
public string invoiceReciever { get; set; }
public Address invoiceAddress { get; set; }
[Display(Name = "address", ResourceType = typeof(GuiText))]
public Address address { get; set; }
[Display(Name = "prefLang", ResourceType = typeof(GuiText))]
public string preferedLanguage { get; set; }
public List<SelectListItem> preferedLanguageList { get; set; }
I have checked the variables in debugger and it all seems to be ok.
I'm using MySql connector v6.5.4.
So anyone got any ideas what the problem might be?
After some days of frustration and searching i found the problem.
I used a custom made equals method in my UserInformation and Address class. That caused the problems. Now i have removed it and changed my Unit Tests to work in another way.