MVC 4 Model binding with partial view - c#

#using (Html.BeginForm("PrintDoorSigns", "TimeTable", FormMethod.Post, new { id = "printDoorSigns" }))
{
<input type="hidden" id="doorSignDate" name="SelectedDate" />
<h3>Door Signs</h3>
<fieldset class="float-left">
<legend>Date</legend>
<div id="signsDate"></div>
</fieldset>
<div id="doorSignsRoomList" class="float-left">
#{Html.RenderAction("DoorSignsForm", new { date = DateTime.Now });}
</div>
<div>
<fieldset>
<legend>Options</legend>
<button id="SelectAllRooms">Select All</button>
<button id="RemoveAllRooms">Remove All</button>
</fieldset>
</div>
}
I have this form which renders this partial view:
#model WebUI.ViewModels.CalendarVM.DoorSignsFormVM
<fieldset>
<legend>Rooms</legend>
#{ var htmlListInfo = new HtmlListInfo(HtmlTag.vertical_columns, 3, null, TextLayout.Default, TemplateIsUsed.No);
if (Model.Rooms.Count() > 0)
{
<div id="roomsWithBookings" class="CheckBoxList float-left">
#Html.CheckBoxList("SelectedRooms", model => model.Rooms, entity => entity.Value, entity => entity.Text, model => model.SelectedRooms, htmlListInfo)
</div>
}
}
</fieldset>
Controller action:
public ActionResult PrintDoorSigns(DateTime SelectedDate, DoorSignsFormVM Model)
when I submit the form, the hidden input "SelectedDate" gets passed back fine and the Model variable which contains two IEnumerable variables isn't null. One of the lists is null which I expect, as it shouldn't be passed back and the SelectedRooms variable which I expect to be populated is a new list with count 0.
I assume the binding is just wrong on this property but I don't understand why, any pointers? Thanks
EDIT:
public PartialViewResult DoorSignsForm(DateTime date)
{
var userID = _bookingService.GetCurrentUser(User.Identity.Name);
var model = new DoorSignsFormVM();
model.Rooms = _sharedService.GetRoomsWithBookings(date, userID.FirstOrDefault().DefSite);
return PartialView("_DoorSigns", model);
}
Here is the doorsignsform action that gets rendered in the form.

As you say, ASP.NET MVC is not recognizing the checkbox values as being part of the DoorSignsFormVM view model.
Given that your SelectedRooms property is a collection of SelectListItems, MVC is not recognizing how to bind the string values from the checkboxes to this property.
Try adding another property called SelectedRoomValues of type string[] to your viewmodel and change your checkbox code to
#Html.CheckBoxListFor(model => model.SelectedRoomValues, model => model.Rooms, entity => entity.Value, entity => entity.Text, model => model.SelectedRooms, htmlListInfo)
MVC will then know how to bind to this new property, which will be populated with the SelectListItem.Value values.

Related

How to pass an ID parameter on an action link based on a dropdown list selection in ASP.NET MVC C#

