Pass 2 parameters into view - asp.net-mvc

I've got a view where I create new object and pass it to another view:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "ID,carID,DateFrom,DateTo,UserID")] Reservation reservation)
{
if (ModelState.IsValid)
{
return RedirectToAction("ChooseCars",reservation);
}
return View(reservation);
}
in "ChooseCars" I have:
public ActionResult ChooseCars(Reservation reservation)
{
var reservations = db.Reservations.ToList();
var cars = db.Cars.ToList();
var reservationsResult = reservations.Where(res => res.DateFrom <= reservation.DateFrom && res.DateTo >= reservation.DateTo);
if (reservationsResult != null)
{
emptyCars = cars.Where(c => !reservationsResult.Any(y => y.carID == c.ID));
cars = emptyCars.ToList();
}
return View(cars);
}
and in that "ChooseCars" view I populate table with list of Cars that haven't been reserved.. Now I need to somehow pass that reservation and chosen car (by id) to some method where I create new "reservation" object containing carId.
What is the best way to do that?
I wrote a method, but I have no idea how to route those parameters to it:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult AddReservation([Bind(Include = "ID,carID,DateFrom,DateTo,UserID")] Reservation reservation, int? id)
{
Reservation finalReservation = new Reservation(id, reservation.DateFrom, reservation.DateTo, reservation.UserID);
db.Reservations.Add(finalReservation);
return View();
}
How it looks:

