modelBinding works when using model but not with viewmodel - c#

I'm trying to get a dropdown show the right value when editing using a viewmodel but it only works when i pass the complete model to the view.
When I do it like this and there is already a contact selected it shows that contact in the edit screen.
Model
public class ClientModel
{
public int ID { get; set; }
public int ContactID { get; set; }
//Other atributes
}
View EditContact
#model Project.Models.ClientModel
#Html.DropDownListFor(model => model.ContactID , (SelectList)ViewBag.ContactID, "select a contact")
Controller
public ActionResult EditContact(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
var Contact = db.Contacts.ToList();
ViewBagID.Contact = new SelectList(Contact.AsEnumerable(), "ID", "name", "Contact");
ClientModel model= db.ClientModel.Find(id);
return View(model);
}
But when I do it like this and there is already a contact selected the dropdownlist shows select contact.
Model
public class ClientModel
{
public int ID { get; set; }
public int ContactID { get; set; }
//Other atributes
}
ViewModel
public class ClientEditContactModel
{
public int ID { get; set; }
public int ContactID { get; set; }
}
View EditContact
#model Project.Models.ClientEditContactModel
#Html.DropDownListFor(model => model.ContactID, (SelectList)ViewBag.ContactID, "select a contact")
Controller
public ActionResult EditContact(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
var Contact = db.Contacts.ToList();
ViewBag.ContactID = new SelectList(Contact.AsEnumerable(), "ID", "name", "Contact");
ClientModel client= db.ClientModel.Find(id);
ClientEditContactModel model = new ClientEditContactModel();
model.ID = client.ID;
model.ContactID = client.ContactID
return View(model);
}
How do i fix this with the viewmodel?
Edit
I've made some typo's in my code so I fixed them but because of them i found the answer see below.

I found the answer after some more research here https://stackoverflow.com/a/11949123/4252392.
The problem was that ViewBag's name is the same as the model's property.
So i changed the Viewbag's name.
New Controller
public ActionResult EditContact(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
var Contact = db.Contacts.ToList();
ViewBag.ContactIDList = new SelectList(Contact.AsEnumerable(), "ID",
"name", "Contact");
ClientModel client= db.ClientModel.Find(id);
ClientEditContactModel model = new ClientEditContactModel();
model.ID = client.ID;
model.ContactID = client.ContactID
return View(model);
}
New View
#model Project.Models.ClientEditContactModel
#Html.DropDownListFor(model => model.ContactID, (SelectList)ViewBag.ContactIDList,
"select a contact")

If you set selected value in ContactID property from dropdown so you need to set dropdown in view like below:
#model Project.Models.ClientEditContactModel
#Html.DropDownListFor(model => model.ContactID, (SelectList)ViewBag.Contact,
"select a contact")

Related

How to Edit using a ViewModel in MVC?

