I am having the difficulty to post back the new data being entered. It seems that the data sent to the view are sent back to the controller, despite changes made to the data before submit.
My code is as follows:
Controller
public class GroupRateController : Controller
{
//
// GET: /GroupRate/
public ActionResult Index()
{
GroupRateModel model = new GroupRateModel();
return View(model);
}
[HttpPost]
public ActionResult Index(GroupRateModel model)
{
model.Save(model);
return View(model);
}
}
View
#model MvcApplication1.Models.GroupRateModel
#{
View.Title = "Index";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>Index</h2>
#using (Html.BeginForm())
{
#Html.ValidationSummary()
<table>
<thead>
</thead>
<tr><th>Rate Group</th><th>Default Amount</th><th>Client Amount</th></tr>
#foreach (var item in #Model.ClientRateDetails)
{
<tr><td>#item.RateGroupName</td><td align="right">#Html.DisplayFor(m => #item.RateGroupID)</td><td>#Html.EditorFor(model => item.ClientRate)</td></tr>
}
</table>
<p> <input type ="submit" value="Save" id="submit" /></p>
}
Model
using System.ComponentModel.DataAnnotations;
namespace MvcApplication1.Models
{
public class GroupRateModel
{
public List<ClientRateDetailsModel> ClientRateDetails = new List<ClientRateDetailsModel>() ;
public string Name { get; set; }
public GroupRateModel()
{
ClientRateDetails.Add(new ClientRateDetailsModel
{
RateGroupID = 1,
RateGroupName = "Test1",
ClientRate = 100
});
ClientRateDetails.Add(new ClientRateDetailsModel
{
RateGroupID = 2,
RateGroupName = "Test2",
ClientRate = 200
});
ClientRateDetails.Add(new ClientRateDetailsModel
{
RateGroupID = 3,
RateGroupName = "Test3",
ClientRate = 300
});
}
public void Save(GroupRateModel model)
{
foreach (var item in model.ClientRateDetails)
{
//...;
}
}
}
public class ClientRateDetailsModel
{
[DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:00.00}", NullDisplayText = "")]
[Range(0, (double)decimal.MaxValue, ErrorMessage = "Please enter a valid rate")]
public decimal? ClientRate { get; set; }
public int? RateGroupID { get; set; }
public string RateGroupName { get; set; }
}
}
This might be because the names of your input controls don't have correct names for the model binder to be able to fetch the values correctly. Also I see that the ClientRateDetails is not a property but a field in your model which won't be bound correctly. So here's how I would suggest you to improve your code:
Start with the model:
public class GroupRateModel
{
public IEnumerable<ClientRateDetailsModel> ClientRateDetails { get; set; }
public string Name { get; set; }
public GroupRateModel()
{
// Remark: You cannot assign your ClientRateDetails collection here
// because the constructor will be called by the default model binder
// in the POST action and it will erase all values that the user
// might have entered
}
public void Save(GroupRateModel model)
{
foreach (var item in model.ClientRateDetails)
{
//...;
}
}
}
public class ClientRateDetailsModel
{
[DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:00.00}", NullDisplayText = "")]
[Range(0, (double)decimal.MaxValue, ErrorMessage = "Please enter a valid rate")]
public decimal? ClientRate { get; set; }
public int? RateGroupID { get; set; }
public string RateGroupName { get; set; }
}
then a controller:
public class HomeController: Controller
{
public ActionResult Index()
{
var model = new GroupRateModel();
model.ClientRateDetails = new[]
{
new ClientRateDetailsModel
{
RateGroupID = 1,
RateGroupName = "Test1",
ClientRate = 100
},
new ClientRateDetailsModel
{
RateGroupID = 2,
RateGroupName = "Test2",
ClientRate = 200
},
};
return View(model);
}
[HttpPost]
public ActionResult Index(GroupRateModel model)
{
model.Save(model);
return View(model);
}
}
and then the corresponding view:
#model MvcApplication1.Models.GroupRateModel
#{
View.Title = "Index";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>Index</h2>
#using (Html.BeginForm())
{
#Html.ValidationSummary()
<table>
<thead>
<tr>
<th>Rate Group</th>
<th>Default Amount</th>
<th>Client Amount</th>
</tr>
</thead>
#Html.EditorFor(x => x.ClientRateDetails)
</table>
<p><input type ="submit" value="Save" id="submit" /></p>
}
and then have a corresponding editor template (~/Views/Home/EditorTemplates/ClientRateDetailsModel.cshtml):
#model MvcApplication1.Models.ClientRateDetailsModel
<tr>
<!-- Make sure you include the ID as hidden field
if you want to get it back inside the POST action
-->
#Html.HiddenFor(x => x.RateGroupID)
<td>#Model.RateGroupName</td>
<td align="right">#Model.RateGroupID</td>
<td>#Html.EditorFor(x => x.ClientRate)</td>
</tr>
Related
I am trying to insert selected checkbox values to database. But I get an error
Unable to cast object of type 'System.Collections.Generic.List` to type 'System.String'
Please help. Thanks.
Model:
public class CheckboxModel
{
public int Id { get; set; }
public string Name { get; set; }
public bool Checked { get; set; }
}
public class MainModel
{
public List<CheckboxModel> CheckBoxes { get; set; }
}
HomeController:
// Get
public ActionResult Index()
{
MainModel model = new MainModel();
var list = new List<CheckboxModel>
{
new CheckboxModel{Id = 1, Name = "Male", Checked = false},
new CheckboxModel{Id = 2, Name = "Female", Checked = false},
};
model.CheckBoxes = list;
return View(model);
}
[HttpPost]
public ActionResult Create([Bind(Include = "Checkboxes")] MainModel model)
{
if (ModelState.IsValid)
{
db.MainModel.Add(model);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(MainModel);
}
View:
#using (Html.BeginForm("Create", "Home", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
#for (var i = 0; i < Model.Checkboxes.Count; i++)
{
<table>
<tr>
<td>
#Html.HiddenFor(m => Model.Checkboxes[i].Id)
#Html.HiddenFor(m => Model.Checkboxes[i].Name)
#Html.CheckBoxFor(m => Model.Checkboxes[i].Checked)
</td>
<td>
#Html.DisplayFor(m => Model.Checkboxes[i].Name)
</td>
</tr>
</table>
}
1) How to pass id in AddBookInCategory form in #Html.EditorFor(model=>model.CategoryID).
2) And second how after adding new item in public ActionResult AddBookInCategory(Books book) return to category with id it must be something like return RedirectToAction("ShowBooksFromCategory", 1); but it does not work.
HomeController:
public class HomeController : Controller
{
//
// GET: /Home/
TEntities TE = new TEntities();
public ActionResult Index()
{
return View();
}
public ActionResult ShowCategories()
{
return View(TE.Category.ToList());
}
public ActionResult ShowBooksFromCategory(int id)
{
return View(TE.Books.Where(key => key.CategoryID == id).ToList());
}
public ActionResult AddBookInCategory(int id)
{
return View();
}
[HttpPost]
public ActionResult AddBookInCategory(Books book)
{
TE.Books.Add(book);
TE.SaveChanges();
return View();
//return RedirectToAction("ShowBooksFromCategory", 1);
}
}
AddBookInCategory.cshtml:
#model TestDataBase.Models.Books
#{
ViewBag.Title = "AddBookInCategory";
}
<h2>AddBookInCategory</h2>
#using(#Html.BeginForm())
{
<p>Book Name:</p>
<br />
#Html.EditorFor(model=>model.BookName)
<p>Category:</p>
<br />
#Html.EditorFor(model=>model.CategoryID)
<input type="submit" value="Create"/>
}
Index.cshtml
#{
ViewBag.Title = "Index";
}
<h2>Index</h2>
#Html.ActionLink("ShowCategories", "ShowCategories")
ShowBooksFromCategory.cshtml
#model IEnumerable<TestDataBase.Models.Books>
#{
ViewBag.Title = "ShowBooksFromCategory";
}
<h2>ShowBooksFromCategory</h2>
<table>
#foreach(var item in Model)
{
<tr>
<td>
#item.BookName
</td>
</tr>
}
</table>
#Html.ActionLink("Add item", "AddBookInCategory", new {id=Model.Select(key=>key.CategoryID).FirstOrDefault() })
ShowCategories.cshtml
#model IEnumerable<TestDataBase.Models.Category>
#{
ViewBag.Title = "ShowCategories";
}
<h2>ShowCategories</h2>
<table>
#foreach(var item in Model )
{
<tr>
<td>
#item.CategoryName
</td>
<td>
#Html.ActionLink("ShowBooksFromCategory", "ShowBooksFromCategory", new { id=item.CategoryID})
</td>
</tr>
}
</table>
Models:
public partial class Books
{
public int CategoryID { get; set; }
public string BookName { get; set; }
public int BookID { get; set; }
}
public partial class Category
{
public int CategoryID { get; set; }
public string CategoryName { get; set; }
}
Hi #A191919 To redirect with an int you can do the following (this is exactly the same thing you did within your actionlink to get the first form..)
return RedirectToAction("ShowBooksFromCategory", new { id = book.CategoryID });
To get the ID into your form you could use ViewBag.
public ActionResult AddBookInCategory(int id)
{
ViewBag.id = id;
return View();
}
The use the viewbag value to fill in your form input.
I have read the tutorials and prepared a list of checkboxes for the page. When the form is submitted, the Selected property only get the value false.
Is there something I missed?
The Model
public class SelectStudentModel
{
public int StudentID { get; set; }
public string CardID { get; set; }
public string Name { get; set; }
public bool Selected { get; set;}
}
The ViewModel
public class SelectStudentViewModel
{
public List<SelectStudentModel> VMList;
public SelectStudentViewModel()
{
VMList = SelectStudentModel.GETStudent();
}
}
The View
#using Student.Models
#model SelectStudentViewModel
#using (Html.BeginForm("AddStudent", "SectionStudent", FormMethod.Post, new { #role = "form" }))
{
#{ for (int i = 0; i < Model.VMList.Count(); i++)
{
<tr>
<td>#Html.CheckBoxFor(m => m.VMList[i].Selected)</td>
<td>#Html.DisplayFor(model => model.VMList[i].Name)</td>
</tr>
}
}
<input type="submit" value="submit" />
}#* end form *#
The Controller for posted data
[HttpPost]
public ActionResult AddStudent(SelectStudentViewModel model)
{
foreach (SelectStudentModel m in model.VMList)
{
Console.Write(m.Selected.ToString());
}
return PartialView("StudentSelectForm", model);
}
VMList is a field in your SelectStudentViewModel model. You need to change it to a property (with a getter/setter) so the DefaultModelBinder can set the values
public class SelectStudentViewModel
{
public List<SelectStudentModel> VMList { get; set; } // change
public SelectStudentViewModel()
{
VMList = SelectStudentModel.GETStudent();
}
}
Side note: Suggest you change #Html.DisplayFor(model => model.VMList[i].Name) to #Html.LabelFor(m => m.VMList[i].Selected, Model.MList[i].Name) so that you get a label associated with the checkbox
Model Room:
public class Room
{
public int Id { get; set; }
public string NumberRoom { get; set; }
public double CostPerNight { get; set; }
public virtual Category Category { get; set; }
}
My view model code
public class RoomModel
{
public IList<Room> Rooms { get; set; }
}
My Razor code:
#model hotel.Models.RoomModel
#using (Html.BeginForm("ComfortLevelView", "Category"))
{
for (int i = 0; i < Model.Rooms.Count(); i++)
{
<table class="simple-little-table" cellspacing='0'>
<tr>
<td>#Html.DisplayFor(m => Model.Rooms[i].NumberRoom) </td>
<td>#Html.DisplayFor(m => Model.Rooms[i].Categoryid)</td>
<td>#Html.DisplayFor(m => Model.Rooms[i].NumberOfSeats) </td>
<td>
#{ var result = Model.Rooms[i].CostPerNight * numberNights; }
<p>#ViewBag.NumberNights ночей</p>:#result
</td>
<td>
<input type="submit" id="submit" value="Booking" />
</td>
</tr>
</table>
</div>
}
}
Controller:
public ActionResult ComfortLevelView(int NumberNights, int CategoryId, int NumberPeoples ,DateTime SelectedDate)
{
IRoomService roomService = new RoomService();;
return View(roomService.GetRoomsByCategory(CategoryId, SelectedDate, NumberNights, NumberPeoples));
}
[HttpPost]
public ActionResult ComfortLevelView(RoomModel model)
{
//
}
The model item passed into the dictionary is of type 'System.Data.Entity.Infrastructure.DbQuery`1[Hotel.BusinessObject.Room]', but this dictionary requires a model item of type 'hotel.Models.RoomModel'.
The error message is self explanatory. You have this in your view
#model hotel.Models.RoomModel
but you pass an instance of System.Data.Entity.Infrastructure.DbQuery<Hotel.BusinessObject.Room> to your view because of this line of code in your controller
return View(roomService.GetRoomsByCategory(CategoryId, SelectedDate, NumberNights, NumberPeoples));
You need to pass an instance of RoomModel instead of System.Data.Entity.Infrastructure.DbQuery<Hotel.BusinessObject.Room>. I would suggest changing your controller code to below
public ActionResult ComfortLevelView(int NumberNights, int CategoryId, int NumberPeoples, DateTime SelectedDate)
{
IRoomService roomService = new RoomService();
var rooms = roomService.GetRoomsByCategory(CategoryId, SelectedDate, NumberNights, NumberPeoples);
RoomModel model = new RoomModel();
model.Rooms = rooms.ToList();
return View(model);
}
I am new to MVC and am trying to populate a DropDownList in my view with a list of 'rules' from my controller. When I do it the way listed, I just get a dropdownlist with a bunch of items that say CellularAutomata.Models.Rules. I know I am doing this incorrectly, I'm just wondering how I actually get it to show the rule description for each rule in the dropdownlist.
I have a Model
public class Rule
{
public int ID { get; set; }
public int Name { get; set; }
public string Description{ get; set; }
public Rule(int name, string description)
{
Name = name;
Description = description;
}
public Rule()
{
Name = 0;
Description = "";
}
}
A Controller
public ActionResult Index()
{
var rules = from rule in db.Rules
select rule;
return View(rules.ToList());
}
And a view
#model IEnumerable<CellularAutomata.Models.Rule>
#{
ViewBag.Title = "Index";
}
<h2>Index</h2>
<table>
<tr>
<td>
#Html.DropDownList("Test", new SelectList(Model))
</td>
</tr>
</table>
You could have a view model:
public class MyViewModel
{
public string SelectedRuleId { get; set; }
public IEnumerable<Rule> Rules { get; set; }
}
and then in your controller:
public ActionResult Index()
{
var model = new MyViewModel
{
Rules = db.Rules
};
return View(model);
}
and in the view:
#model CellularAutomata.Models.MyViewModel
#{
ViewBag.Title = "Index";
}
<h2>Index</h2>
#Html.DropDownListFor(
x => x.SelectedRuleId,
new SelectList(Model.Rules, "ID", "Description")
)