I cant seem to figure this out. I have a view page that's for adding a product to an order. There's a dropdown list where you select the product you want to add. Once you select a product, I have an onchange function that basically inserts the value of the Product ID into a hidden input field. Where I'm stuck is I have an action link that goes to a different controller and a different model so I can't just use the Model.ProductID when I use the id parameter. Is there a way to get the value of the input field that is essentially the ProductID value from the product selected and use that as the id parameter on the actionlink? The actionlink opens a product view that shows a pic of the product and the qty in stock. but when I click on the link, its not getting the id value of the product selected.
Here is the relevant part of my view page:
<div class="form-group">
<label class="lbl3">Product:</label><span class="required"> *</span><label class="ddl1">#Html.DropDownListFor(model => model.ProductID, ViewBag.ProductID as SelectList, "--Select a Product--", new { #class = "form-control prod-ctl", #onChange = "selectedText(this)" })</label>
<input type="hidden" id="txt" name="poProduct" required />
<label class="lbl2">Qty Ordered:</label><span class="required"> *</span><input type="text" inputmode="numeric" class="col-md-3 form-control qty-ctl" name="poQtyOrdered" id="poQtyOrdered" required />
<label class="chk-link"><a class='prod-modal chk-stock' href="#Url.Action("AmtInStock", "Products", new { id = "THIS IS WHERE IM STUCK" })"><span class="fa solid fa-search"> <u>Check Stock</u></span></a></label>
<script>
function selectedText(ddlitem) {
var selvalue = ddlitem.value;
var seltext = ddlitem.options[ddlitem.selectedIndex].innerHTML;
$('#txt').val(selvalue);
}
</script>
Here is my controller for the actionlink:
public ActionResult AmtInStock(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
var product = db.Products.Find(id);
if (product == null)
{
return HttpNotFound();
}
return PartialView("AmtInStock", product);
}
and lastly, here is the ddl code in controller for the main page:
ViewBag.ProductID = new SelectList(db.Products, "ProductID", "Product_Code");
So I need to be able to select a product in the dropdown list and if I click on the actionlink, I need to be able to get the value of that selected item to pass in the id parameter.
Thanks,
Kip M.

Unable to submit List of model in MVC [duplicate]