I am new to MVC and trying to understand ViewModels. I understand how to use Create and a ViewModel, But am unsure how to Edit using a View Model?
My VM:
public class BookingViewModel
{
[Display (Name = "Select Patient")]
public Guid PatientId { get; set; }
public IEnumerable<SelectListItem> PatientList { get; set; }
[Display(Name = "Select Practice")]
public Guid PracticeId { get; set; }
public IEnumerable<SelectListItem> PracticeList { get; set; }
[Display(Name = "Select Optician")]
public Guid OpticianId { get; set; }
public IEnumerable<SelectListItem> OpticiansList { get; set; }
public Optician Optician { get; set; }
[Display(Name = "Select Date")]
[DataType(DataType.Date)]
[DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:dd/MM/yyyy}")]
public DateTime Date { get; set; }
[Display(Name = "Select Time")]
public Guid TimeId { get; set; }
public IEnumerable<SelectListItem> TimeList { get; set; }
}
My Controller:
public ActionResult Create()
{
// Creates a new booking
BookingViewModel bookingViewModel = new BookingViewModel();
// Initilises Select List
ConfigureCreateViewModel(bookingViewModel);
return View(bookingViewModel);
}
// Initilises Select List
public void ConfigureCreateViewModel(BookingViewModel bookingViewModel)
{
// Displays Opticians Name - Needs changed to full name
bookingViewModel.OpticiansList = db.Opticians.Select(o => new SelectListItem()
{
Value = o.OpticianId.ToString(),
Text = o.User.FirstName
});
// Displays Patients name - needs changed to full name DOB
bookingViewModel.PatientList = db.Patients.Select(p => new SelectListItem()
{
Value = p.PatientId.ToString(),
Text = p.User.FirstName
});
// Displays Practice Name
bookingViewModel.PracticeList = db.Practices.Select(p => new SelectListItem()
{
Value = p.PracticeId.ToString(),
Text = p.PracticeName
});
// Displays Appointment Times
bookingViewModel.TimeList = db.Times.Select(t => new SelectListItem()
{
Value = t.TimeId.ToString(),
Text = t.AppointmentTime
});
}
// Allows Admin to create booking for patient
// POST: Bookings1/Create
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(BookingViewModel bookingViewModel)
{
// to ensure date is in the future
if (ModelState.IsValidField("Date") && DateTime.Now > bookingViewModel.Date)
{
ModelState.AddModelError("Date", "Please enter a date in the future");
}
// if model state is not valid
if (!ModelState.IsValid)
{
// Initilises Select lists
ConfigureCreateViewModel(bookingViewModel);
return View(bookingViewModel); // returns user to booking page
}
else // if model state is Valid
{
Booking booking = new Booking();
// Sets isAvail to false
booking.isAvail = false;
booking.PracticeId = bookingViewModel.PracticeId;
booking.Optician = bookingViewModel.Optician;
booking.PatientId = bookingViewModel.PatientId;
booking.Date = bookingViewModel.Date;
booking.TimeId = bookingViewModel.TimeId;
// Generates a new booking Id
booking.BookingId = Guid.NewGuid();
// Adds booking to database
db.Bookings.Add(booking);
// Saves changes to Database
db.SaveChanges();
// Redirects User to Booking Index
return RedirectToAction("Index");
}
}
I am really unsure how to Edit a View Model, any advice would be greatly appreciated
public ActionResult Edit(Guid? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Booking booking = db.Bookings.Find(id);
if (booking == null)
{
return HttpNotFound();
}
BookingViewModel bookingViewModel = new BookingViewModel()
{
Date = booking.Date,
OpticianId = booking.OpticianId,
PatientId = booking.PatientId,
PracticeId = booking.PracticeId,
TimeId = booking.TimeId
};
return View(booking, bookingViewModel);
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(Booking booking)
{
if (ModelState.IsValid)
{
db.Entry(booking).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
return View(booking);
}
There is no overload of Controller.View method that accepts 2 models/objects.
You Edit() GET method needs to be
public ActionResult Edit(Guid? id)
{
....
BookingViewModel bookingViewModel = new BookingViewModel()
{
....
}
// Call the ConfigureCreateViewModel() method so that you SelectList's are populated
// as you have done in the Create() method (ConfigureViewModel might be a better name?)
ConfigureCreateViewModel(bookingViewModel);
return View(bookingViewModel); // adjust this
}
and the POST method needs to be
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(BookingViewModel model)
{
if (!ModelState.IsValid)
{
ConfigureCreateViewModel(model)
return View(model);
}
// Get your data model and update its properties based on the view model
Booking booking = db.Bookings.Find(id);
booking.PracticeId = bookingViewModel.PracticeId;
booking.OpticianId = bookingViewModel.OpticianId;
.... // etc
db.Entry(booking).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
and your view should have #model BookingViewModel
Side note: Your view model should not contain property public Optician Optician { get; set; } (you binding to the property public Guid OpticianId { get; set; })

List not converting to IEnumerable

Below is the error i getting :
The model item passed into the dictionary is of type 'System.Collections.Generic.List[StoredProcedureEF_MVC.tbl_users]', but this dictionary requires a model item of type 'System.Collections.Generic.IEnumerable[StoredProcedureEF_MVC.Models.User]'.
I have tried a lot but don't know where i was doing wrong, no luck from last two days. I am learning MVC, so sorry if you got some stupid mistake.
My Model :
namespace StoredProcedureEF_MVC.Models
{
[Table("tbl_users")]
public class User
{
[Key]
public int UserId { get; set; }
[Required]
public string Username {get;set;}
[Required]
public string Email { get; set; }
}
}
VIEW:
#model IEnumerable<StoredProcedureEF_MVC.Models.User>
#{
ViewBag.Title = "Delete";
}
#{
var grid = new WebGrid(source: Model);
}
#grid.GetHtml(
columns: grid.Columns(
grid.Column("UserID"),
grid.Column("Username"),
grid.Column("Email"),
grid.Column(
format: (item) => Html.ActionLink("Delete", "DeleteUser", new {id=item.UserID })
)
)
)
CONTROLLER ACTION:
[HttpGet]
public ActionResult Delete()
{
SPEFMVCEntities conn = new SPEFMVCEntities();
var result = (from p in conn.tbl_users select p).ToList();
return View(result);
}
try
var result = conn.tbl_users.Select(c => new StoredProcedureEF_MVC.Models.User
{
UserId = c.UserId,
UserName = c.UserName,
Email = c.Email
}).ToList();
return View(result);
Try to change your controller method to this:
[HttpGet]
public ActionResult Delete()
{
SPEFMVCEntities conn = new SPEFMVCEntities();
var result = (from p in conn.tbl_users select p as StoredProcedureEF_MVC.Models.User).ToList();
return View(result);
}

