MVC foreach set item.ID to model.ID - asp.net-mvc

I have a form that shows all the available hotel rooms, each room has a button that does a HttpPost if clicked, I have made a property in the BookingViewModel called 'RoomID'. I would like to assign the item.RoomID to Model.RoomID so I can use it in my controller to get the id from the selected room but i'm not sure how to achieve this.
ChooseRoom View
#foreach (var item in Model.AvailableRooms)
{
<li class="room-item clearfix">
<h5>#item.Name</h5>
<div class="room-list-left">
<img src="#item.Image" alt="" />
</div>
<div class="room-list-right">
<div class="room-meta">
<ul>
<li><span>Occupancy:</span> #item.Adults Adults #item.Childs Children</li>
#if (item.SmokingRoom)
{
<li><span>Smoking Allowed:</span> Yes</li>
}
else
{
<li><span>Smoking Allowed:</span> No</li>
}
</ul>
</div>
<div class="room-price">
<p class="price">From: <span>$#item.Price</span> / Night</p>
</div>
<div class="clearboth"></div>
#using (Html.BeginForm("chooseroom", "booking", FormMethod.Post))
{
<input class="button2" type="submit" value="Select Room" />
}
BookingController
[HttpPost]
public ActionResult ChooseRoom(BookingViewModel vm)
{
BookingViewModel bookingObj = GetBooking();
bookingObj.SelectedRoom = Repository.GetRoomByID(vm.RoomID);
return View("reservation", bookingObj);
}
Thank you for your time!

update your begin form as below
#using (Html.BeginForm("chooseroom", "booking", FormMethod.Post))
{
<input type="hidden" name="RoomId" value="#item.RoomID" />
<input class="button2" type="submit" value="Select Room" />
}
Just need to provide input tags having the same name as your ViewModel property.

You could add inputs in foreach loop , it should be inside form. Something like this <input name="Model.AvailableRooms[index].RoomID" value="Id Here"/>
Or if you want to select one Room you should use ajax and post id.
If I'm not wrong you form is in loop,so you could add hidden input with id
#Html.HiddenFor(c => c.AvailableRooms[index].RoomID)

Related

Edit action in controller not updating

When I edit an item and return to the index view the item doesn't show what I updated it to.
I think I know what the problem is but not sure how to fix it. In my service class I have a CreateEditItem method and when I step thru the code it hits the if condition <=0. So it acts like there is an id of 0 when I click the submit button to submit my update. I'm not sure what to do to fix this. Do I need to have a separate method for Edit? And if so what should that look like?
public bool CreateEditItem(Item item)
{
if (item.ItemId <= 0)
{
var maxId = _mockList.Max(p => p.ItemId);
item.ItemId = maxId + 1;
_mockList.Add(item);
return true;
}
var itemToEdit = _mockList.FirstOrDefault(p => p.ItemId ==
item.ItemId);
itemToEdit = item;
return true;
}
Action in Controller
[HttpPost]
public IActionResult EditItem(Item itemToEdit)
{
_itemService.CreateEditItem(itemToEdit);
return RedirectToAction(nameof(Index), new { id =
itemToEdit.ItemId });
}
View:
<div class="row">
<form asp-action="EditItem">
<div asp-validation-summary="ModelOnly" class="text-
danger"></div>
<div class="container form-group">
<div class="row">
<div class="col-md-2">As Of : <label
for="AsOf" /></div>
<div class="col-md-4"><input id="AsOf"
value="#Model.ItemToEdit.AsOf" name="AsOf" type="date" /></div>
</div>
<br />
<div class="row">
<div class="col-md-2">Title Summary : <label
for="TitleSummary" /></div>
<div class="col-md-2"><input id="TitleSummary"
value="#Model.ItemToEdit.Title" name="Title" type="text" /></div>
</div>
<br />
<br />
<div class="row">
<div class="col-md-2"><input type="submit"
value="Submit" class="btn btn-primary" /></div>
</div>
</div>
</form>
</div>
I expect when I click the submit button to submit my update it will show the updated Title and/or AsOf date.
change your method from HTTPut to HttpPost
it will work.

Data not populating in form upon clicking edit

I am working on this ASP.NET MVC project where I am performing simple CRUD operations. On clicking Edit button, I want to get the data from the database and populate it in the Create View (same view with the help of which I entered the data).
The issue that I have is that, though I am able to enter the data into the database using the Create.cshtml view, I am not able to populate the data back into the fields to the same View upon clicking Edit. On checking, I see that I am able to get the data from the database from the Controller and I am sending it to the View - Create. But, the fields are not getting populated in the View.
Where am I going wrong?
View - Create.cshtml
<form method="post" action="/Books/Create" id="formBooks">
<div class="form-group">
<div class="form-row">
<div class="form-group col-md-6">
<div>
<label asp-for="Title" class="label">Title</label>
<input asp-for="Title" class="form-control" id="title" name="title" required />
<span asp-validation-for="Title" class="text-danger"></span>
</div>
<div>
<label asp-for="Author" class="label">Author</label>
<input asp-for="Author" class="form-control" id="author" name="author" required />
<span asp-validation-for="Author" class="text-danger"></span>
</div>
...
</div>
<div class="form-group col-md-6">
<button type="submit" value="Save" class="btn bgm-orange waves-effect mybtn">SAVE</button>
</div>
</div>
</div>
</form>
Controller - BooksController.cs
public ActionResult Create(int? Id)
{
if(Id == null)
{
return View();
}
else
{
var bookData = _context.Books
.Where(b => b.ID == Id)
.FirstOrDefault();
return View(bookData);
}
}
public ActionResult Create(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Books books= db.Books.Find(id);
if (books== null)
{
return HttpNotFound();
}
return View(books);
}
//Try this i hope this will work
The name attribute plays a vital role in binding the data to the <input></input> field. Also, value attribute gets the value to display in the Edit view.
<input asp-for="Title" class="form-control" id="title" name="title" placeholder="Enter title..." value="#(Model != null ? Model.Title : "")" required />

MVC Razor, How to keep Model object between Actions

I'm trying to display a product stock list.
I would like to let the user an option to edit the quantity's and the ability to remove a product from this list. the problem is, the Model object disappear after the submit action. i would like to preserve it, in order to update the stock in DB later on.
Controllers:
public ActionResult EditProducts()
{
//! Pulling DATA from db using DbContext
ProductDAL proDAL = new ProductDAL();
List<Products> pl = proDAL.Products.ToList<Products>();
ProductModel productModel = new ProductModel();
productModel.oneProduct = new Products();
productModel.ProductsCollection = new List<Products>();
productModel.ProductsCollection = pl;
TempData["pM"] = productModel;
return View("EditProducts", TempData["pM"]);
}
public ActionResult SubmitProductsValues(ProductModel productModel)
{
//! Some farther work to do...
return View("EditProducts", TempData["pM"]);
}
My View:
#using (Html.BeginForm("SubmitProductsValues", "Admin", FormMethod.Post))
{
<div class="col-xs-12 hclearfix edit">
<div class="col-xs-2 eRow et"><b>Product SKU</b></div>
<div class="col-xs-2 eRow et"><b>Product Name</b></div>
<div class="col-xs-2 eRow et"><b>Product Price</b></div>
<div class="col-xs-2 eRow et"><b>Product Quantity</b></div>
<div class="col-xs-2 eRow et"><b>Product Picture</b></div>
<div class="col-xs-1 eRow et"><b>pId</b></div>
<div class="col-xs-1 eRow et"><b>Remove?</b></div>
#{ int i = 0; }
#foreach (Products obj in Model.ProductsCollection)
{
<div class="col-xs-2 eRow">#Html.Raw(obj.SKU)</div>
<div class="col-xs-2 eRow">#Html.Raw(obj.Name)</div>
<div class="col-xs-2 eRow">#Html.Raw(obj.Price)</div>
<div class="col-xs-2 eRow">#Html.EditorFor(m=>m.ProductsCollection[i].Quantity)</div>
<div class="col-xs-2 eRow">#Html.Raw(obj.PicURL)</div>
<div class="col-xs-1 eRow">#Html.Raw(obj.Id)</div>
<div class="col-xs-1 eRow">#Html.CheckBox("remove")</div>
i++;
}
<div class="col-xs-12 eRow">
<p class="left">
<input type="submit" id="btnSubmit" value="Save Changes" />
</p>
<p class="alert-danger right">
#Html.ValidationSummary()
</p>
</div>
</div>
BTW, only this raw: #Html.EditorFor keeps the values of the returned data.
but i would like to avoid using #Html.EditorFor for the other fields, while
keeping those fields data.
Thank you so much for your help (:
You are getting null because the other field values are not in the form fields. Model binding will map the data from your form fields ( with names matching to your view model property name). Currently you are displaying Name, Price etc in just a div, not an input field.
But since you do not want to update any other fields, you should not worry about getting other field value as null. What you need is the unique Id of your record and the Quantity field value which has the updated value from form.
Als you do not need TempData. You can pass your model to the View method.
public ActionResult EditProducts()
{
var proDAL = new ProductDAL();
List<Products> pl = proDAL.Products.ToList<Products>();
ProductModel productModel = new ProductModel();
productModel.ProductsCollection = new List<Products>();
productModel.ProductsCollection = pl;
return View("EditProducts",productModel);
}
And in your view, you need to create input fields with names which matches the property name so that model binding will work when you post the form.
#model ProductModel
#using (Html.BeginForm("SubmitProductsValues", "Admin", FormMethod.Post))
{
<h2>Items</h2>
int i = 0;
foreach(var p in Model.Products)
{
<div>#p.Name</div>
<input type="hidden" name="ProductsCollection[#i].Id" value="#p.Id" />
<input type="text" name="ProductsCollection[#i].Quantity" value="#p.Quantity" />
}
<input type="submit" value="Update" />
}
Now in your HttpPost, you will have the ProductsCollection available withe updated data from the form user submitted.
[HttpPost]
public ActionResult SubmitProductsValues(ProductModel model)
{
// loop through model.ProductsCollection
foreach(var p in Model.ProductsCollection)
{
var q=p.Quantity;
var id=q.Id;
// to do : update quantity of the record for the value in Id variable.
}
// to do : Save and redirect
}
<input type="hidden" name="ProductsCollection[#i].SKU" value="#p.SKU" />
<input type="hidden" name="ProductsCollection[#i].Name" value="#p.Name" />
<input type="hidden" name="ProductsCollection[#i].Price" value="#p.Price" />
<input type="hidden" name="ProductsCollection[#i].PicURL" value="#p.PicURL" />
<input type="hidden" name="ProductsCollection[#i].Id" value="#p.Id" />
Thanks to #Shyju (:

Form action not hitting MVC controller method

I want to do a simple file upload using Html forms. I have the following in my view:
<form action='#Url.Action("Save", "Order")' method="post" enctype="multipart/form-data" id="attachmentForm">
<div >
<label style="text-align: left;">Delivery note:</label>
</div>
<div style="float:left; ">
<input type="file" name="DeliveryNoteFile" id="DeliveryNote" style="width: 400px;" />
</div>
<div style="float:right; margin-top:10px; margin-left:5px; margin-bottom:0px;">
#(Html.Kendo().Button()
.Name("btnAddAttachment")
.HtmlAttributes( new {type = "submit"} )
.Content("Submit"))
</div>
</form>
Now here is my controller method. Controller name: Order , Method name: Save.
Why is it not hitting my controller method?
[HttpPost]
public ActionResult Save(HttpPostedFileBase file)
{
if (file != null)
{
var fileName = Path.GetFileName(file.FileName);
var physicalPath = Path.Combine(Server.MapPath("C:\\Attachments"), fileName);
file.SaveAs(physicalPath);
}
return Content("");
}
Note that this is only a first draft. Any suggestions to improve this are also welcome.
I think in your case your button is not of type submit that is why it is not hitting controller action just try making submit button this way:
#(Html.Kendo().Button()
.Name("btnAddAttachment")
.HtmlAttributes( new {type = "submit"} )
.Content("Submit"))
as # AbbasGaliyakot comment worked for the user in comment section so i m also including it here.
Change controller action parameter name from file to DeliveryNoteFile.
Please try this out. This would help.
#using (Html.BeginForm("Save", "Order", FormMethod.Post, new { enctype = "multipart/form-data", id = "attachmentForm" }))
{
<div >
<label style="text-align: left;">Delivery note:</label>
</div>
<div style="float:left; ">
<input type="file" name="DeliveryNoteFile" id="DeliveryNote" style="width: 400px;" />
</div>
<div style="float:right; margin-top:10px; margin-left:5px; margin-bottom:0px;">
#(Html.Kendo().Button()
.Name("btnAddAttachment")
.HtmlAttributes( new {type = "submit"} )
.Content("Submit"))
</div>
}
And in JS you need to bind the click function of your submit button like shown below:
$('#btnAddAttachment').bind('click', function () {
$('#attachmentForm').submit();
});
Thanks!