This question already has answers here:
Post an HTML Table to ADO.NET DataTable
(2 answers)
Closed 7 years ago.
I am displaying a list of items in a Collection in edit mode in a view. after editing the documents, I want to submit. But I am unable to postback the list. List shows null.
here is my View
#model List<NewsLetter.Models.NewsLetterQuestions>
#using (Html.BeginForm("GetAnswersfromUser", "NewsLetter", FormMethod.Post, null))
{
#Html.AntiForgeryToken()
foreach (var item in Model) {
<div>
#Html.DisplayFor(modelItem => item.Question)
</div>
<div>
#Html.TextAreaFor(modelItem => item.Answer)
</div>
}
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Submit" class="btn btn-default" />
</div>
</div>
}
Here is my Controller
public ActionResult GetAnswersfromUser(string id)
{
id = "56c5afc9afb23c2df08dd2bf";
List<NewsLetterQuestions> questions = new List<NewsLetterQuestions>();
var ques = context.NewsLetterQuestionCollection.Find(Query.EQ("NewsLetterId", id));
foreach(var x in ques)
{
questions.Add(x);
}
return PartialView(questions);
}
[HttpPost]
public ActionResult GetAnswersfromUser(List<NewsLetterQuestions> nql)
{
string id = "56c5afc9afb23c2df08dd2bf";
foreach (var item in nql)
{
var query = Query.And(Query.EQ("NewsLetterId", id), Query.EQ("Question", item.Question));
var update=Update<NewsLetterQuestions>
.Set(r => r.Answer, item.Answer);
context.NewsLetterQuestionCollection.Update(query,update);
}
return RedirectToAction("NewsLetterIndex");
}
When i hit submit it throws error.
System.NullReferenceException: Object reference not set to an instance of an object.
In the line
foreach (var item in nql)
which means that nql is null.
In order for the model binder to be able to bind the posted data, all your input names need to be in the format of [N].Property, where N is the index of the item within the list. In order for Razor to generate the input names properly, then, you need to pass it an indexed item, which means you need a for loop, rather than a foreach:
#for (var i = 0; i < Model.Count(); i++)
{
...
#Html.TextAreaFor(m => m[i].Answer)
...
}
You're never passing the list back to the controller's Post handler. You need to route the list back to the controller.
You should be doing something similar to this untested code :)
Html.BeginForm("Index", "Home", new { #nql=Model }, FormMethod.Post)
Take a look at this post as well. It is similar to your issue: Pass multiple parameters in Html.BeginForm MVC4 controller action and this Pass multiple parameters in Html.BeginForm MVC

MVC (Razor) Filter DropDownList

I'm new to MVC and JavaScript and I have a question about DropDownList.
I Build a program of "Car Renting" and I have a View that allow adding new Car to the inventory.
The view include 2 dropdownlists (see below):
<div class="editor-field">
#Html.DropDownList("ManufacturerId", string.Empty)
#Html.ValidationMessageFor(model => model.ManufacturerId)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.ModelId)
</div>
<div class="editor-field">
#Html.DropDownList("ModelId", string.Empty)
#Html.ValidationMessageFor(model => model.ModelId)
</div>
I want that when user select a manufacturer for example (Alfa Romeo) the "model" list box will display only "Alfa Mito" models and not the full list...
My Controller function send to the view the Model List using ViewBag see below:
public ActionResult AddNewCar()
{
ViewBag.ManufacturerId = new SelectList(db.Manufacturers, "ManufacturerId", "ManufacturerName");
ViewBag.ModelId = new SelectList(db.Models, "ModelId", "ModelName");
ViewBag.BranchId = new SelectList(db.Branchs, "BranchId", "BranchName");
return View();
}
Please advice.
Thanks,
Almog
call below action method from jquery on dropdown change event.
public List<carmodels> PopulateState(int manufacturerId)
{
var carmodelsObj = (from st in dc.Carmodels
where st.manufacturerId.Equals(manufacturerId)
select st).ToList();
return (carmodelsObj);
}
You need to repopulate/populate your ModelId dropdown on every time when your first dropdown changes (using jquery). Do following:
Get the ManufactureId from first dropdown on change event. and place an ajax call to repopulate your second dropdown.
$("#ManufactureId").change(function() {
var manufacturerId = manufacturer$('#ManufacturerId').val();
$.ajax({url: "~/Car/GetCarsByManufacturer", success: function(result){
//re populate your second dropdown here
//hint: you may use response.id for value
}});
});
Create a function in your controller that returns Car Models, based on selected. (call this function in previous step using ajax).
public List<carmodels> GetCarsByManufacturer(int manufacturerId)
{
var carmodelsObj = (from st in dc.Carmodels
where st.manufacturerId.Equals(manufacturerId)
select st).ToList();
return (carmodelsObj);
}

How to pass the text/Value of an Html element from view to controller

I want to access the value of button in controller and then pass it to the view as well.
But the value of "str" passed from view to controller is null.
Index.chtml
#{
var str = "Shoes";
}
<a href="~/Home/Products_By_Category/#str" target="_parent">
<input type="button" value="Shoes" class="btn"/>
</a>
/////////////////////////
<pre lang="c#">
public ActionResult Products_By_Category(string s)
{
ViewBag.category = s;
return View();
}
Have the same name s for your input also.
Use ViewBag.category in the client side. Since ViewBag is a dynamic entity.
Are you using form submit in which case MVC will automatically fill the value of the input for you.
Now I'm using
Index.cshtml
#{
var str="Shoes";
}
<form action="~/Home/Products_By_Category/#str" method="post">
<input type="submit" value="Shoes" class="btn"/>
</form>
/////////////
public ActionResult Products_By_Category(string s)
{
var context = new Shoe_StoreDBEntities();
var q = from p in context.Products
join c in context.Categories on p.CategoryId equals c.Id
where c.Name.Equals(s)
select new { p, c };
}
but still the value in "s" is still null
First. The controller passes data to the view. There is no other way around. It's because the basic nature of a webapplication.
Basically: Request -> controller -> select and render a view.
The view itself is not a known concept in the client browser. That is simple html/css/js.
Your view should looks like this:
#{
var str = "Shoes";
}
#using (Html.BeginForm("Products_By_Category"))
{
<input type="submit" name="s" id="s" value="#(str)"/>
}
Some note:
1) If you use a variable inside an html element attribute you have to bracket it.
2) You should use the builtin html helper whenever it's possible (beginform)
3) This example only work if you click the submit button to postback the data. If there is other submit button or initiate the postback from js, the button data is not included into the formdata. You should use a hidden field to store the str value and not dependent from the label of the button:
#{
var str = "Shoes";
}
#using (Html.BeginForm("Products_By_Category"))
{
<input type="hidden" id="s" name="s" value="#(str)"/>
<input type="submit" value="Do postback"/>
}

How to save values in a list in ASP MVC 3