getting generics error when try to bind the grid

I am trying to bind the grid (Kendo UI) with user entered values in TextBox, but when I start the program, I get an error like this,
Exception Details: System.InvalidOperationException: The model item passed into the dictionary is of type 'System.Collections.Generic.List`1[KendoPratapSampleMVCApp.Models.EmployeeDetails]', but this dictionary requires a model item of type 'KendoPratapSampleMVCApp.Models.ParentViewModel'.
When the user entered the value in TextBox and then presses the submit button, the entered value needs to show in the grid.
This is my model,
namespace KendoPratapSampleMVCApp.Models
{
public class TextBoxGrid
{
public string EnteredValue { get; set; }
public List<EmployeeDetails> employees;
}
public class ParentViewModel
{
public EmployeeDetails EmployeeDetails { get; set; }
public TextBoxGrid TextBoxGrid { get; set; }
}
public class EmployeeDetails
{
public string EmployeeId { get; set; }
public string ManagerId { get; set; }
}
}
This is my controller (where i am binding the user entered value to grid)
namespace KendoPratapSampleMVCApp.Controllers
{
public class EnterValuesGridController : Controller
{
public ActionResult Index( TextBoxGrid model)
{
return View(GetEmployee());
}
[HttpPost]
public ActionResult PostValues(TextBoxGrid model)
{
TempData["enteringValue"] = model.EnteredValue;
return View(model);
}
public IEnumerable<EmployeeDetails> GetEmployee()
{
string enteredValueId =(string) TempData["enteringValue"];
string managerId = "M" +enteredValueId;
List<EmployeeDetails> empdtls = new List<EmployeeDetails>();
EmployeeDetails em1 = new EmployeeDetails();
em1.EmployeeId = enteredValueId;
em1.ManagerId = managerId;
empdtls.Add(em1);
return empdtls;
}
public ActionResult Orders_Read([DataSourceRequest]DataSourceRequest request)
{
return Json(GetOrders().ToDataSourceResult(request));
}
private IEnumerable<EmployeeDetails> GetOrders()
{
return GetEmployee();
}
}
}
And this is my view where I am displaying the grid,
#model KendoPratapSampleMVCApp.Models.ParentViewModel
#{
ViewBag.Title = "Index";
}
#using (Html.BeginForm("PostValues","EnterValuesGrid",FormMethod.Post))
{
#Html.TextBoxFor(m=>m.TextBoxGrid.EnteredValue)
<input type="submit" name="Submitbutton1" value="Submit1" />
#(Html.Kendo().Grid<KendoPratapSampleMVCApp.Models.ParentViewModel>()
.Name("grid")
.Columns(columns => {
columns.Bound(s=>s.EmployeeDetails.EmployeeId).Filterable(false).Width(100);
columns.Bound(s => s.EmployeeDetails.ManagerId).Filterable(false).Width(100);
})
.Pageable()
.Sortable()
.Scrollable()
.Filterable()
.HtmlAttributes(new { style = "height:430px;" })
.DataSource(dataSource => dataSource
.Ajax()
.PageSize(20)
.Read(read => read.Action("Orders_Read", "EnterValuesGrid"))
)
)
}
Would anyone please tell me why I am getting this error. How can I resolve this one?
EDIT : Changed postvalue method
[HttpPost]
public ActionResult PostValues(TextBoxGrid model)
{
TempData["enteringValue"] = model.EnteredValue;
var viewmodel = new ParentViewModel
{
TextBoxGrid = new TextBoxGrid { employees = GetEmployee().ToList() }
};
return View("Index", viewmodel);
}
when I submit the button it not showing the values in grid but its showing empty grid...
Error, because model of your view is ParentViewModel, but you give its with
return view(GetEmployee);
IEnumerable, so not corresponding object for model of view.
I advice you do it as follow
public ActionResult Index( TextBoxGrid model)
{
var viewModel = new ParentViewModel
{
TextBoxGrid = new TextBoxGrid { employees = GetEmployee().ToList()}
//but first change TextBoxGrid Property from emplyees to employees{get;set;}, second from return empdtls; to return empdtls.AsEnumarable();
}
return View(viewModel);
}
You must create PostValues view,, or change PostValues to Index, if its give you dublicat change you code as follow
[HttpPost]
public ActionResult PostValues(TextBoxGrid model)
{
TempData["enteringValue"] = model.EnteredValue;
return View("Index",model);
}