Your editing data, so the first thing is to create a view model(s) representing want you want to edit/display in the view. In your case you need the start and end dates, a collection of Car and the selected car.
public class ReservationVM // add validation and display attributes as appropriate
{
public DateTime StartDate { get; set; }
public DateTime EndDate { get; set; }
public int? SelectedCar { get; set; }
public IEnumerable<Car> AvailableCars { get; set; }
}
And your controller methods will be
[HttpGet]
public ActionResult Create()
{
ReservationVM model = new ReservationVM();
return View(model);
}
[HttpPost]
public ActionResult Create(ReservationVM model)
{
if (!ModelState.IsValid)
{
return View(model);
}
var availableCars = ... // your query to load the collection of cars basd on the dates
if (!availableCars.Any())
{
ModelState.AddModelError("", "There are no cars available for these dates");
return View(model);
}
model.AvailableCars = availableCars;
return View("SelectCar", model);
}
[HttpPost]
public ActionResult Confirm(ReservationVM model)
{
// Initialize new Reservation, save and redirect
Reservation reservation = new Reservation()
{
StartDate = model.StartDate,
EndDate = model.EndDate,
CarId = model.SelectedCar.Value,
UserId = ... // current user?
};
db.Reservations.Add(reservation);
db.SaveChanges();
return RedirectToAction(....);`
}
And the views will be
Create.cshtml
#model ReservationVM
...
#using (Html.BeginForm())
{
#Html.TextBoxFor(m => m.StartDate)
#Html.TextBoxFor(m => m.EndDate)
<input type="submit" value="Next" />
}
SelectCar.cshtml
#model ReservationVM
....
<table>
#foreach(var car in Model.AvailableCars)
{
<tr>
<td>#car.Make</td>
<td>#car.Model</td>
....
<td>
#using (Html.BeginForm("Confirm", "Home", new { StartDate = Model.StartDate, EndDate = Model.EndDate, SelectedCar = car.ID }))
{
<input type="submit" value="Reserve" />
}
</td>
</tr>
}
</table>

Related

Combining Create and Index Views in one View in Asp.Net MVC 5

I have a controller in my Dashboard Area and an action to return categories as a list to view and another action to create new category
My Actions:
public ActionResult Categories() {
return View(db.Categories.OrderBy(Categories => Categories.Name).ToList());
}
[HttpPost]
public RedirectToRouteResult NewCategory(string name, string address, string parentId) {
if (ModelState.IsValid) {
int? ParentID = null;
if (parentId != "null") {
ParentID = parentId.AsInt();
}
Category oCategory = new Category();
oCategory.Name = name;
oCategory.Address = address;
oCategory.ParentID = ParentID;
db.Categories.Add(oCategory);
db.SaveChanges();
db.Dispose();
db = null;
}
return RedirectToAction("Categories");
}
I have a pure HTML form inside the Categories View to get user inputs to create a new category and a block that represents the categories that I already have.
I have a Select and several Foreach loops that iterates through categories from parent to children inside my form.
Here is the code:
<select name="parentID" id="parentCategoryId">
<option value="null" selected>nothing</option>
#foreach (var Category in Model) {
if (Category.ParentID == null) {
<option value="#Category.ID">#Category.Name</option>
foreach (var SubCategory1 in Model) {
if (SubCategory1.ParentID == Category.ID) {
<option value="#SubCategory1.ID">
»
#SubCategory1.Name
</option>
foreach (var SubCategory2 in Model) {
if (SubCategory2.ParentID == SubCategory1.ID) {
<option value="#SubCategory2.ID">
»
#SubCategory2.Name
</option>
foreach (var SubCategory3 in Model) {
if (SubCategory3.ParentID == SubCategory2.ID) {
<option value="#SubCategory3.ID">
»
#SubCategory3.Name
</option>
}
}
}
}
}
}
}
}
</select>
Inside the view I get the data from Model using :
#model IEnumerable<project.Models.Category>
But I need another Model object to use here:
#Html.ValidationMessageFor(model => model.Title, "", new { #class = "text-danger" })
and validation operation!
The question is how can I combine these two views?
And now I’m stuck with this error:
Validation failed for one or more entities. See 'EntityValidationErrors' property for more details.
You need create model:
public class CategoryModel {
public string Name {get;set;}
public string Address {get;set;}
pubic string ParentId {get;set;}
public IEnumerable<Category> Categories {get;set;}
}
In your Controller:
public ActionResult Categories() {
var model = new CategoryModel();
model.Categories = db.Categories.OrderBy(Categories => Categories.Name).ToList();
return View(model);
}
[HttpPost]
public RedirectToRouteResult NewCategory(CategoryModel model) {
if (ModelState.IsValid) {
int? ParentID = null;
if (model.ParentId != "null") {
ParentID = model.ParentId.AsInt();
}
Category oCategory = new Category();
oCategory.Name = Model.Name;
oCategory.Address = Model.Address;
oCategory.ParentID = ParentID;
db.Categories.Add(oCategory);
db.SaveChanges();
db.Dispose();
db = null;
}
return RedirectToAction("Categories");
}
and in the view:
#model project.Models.CategoryModel
now you can create fields like in the same view:
#Html.EditorFor(Model=>model.Title)
#Html.ValidationMessageFor(model => model.Title, "", new { #class = "text-danger" })

How do I get a strongly typed DropDownList to bind to a control Action

I've just started a new MVC project and I'm having trouble getting the post result from a form.
This is my Model Class :
public class User
{
public int id { get; set; }
public string name { get; set; }
}
public class TestModel
{
public List<User> users { get; set; }
public User user { get; set; }
public SelectList listSelection { get; set; }
public TestModel()
{
users = new List<User>()
{
new User() {id = 0, name = "Steven"},
new User() {id = 1, name = "Ian"},
new User() {id = 2, name = "Rich"}
};
listSelection = new SelectList(users, "name", "name");
}
}
This is my view class
#model MvcTestApplicaiton.Models.TestModel
#{
ViewBag.Title = "Index";
}
<h2>Index</h2>
#using (Html.BeginForm())
{
#Html.DropDownListFor(x => x.user, #Model.listSelection)
<p>
<input type="submit" value="Submit" />
</p>
}
#if (#Model.user != null)
{
<p>#Model.user.name</p>
}
And this is my controller :
public class TestModelController : Controller
{
public TestModel model;
//
// GET: /TestModel/
public ActionResult Index()
{
if(model ==null)
model = new TestModel();
return View(model);
}
[HttpPost]
public ActionResult Test(TestModel test)
{
model.user = test.user;
return RedirectToAction("index", "TestModel");
}
}
The drop down list appears just fine but I can't see to get the ActionResult Test function to run. I thought it would just bind itself with reflection but whatever is wrong, I can't see it.
You have two main errors in your code.
As Brett said you're posting to the Index method, but you don't have Index method that supports POST verb. The easiest way to fix is to change Html.BeginForm() with Html.BeginForm("Test", "TestModel")
You're using Html.DropDownListFor in a wrong way. You could pass only a value types there, because don't forget that the View will generate an HTML page. So instead of User in your Model you should have an UserID and in your View you should have #Html.DropDownListFor(x => x.UserID, #Model.listSelection). And finally in your Action you should query your data source to get the details for the user with this ID.
Hope this helps.
Looks like you're posting back to index. Either use a GET Test() action method, or specify the ACTION parameter in BeginForm().
For example,
#using (Html.BeginForm("Test", "TestModel"))
{
#Html.DropDownListFor(x => x.user, #Model.listSelection)
<p>
<input type="submit" value="Submit" />
</p>
}
Or use a view named Test (rename index.cshtml to test.cshtml):
public ActionResult Test()
{
if(model ==null)
model = new TestModel();
return View(model);
}

MVC display foreign key from another table

Controller:
public ActionResult Details(int id)
{
ViewBag.AccountType = new BusinessLayer.AccountTypeManager().GetAccountTypes();
return View(new BusinessLayer.AccountManager().getAccount(id));
}
View:
<div class="display-label">Account Type</div>
<div class="display-field">#Html.DisplayFor(modelItem => modelItem.AccountType)</div><br />
This current view displays the AccountType ID. How can I display the AccountType Name which is being passed by the ViewBag.AccountType (IEnumerable)
something like following
<div class="display-label">Account Type</div>
<div class="display-field">#Html.DisplayFor(modelItem => modelItem.AccountType)</div>
#{
var TypeNames = ViewBag.AccountType as IEnumerable<string>;
foreach(var item in TypeNames)
{
<div>item</div>
}
}
Mode elegant way
public class AccountTypeVewModel
{
public IEnumerable<string> typeNames { get; set; }
public Account account { get; set; }
}
controller
public ActionResult Details(int id)
{
AccountTypeVewModel model = new AccountTypeVewModel();
model.typeNames = new BusinessLayer.AccountTypeManager().GetAccountTypes();
model.account = new BusinessLayer.AccountManager().getAccount(id);
return View(model);
}
view
<div class="display-label">Account Type</div>
<div class="display-field">#Html.DisplayFor(modelItem => modelItem.account.AccountType)</div>
#{
foreach(var item in Model.typeNames)
{
<div>item</div>
}
}

MVC trying to pass model from razor view to controller

So my story is that I am having trouble with the post to the controller, the view seems to work fine. When the postback happens the tm.BookId is 0 (should be 1) and the list count is 0. First I will display the model:
public class TransferModel
{
public TransferModel()
{
cbItems = new List<CheckBoxItem>();
}
public List<CheckBoxItem> cbItems {get;set;}
public int BookId;
public class CheckBoxItem
{
public int AttributeId { get; set; }
public string Attribute { get; set; }
public bool Selected { get; set; }
}
}
The Controller part:
public ActionResult AddAttributes(int id = 0)
{
db.transMod.BookId = id;
BookInfo book = db.BookInfoes.Find(id);
var latts = db.BookAtts.ToList();
foreach (BookAtt ba in latts)
{
db.transMod.cbItems.Add(new TransferModel.CheckBoxItem { Attribute = ba.Attribute, AttributeId = ba.BookAttId, Selected = false });
}
List<BookAtt> atInList = book.BookAtts.ToList();
foreach (TransferModel.CheckBoxItem cb in db.transMod.cbItems)
{
if (atInList.Exists(item => item.Attribute == cb.Attribute))
cb.Selected = true;
}
return View(db.transMod);
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult AddAttributes(TransferModel tm)
{
List<BookAtt> atPool = db.BookAtts.ToList();
BookInfo book = db.BookInfoes.Find(tm.BookId);
foreach (TransferModel.CheckBoxItem sel in tm.cbItems)
{
if (sel.Selected)
book.BookAtts.Add(atPool.Find(item1 => item1.Attribute == sel.Attribute));
}
db.SaveChanges();
return RedirectToAction("AddAttributes");
}`enter code here`
And finally the view:
#model BrightStar.Models.TransferModel
#{
ViewBag.Title = "Update Attributes";
}
<h2>Add Attributes</h2>
#using (Html.BeginForm()) {
#Html.AntiForgeryToken()
<table>
#Html.HiddenFor(model => Model.BookId)
#Html.HiddenFor(model => Model.cbItems)
#foreach (var itm in Model.cbItems)
{
<tr>
<td>#Html.HiddenFor(mo => itm.AttributeId)</td>
<td>#Html.CheckBoxFor(mo => itm.Selected)</td>
<td>#Html.DisplayFor(mo => itm.Attribute)</td>
</tr>
}
</table>
<p>
<input type="submit" value="Save" />
</p>
}
enter code here
Model binding doesn't happen automatically, items needs to be in certain format to get binded to list properties in POST actions. Check this out.
Try checking out the value of BookId property in the DOM to confirm it is 1, otherwise it should bind normally.
You should reference your model's properties in helpers to correctly generate names for your controls:
#Html.HiddenFor(model => Model.cbItems)
should be
#Html.HiddenFor(model => model.cbItems)

how can get data in drop down list from data base in mvc3.?

I am designing a simple webpage using MVC3 in asp.net. I prepared a database using Sql Server, and i have attached this database in App_Data. There is a table employee in that database.
i want to get name of employee in a drop down list. so i can select name of employee.
so please suggest me what will be model,view and controller code for accessing employee name in drop down list.
I would start by designing a view model which will hold the data:
public class EmployeeViewModel
{
public string SelectedEmployeeName { get; set; }
public IEnumerable<SelectListItem> Employees { get; set; }
}
then a controller:
public class HomeController: Controller
{
public ActionResult Index()
{
IEnumerable<Employee> employees = GetEmployeesFromDb();
var model = new EmployeeViewModel
{
Employees = employees.Select(x => new SelectListItem
{
Value = x.Name,
Text = x.Name
})
};
return View(model);
}
[HttpPost]
public ActionResult Index(EmployeeViewModel model)
{
return Content("Selected employee name: " + model.SelectedEmployeeName, "text/plain");
}
}
and finally the strongly typed view:
#model EmployeeViewModel
#using (Html.BeginForm())
{
#Html.DropDownListFor(
x => x.SelectedEmployeeName,
new SelectList(Model.Employees, "Value", "Text")
)
<input type="submit" value="OK" />
}
1) Create a Method to populate the list from DB
2) Set a ViewModel to hold the List and selected value
//MODEL
public List<SelectListItem> CategoriesSelectList()
{
var query = from c in _yourRepository.GetAll()
select c;
List<SelectListItem> obj = new List<SelectListItem>();
foreach (var item in query)
{
var result = new SelectListItem();
result.Text = item.name;
result.Value = item.id.ToString();
obj.Add(result);
}
return obj;
}
//VIEWMODEL
public class ViewModel
{
[DisplayName("Category")]
public int categoryId { get; set; }
public List<SelectListItem> CategoryList()
{
return new Model().CategoriesSelectList();
}
}
//CONTROLLER
public ActionResult Create()
{
//set the id for the VIEWMODEL property, if necesary
var e = new ViewModel();
e.categoryId = 1;//set the selected value
return View(e);
}
//VIEW
<div class="editor-label">
<%: Html.LabelFor(model => model.categoryId) %>
</div>
<div class="editor-field">
<%: Html.DropDownListFor(model => model.categoryId,Model.CategoryList()) %>
<%: Html.ValidationMessageFor(model => model.categoryId) %>
</div>

Resources