Validation multiple checkbox form

in the page I have only three checkbox, the client should choose at least one before clicking on the submit button :
Controller :
[HttpPost]
public ActionResult Client(OrderItems model)
{
if (bValidated){
//Code here
}
else
{
model.itemChoosed = false;
return View("Client", model);
}
View Client :
#model WebApp.Models.OrderItems
#using (Html.BeginForm("Client", "Home", FormMethod.Post, new { #class = "form-group", role = "form" }))
{
#Html.AntiForgeryToken();
<h2>Client</h2>
#Html.Partial("SentMessage")
<div>
<div>
<h3>Item 1</h3>
<label>#Html.CheckBoxFor(model => model.CLInfo.Item1) Item 1</label>
</div>
<div>
<h3>Item 2</h3>
<label>#Html.CheckBoxFor(model => model.CLInfo.Item2) Item 2</label>
</div>
<div>
<h3>Item 3</h3>
<label>#Html.CheckBoxFor(model => model.CLInfo.Item3) Item 3</label>
</div>
</div>
<div class="row">
<input type="submit" name="action:Client" id="btnClient" class="btn btn-primary flat btn-large pull-right" value="Client" />
</div>
}
After I choose to put the condition into a Partail View :
Partial View SentMessage:
#model WebApp.Models.OrderItems
#if (!model.itemChoosed)
{
<div>You must choose at least one item</div>
}
I have the error message :
The view 'Client' or its master was not found or no view engine supports the searched locations. The following locations were searched:
~/Views/Home/Client.aspx
..
~/Views/Home/Client.cshtml
..
but Home/Client.cshtml existe since it's the view
Thanks

Resources