Unable to edit the user information in mvc - asp.net-mvc

Here is my problem , So i wanted to only allowing the user to change/edit their password and username only.
My original model for customer is this
public string IC { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Username{ get; set; }
public string Password{ get; set; }
And this is my VM for the customer
public string Username{ get; set; }
public string Password{ get; set; }
And this is my controller for the edit function
public ActionResult Edit([Bind(Include = "Username,Password")] CustomersVM customersVM )
{
if (ModelState.IsValid)
{
db.Entry(customersVM ).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
return View(customersVM );
}
view.cshtml
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
#Html.HiddenFor(model => model.IC)
<div class="form-group">
#Html.LabelFor(model => model.Username, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Username, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Username, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Password, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Password, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Password, "", new { #class = "text-danger" })
</div>
</div>
So this VM is to let the ModelState goes valid, which is will going right into the database but it turn out to turn this type of error
System.InvalidOperationException: 'The entity type CustomerVM is not part of the model for the current context.'

In order to edit/update a record, you need to identify that record first. I your case, your ViewModel is not what your database holds but the first model in your question. So you need to map that viewModel to the real model before saving or fetch the existing record then modify it then set it as modified before saving.
public ActionResult Edit([Bind(Include = "Username,Password")] CustomersVM customersVM )
{
if (ModelState.IsValid)
{
var existing = db.Customers.FirstOrDefault(x => x.Id == customersVM.Id);
if (existing != null)
{
existing.Username = customersVM.Username;
existing.Password = customerVM.Password;
db.Entry(existing ).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
}
return View(customersVM );
}

Related

How to store and display SelectList data

I am using SelectList to populate dropdownlists in my view. It works for the Create and Edit views to store ID value data in a table. How do I retrieve the 'Name' value to display in a Details view?
Model
Public Class Employee {
[Key]
public int ID { get; set;}
public string UserName {get; set; }
public byte Gender { get; set; }
}
ViewModel
public class EmployeeEditViewModel {
public int ID { get; set; }
public string UserName { get; set; }
public SelectList GenderList { get; set; }
public EmployeeEditViewModel () {
GenderList = CommonHelper.GenderList(null);
}
}
Helper
public static SelectList GenderList(object selected)
{
return new SelectList(new[]
{
new { Value = 0, Name = "Male" },
new { Value = 1, Name = "Female" }
}
, "Value", "Name", selected);
}
Edit View
#model Models.ViewModel.EmployeeEditViewModel
#using (Html.BeginForm()) {
#Html.HiddenFor(model => model.ID)
<div class="form-group">
#Html.LabelFor(model => model.UserName, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.UserName, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.UserName, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.GenderList, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownListFor(model => model.Gender, Model.GenderList, "- Select -", new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.GenderList, "", new { #class = "text-danger" })
</div>
</div>
}
Controller
[HttpPost]
public ActionResult CreateEmployee(EmployeeEditViewModel emProfile)
{
try
{
if (ModelState.IsValid)
{
Employee newUser = new Employee();
newUser.UserName = emProfile.UserName;
newUser.Gender = emProfile.Gender;
userRepository.Add(newUser);
userRepository.SaveChanges();
return RedirectToAction("Index");
}
}
catch (Exception ex)
{ }
return View(emProfile);
}
So far it works great, I am able to create, edit Employee records and 1 or 0 is stored in the table for the gender.
But when I want to display the employee data in a details view how do I get the text 'Male' or 'Female'?
I ended up creating a helper method to retrieve the text.
public static string GetTextFromSelectList(int id, string listName)
{
string selectedText = string.Empty;
SelectListItem selectedItem;
switch (listName)
{
case "Gender":
selectedItem = Helper.CommonHelper.GenderList(null).FirstOrDefault(x => x.Value == id.ToString());
selectedText = selectedItem == null ? null : selectedItem.Text;
break;
default:
selectedText = null;
break;
}
return selectedText;
}

How to realize DropDownListFor in View?

I want to show all names of "Category" in the dropdownlist in Create View by HtmlHelper.
The Model of "Category" is:
public class Category
{
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
}
The Controller is:
public ActionResult Create()//
{
ViewBag.Categorys = new SelectList(categoryRepo.SelectAll(), "Id", "Name");
return View();
}
The View is:
<div class="form-group">
#Html.LabelFor(model => model.CategoryId, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownListFor(model => model.CategoryId, (SelectList)ViewBag.Categorys, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.CategoryId, "", new { #class = "text-danger" })
</div>
</div>
You may try this,
#Html.DropDownList("Categorys", null, "Select Category", new {#class="form-control"})

Why always in the database, the DateTime property is null?

i 'm beginner in programming with MVC5.
I am working with MVC5 and Entity framework 6.
I have a class and a DateTime property like this:
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}",ApplyFormatInEditMode = true)]
[Column(TypeName = "datetime2")]
public DateTime? BirthDay { get; set; }
my controller:
public ActionResult Create([Bind(Include = "MelliCode,EnCode,grade,quota,password,FName,Lname,shenasname,FatehrName,sex,tel,mobile,ResAddress,WorkAddress")] Expert expert)
{
if (ModelState.IsValid)
{
db.Experts.Add(expert);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(expert);
}
and my view like this:
<div class="form-group">
#Html.LabelFor(model => model.BirthDay, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.BirthDay, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.BirthDay, "", new { #class = "text-danger" })
</div>
However, after the run of the page and enter personal information in the database is inserted to null for Birthday!!!why?
I found my problem
I had forgotten Birthday in [Bind] attribute
public ActionResult Create([Bind(Include = "BirthDay,MelliCode,EnCode,grade,quota,password,FName,Lname,shenasname,FatehrName,sex,tel,mobile,ResAddress,WorkAddress")] Expert expert)
{
if (ModelState.IsValid)
{
db.Experts.Add(expert);
db.SaveChanges();
return RedirectToAction("Index");
}

How to save dropdownlist selected value to the database int asp.net MVC 5

I am currently new to Asp.net MVC .In one of the view I add a dropdownlist and I bind this dropdownlist with my database like this
Controller CollegeController
[HttpGet]
public ActionResult Create()
{
IEnumerable<SelectListItem> items = db.College_Names.Select(c => new SelectListItem { Value = c.id.ToString(), Text = c.Name });
IEnumerable<SelectListItem> item = db.Stream_Names.Select(c => new SelectListItem { Value = c.id.ToString(), Text = c.Stream });
ViewBag.CollName=items;
ViewBag.StreamName = item;
return View();
}
[HttpPost]
public ActionResult Create(College college)
{
try
{
if(ModelState.IsValid)
{
db.Colleges.Add(college);
db.SaveChanges();
return RedirectToAction("Index");
}
ViewBag.CollName = db.Colleges;
return View(college);
}
catch
{
return View();
}
}
This is my model
public class College
{
[Required]
public int Id { get; set; }
[Required]
[Display(Name="College Name")]
public int CollegeName { get; set; }
[Required]
public int Stream { get; set; }
[Required]
[Column(TypeName="varchar")]
public string Name { get; set; }
....
public virtual College_Name College_Name { get; set; }
public virtual Stream_Name Stream_Name { get; set; }
}
This is My View
<div class="form-group">
#Html.LabelFor(model => model.CollegeName, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownList("CollName", (IEnumerable<SelectListItem>)ViewBag.CollName, "Select College", new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.CollegeName, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Stream, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownList("StreamName", (IEnumerable<SelectListItem>)ViewBag.StreamName, "Select Stream", new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.Stream, "", new { #class = "text-danger" })
</div>
</div>
Now when I check my database after I save the CollegeName and Stream in the database is zero from the dropdownlist.
You have multiple problems with your code. Firstly you dropdownlists are binding to a properties named CollName and StreamName which do not even exist in your model.
Next you cannot name the property your binding to the same as the ViewBag property.
Your view code would need to be (and always use the strongly typed xxxFor() HtmHelper methods
#Html.DropDownListFor(m => m.CollegeName, (IEnumerable<SelectListItem>)ViewBag.CollName, "Select College", new { #class = "form-control" })
....
#Html.DropDownListFor(m => m.Stream, (IEnumerable<SelectListItem>)ViewBag.StreamName, "Select Stream", new { #class = "form-control" }
and in your POST method, the values of college.CollegeName and college.Stream will contain the ID's of the selected options.
You also need to repopulate the ViewBag properties when you return the view in the POST method (as you did in the GET method) or an exception will be thrown (and note that your current use of ViewBag.CollName = db.Colleges; will also throw an exception)
I also strongly suggest you start learning to use view models (views for editing should not use data models - refer What is ViewModel in MVC?) - and use naming conventions that reflect what your properties are, for example CollegeNameList, or CollegeNames, not CollName

MVC how to retrieve the current date and time in a view

I have been looking for a while now and can't seem to find the answer. What I am trying to do is have the current date and the current Time in two fields on a create page. This page will be used for basic journey scheduling.
What I have so far is my model
public class Journey
{
public int JourneyId { get; set; }
public string Name { get; set; }
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:MM/dd/yyyy}",ApplyFormatInEditMode = true)]
public DateTime Departure { get; set; }
[DataType(DataType.Time)]
[DisplayFormat(DataFormatString="{0:hh\\:mm}", ApplyFormatInEditMode = true)]
public TimeSpan DepartureTime { get; set; }
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:MM/dd/yyyy}")]
public DateTime Arrival { get; set; }
public string Description { get; set; }
public int FareId { get; set; }
public int TrainId { get; set; }
public virtual FareType FareType { get; set; }
public virtual Train Train { get; set; }
}
Account Controller
public class JourneyController : Controller
{
private ApplicationDbContext db = new ApplicationDbContext();
//
// GET: Journey
public ActionResult Index()
{
return View(db.Journey.ToList());
}
//
// GET: Journey/Create
public ActionResult Create()
{
ViewBag.TrainId = new SelectList(db.Train, "TrainId", "Name");
return View();
}
// POST: Journey/Create
[HttpPost]
public ActionResult Create(Journey model)
{
try
{
if (ModelState.IsValid)
{
db.Journey.Add(model);
db.SaveChanges();
return RedirectToAction("Index");
}
ViewBag.TrainId = new SelectList(db.Train, "TrainId", "Name", model.TrainId);
return RedirectToAction("Index");
}
catch (DataException)
{
ModelState.AddModelError("", "Sorry something went wrong");
}
return View(model);
}
}
And finaly my view
<div class="form-horizontal">
<h4>Journey</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.Departure, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Departure, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Departure, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.DepartureTime, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.DepartureTime., new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.DepartureTime, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Arrival, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Arrival, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Arrival, "", new { #class = "text-danger" })
</div>
</div>
Any help would be great
Many thanks
Use custom getters and setters on your DateTime property to provide a default of now:
private DateTime? departure;
public DateTime Departure
{
get { return departure ?? DateTime.Today; }
set { departure = value; }
}
private DateTime? departureTime;
public DateTime DepartureTime
{
get { return departureTime ?? DateTime.Now; }
set { departureTime = value; }
}
private DateTime? arrival;
public DateTime Arrival
{
get { return arrival ?? DateTime.Today; }
set { arrival = value; }
}
Alternatively, you can just manually set the values in your action:
public ActionResult Create()
{
var journey = new Journey
{
Departure = DateTime.Today,
DepartureTime = DateTime.Now,
Arrival = DateTime.Today
};
ViewBag.TrainId = new SelectList(db.Train, "TrainId", "Name");
return View(journey);
}

Resources