Fill Dropdownlist with values from database - MVC4

i have a table in my database which i select all rows to fill it in my dropdownlist in my view.
i canĀ“t understand how can i fill the values in there.
someone can give me a hand?
My code:
Model:
public class MyList
{
public int id { get; set; }
public string name{ get; set; }
}
public class Empresas
{
public static IEnumerable<MyList> Getmyinformation()
{
var list = new List<MyList>();
string connection = ConfigurationManager.ConnectionStrings["DefaultConnection"].ConnectionString;
using (var con = new SqlConnection(connection))
{
con.Open();
using (var command = new SqlCommand("SELECT * FROM mytable", con))
{
SqlDataReader reader = command.ExecuteReader();
while (reader.Read())
{
string Name= reader[1] as string;
list.Add(new MyList() { name= Name});
}
}
con.Close();
}
return list;
}
}
public class DefaultConnection : DbContext
{
public DbSet<MyList> lat { get; set; }
}
Controller:
private DefaultConnection db = new DefaultConnection();
public ActionResult Add()
{
return View(db.lat.ToList());
}
View:
#Html.DropDownListFor("-- Select --", new SelectList("")) <=== ???? i dont know
Simply in controller type:
ViewBag.CategoryList = new SelectList(db.Categories.ToList(), "Id", "Name");
And in view write:
#Html.DropDownListFor(model => model.CategoryId, ViewBag.CategoryList as IEnumerable<SelectListItem>, new { #class = "anyclass" })
In my practice I create dropdownlist as follow:
first I create view model
public class MyObj
{
public int id { get; set; }
public string name{ get; set; }
}
// viewmodel
public class MyviewModel
{
public IQuerable<MyObj> MyObjs{get;set;}
public Other Other{get;set;}
}
then I pass this model from controller to view
private DefaultConnection db = new DefaultConnection();
public ActionResult Index()
{
var drop = new MyviewModel
{
MyObjs = db.MyObjs,// selecting table...
Other = new Other
}
return View(drop);
}
in Controller
#Html.DropDownListFor(model => model.Other.MyObjId, new SelectList(Model.MyObjs , "id", "name","--select--"))
Try this,
View :-
#Html.DropDownListFor(m => m.CustomerId, Model.customerNameList, "--Select--")
Controller:-
public ActionResult CustomerInfo()
{
var List = GetCustomerName();
ViewBag.CustomerNameID = new SelectList(List, "CustomerId", "customerName");
ViewBag.RegisterItems = GetAllRegisterData();
return View();
}
public List<CustomerModel> GetCustomerName()
{
// Customer DropDown
using (dataDataContext _context = new dataDataContext())
{
return (from c in _context.Customers
select new CustomerModel
{
CustomerId = c.CID,
customerName = c.CustomerName
}).ToList<CustomerModel>();
}
}
Model:
public class CustomerModel
{
public int CustomerId { get; set; }
[StringLength(9), Required, DisplayName("Social security number")]
[RegularExpression(#"\d{3}-\d\d-\d{4}", ErrorMessage = "Invalid social security number")]
public string customerName { get; set; }
public List<MyListItems> customerNameList { get; set; }
}
Create a ViewModel like this:
public class ListViewModel
{
public MyList MyList { get; set; }
public int SelectedId { get; set; }
}
Then, change your Action to this:
public ActionResult Add()
{
var viewModel = new ListViewModel { MyList = db.lat.ToList() };
return View(viewModel);
}
And, then, this is what you will have in your View:
#model MyApp.ViewModels.ListViewModel
#Html.DropDownListFor(model => model.SelectedId, new SelectList(Model.MyList as IEnumerable, "Id", "Name"))

How to update a textarea in the current view on Submit in ASP.net MVC 3?

I have a page that has two drop down lists and based upon the selection of these two lists I would like to populate a textarea with some data on submit button press.
The behavior that I am seeing while debugging is that the page is rendered, I make my selections and press submit. The DataAccess returns the correct results and the View returns, but with an exception "There is no ViewData item of type 'IEnumerable' that has the key 'People'.
I can see that I could re-setup the drop down lists, but it feels like I'm approaching this incorrectly. Is there another approach for doing this sort of action in MVC 3?
public ActionResult Test()
{
//People for dropdownlist 1
var db = peopleRepository.People;
var query = db.Select(c => new {c.Id, c.Name});
ViewBag.People = new SelectList(query.AsEnumerable(), "Id", "Name");
//Elements for dropdownlist 2
var list = new Dictionary<string, string> {{"1", "Name"}, {"2", "Address"}, {"3", "Zip"}};
ViewBag.Elements = new SelectList(list, "Key", "Value");
return View();
}
// This part is what I'm confused about.
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Test(string people, string elements)
{
if (ModelState.IsValid)
{
// Output from persistent storage query
var da = new DatabaseAccess(people, elements);
ViewBag.Results = da.Execute();
}
return View();
}
View:
#using (Html.BeginForm("Test", "Home", FormMethod.Post))
{
#Html.DropDownList("People", (SelectList)ViewBag.People, "--Select One--")
#Html.DropDownList("Elements", (SelectList)ViewBag.Elements, "--Select One--")
#Html.TextArea("Results", (string)ViewBag.Results, 10, 120, "")
}
Here is how I would quickly construct it :
Model :
public class People
{
public int Id { get; set; }
public string Name { get; set; }
}
ViewModel (everything needed by the view):
public class TestViewModel
{
public int SelectedPeopleId { get; set; }
public string SelectedElementId { get; set; }
public SelectList People { get; set; }
public SelectList Elements { get; set; }
public String Results { get; set; }
}
Controller (used Index as the default Action, create an init function for the view model that can be adapted)to anything more appropriate :
public class HomeController : Controller
{
private static TestViewModel InitTestVM()
{
//People for dropdownlist 1
var db = new List<People>();//peopleRepository.People;
db.Add(new People { Id = 1, Name = "Name 1" });
db.Add(new People { Id = 2, Name = "Name 2" });
var query = db.Select(c => new { c.Id, c.Name });
//Elements for dropdownlist 2
var list = new Dictionary<string, string> { { "1", "Name" }, { "2", "Address" }, { "3", "Zip" } };
TestViewModel testVM = new TestViewModel
{
People = new SelectList(query.AsEnumerable(), "Id", "Name"),
Elements = new SelectList(list, "Key", "Value")
};
return testVM;
}
public ActionResult Index()
{
return View(InitTestVM());
}
// This part is what I'm confused about.
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Index(TestViewModel testVM)
{
var vm = InitTestVM();
if (ModelState.IsValid && testVM != null)
{
ModelState.Clear();
// Output from persistent storage query
//var da = new DatabaseAccess(people, elements);
vm.Results = "sfdfsdfsdfsdfsdfsdfsdfsdf";//da.Execute();
vm.SelectedElementId = testVM.SelectedElementId;
vm.SelectedPeopleId = testVM.SelectedPeopleId;
return View(vm);
}
return View(vm);
}
}
And finally the View :
#model ViewModels.TestViewModel
#using (Html.BeginForm("Index", "Home", FormMethod.Post))
{
#Html.DropDownListFor(m => m.SelectedPeopleId, Model.People, "--Select One--")
#Html.DropDownListFor(m => m.SelectedElementId, Model.Elements, "--Select One--")
#Html.TextAreaFor(m => m.Results, 10, 120, "")
<input type="submit" value="Test" />
}

Categories

Resources