I am developing an ASP .Net MVC 3 application using C# and SQL Server 2005.
I am using also Entity Framework and Code First Method.
I have a Form in a Partial View which the code is :
<%# Language="C#" Inherits="System.Web.Mvc.ViewUserControl<MvcApplication2.Models.FlowViewModel>" %>
<% using (Html.BeginForm("Save", "ProfileGa")) { %>
<%: Html.ValidationSummary(true) %>
<fieldset class="parametrage">
<legend>Gestion de Gamme</legend>
<div>
<%:Html.Label("Poste :")%><%: Html.DropDownListFor(model => model.SelectedPoste, Model.PostesItems)%>
</div>
<div>
<%:Html.Label("Nombre de Passage :")%><%: Html.EditorFor(model=>model.Nbr_Passage)%>
</div>
<div class="editor-field">
<%: Html.ValidationMessageFor(model => model.Nbr_Passage)%>
</div>
<div>
<%:Html.Label("Position :")%><%: Html.EditorFor(model=>model.Position)%>
</div>
<div>
<%:Html.Label("Poste Suivant :")%><%: Html.DropDownListFor(model => model.PosteSuivantSelected, Model.PostesItems, new { #id = "dd" })%>
</div>
<div>
<input type="submit" value="Enregistrer" id="btnSave" />
</div>
</fieldset>
and this is how it looks :
I want to save the values entred in a List. So I created a list in my view model like this :
public List<Gamme> ListG = new List<Gamme>();
Then in my Controller 'ProfileGaController', I defined a method save to save in the list :
[HttpPost]
public ActionResult Save(FlowViewModel model)
{
if (ModelState.IsValid)
{
Gamme G = new Gamme();
G.ID_Gamme = model.SelectedProfile_Ga;
G.ID_Poste = model.SelectedPoste;
G.Next_Posts = model.PosteSuivantSelected;
G.Nbr_Passage = int.Parse(model.Nbr_Passage);
G.Position = int.Parse(model.Position);
model.ListG.Add(G);
}
return RedirectToAction("Index");
}
Problem :
Each time I a save in the list, th values are deleted and replaced by new ones.
Always, I have count=1 for the list :
I'm not sure why you need this list at all. The Model only exists for the duration of this controller action, and you're not passing it on to the view. In your code, you're making a new Gamme, adding it to a list, and then throwing the whole thing away. If you're just trying to save a new Gamme in the database, does it not work if you do
db.Gammes.Add(G);
db.SaveChanges();
instead of
model.ListG.Add(G);
What's the purpose of the list?
Edited after further clarification:
It seems like you want a temporary list of Gamme items added in one session, so you can use a session variable to store a list of Gammes you've added at that time. Initialise in the controller and add in the save action like so:
((List<Gamme>)System.Web.HttpContext.Current.Session["GammeList"]).Add(G);
Then if you want to assign it to a parameter of the View Model it's like:
model.ListG = (List<Gamme>)System.Web.HttpContext.Current.Session["GammeList"];
I, personally, would go back and engineer this slightly differently. I would put a bool on Gamme called "processed" or something similar, and when you create them, set it to false. That way, instead of using a session variable list, you can get the same list by selecting all Gamme objects where processed is false.
You will always have 1 in the list, because you are creating a new instance of ListG with new List(); So when this is passed back to the controller, it will be newed up and you will add your new G object resulting in a count of 1. Alternatively you could try this: (assuming your db instance is locally accessible)
[HttpPost]
public ActionResult Save(FlowViewModel model)
{
if (ModelState.IsValid)
{
Gamme G = new Gamme();
G.ID_Gamme = model.SelectedProfile_Ga;
G.ID_Poste = model.SelectedPoste;
G.Next_Posts = model.PosteSuivantSelected;
G.Nbr_Passage = int.Parse(model.Nbr_Passage);
G.Position = int.Parse(model.Position);
model.ListG = db.Gammes.ToList();
model.ListG.Add(G);
db.SaveChanges();
}
return RedirectToAction("Index");
}

Categories

Resources