Submit MVC ListBoxFor values to controller - asp.net-mvc

I have a multiselect ListBoxFor control as shown in mvc view
#using ExampleViewModel
#using (Html.BeginForm("SaveExample", "Example", FormMethod.Post, new { #id
= "exampleForm" }))
{
#Html.ListBoxFor(x => x.AssignedContainers, new
MultiSelectList(Model.RegisteredContainers, "ID", "Description", null),
new { #class = "fieldNoFocusRequiredListBox", #size = 15,
id="RegisteredContainers" })
}
View model code looks like this:
public class ExampleViewModel
{
public int[] AssignedContainers { get; set; }
public List<Container_Sizes> RegisteredContainers { get; set; }
}
Controller code:
public ActionResult SaveExample(ExampleViewModel model)
{
// code
return Json(true, JsonRequestBehavior.AllowGet);
}
I was able to bind the listbox with model property RegisteredContainers. I do some some jQuery validation and then submit the form via ajax like this:
function SaveProduct() {
if (!ValidateProductForm()) {
return;
}
$.ajax({
type: "POST",
data: $('#exampleForm').serialize(),
url: '/Example/SaveExample/',
success: function (result) {
},
error: function (jqXhr, error, errorThrown) {
}
});
}
When the break point hits the controller ExampleViewModel -> AssignedContainers is null. Please note that i used ICollection/IEnumerable/List for this property AssignedContainers but no luck. Also when i see $('#exampleForm').serialize() in debugger watch i see ".....&AssignedContainers=17" as there is one item in the list box but received null on controller.
Do i need any updates to model binder or what is going wrong here?

Related

MVC:Why my view didn't change when I changed the model and return view(model)?

My model is called Student which has three properties:Id,Name,score. In my view I use model binding,and in my action I search student and return student information, but even I use ModelState.Clear() it looks like this code does not work,the view always show the student which id=0.
Model:
public class Student
{
public int Id{get;set;}
public string Name{get;set;}
public int Score{get;set;}
}
View:
#project.bll.Student
#Html.TextBoxFor(model=>model.Name)
#Html.TextBoxFor(model=>model.Score)
$.ajax({
url: "#Url.Action("GetStudent","Student")",
type: "post",
data: { "id": $("#Id").val() },//id is set to be 0 or 1 or 2
success: function (result) {
alert(result);
}});
Controller:
public ActionResult GetStudent(int id=0)
{
//ModelState.Clear();
return View(StudnetRepository.GetStudentById(id));
}
If you want to use a Model in your View, you must use the keywork #model at the start
so your View must be
#model YourNamespace.Student
#Html.TextBoxFor(model=>model.Name)
#Html.TextBoxFor(model=>model.Score)
<script>
$.ajax({
url: "#Url.Action("GetStudent","Student")",
type: "post",
data: { "id": $("#Id").val() },//id is set to be 0 or 1 or 2
success: function (result) {
alert(result);
}});
</script>
than controller must instantiate the model
public ActionResult GetStudent(int id=0)
{
var model = new Student();
//get the student with repository
//valorize the studend with model.Id, name etc
return View(model);
}

Html.ActionLink does not pass my id

In my view I have a ActionLink that passes an Id to another View. I used this multiple times but for some reason it does not work on this ActionLink. I even tried with a AJAX POST call in javascript but with no success either. Am I doing something wrong? If so, I am not seeing what.
Controller:
The parameter Id in this function is 0 and should be filled.
public ActionResult NieuwPriveBericht(int Id)
{
TblPER_Personeelslid Sender = BCL.GetEmployeeByLoginName(Session["LoginName"].ToString());
TblPER_Personeelslid Receiver = BCL.GetEmployeeById(Id);
var Model = new TblALG_PrvBericht();
Model.Datum = DateTime.Now.Date;
Model.Zender = Sender.IDPersoneelslid;
Model.Ontvanger = Receiver.IDPersoneelslid;
ViewBag.ReceiverName = Receiver.Voornaam + " " + Receiver.Naam;
return View(Model);
}
public ActionResult PriveBerichten()
{
ViewBag.SelectedEmployee = "";
var Model = new PriveBerichten();
return View(Model);
}
View:
If I debug my view I clearly see #Model.SelectedOption filled.
#using (Html.BeginForm("PriveBerichten", "Home", #Model, FormMethod.Post))
{
#Html.ActionLink("Nieuw bericht maken", "NieuwPriveBericht", new { Id = #Model.SelectedOption }, new { #class = "button-add" })
}
AJAX CALL
$("#DdlEmployees").change(function () {
var SelectedEmployee = $('#DdlEmployees option:selected').val();
$.ajax({
type: "POST",
url: 'PriveBerichten?SelectedEmployee=' + SelectedEmployee, // this works
dataType: "json",
data: $('form').serialize(),
success: function () {
alert("test"); // does not show
},
error: function () {
}
});
})
If you didn't set up the id of route is "Id", you need to use "id". Also delete "#Model" in the BeginForm.
Action
public ActionResult NieuwPriveBericht(int id)
{
//
}
View:
#using (Html.BeginForm("PriveBerichten", "Home", FormMethod.Post))
{
#Html.ActionLink("Nieuw bericht maken", "NieuwPriveBericht",
new { id = #Model.SelectedOption }, new{ #class = "button-add" })
}
Thanks for showing the ActionResult that generates the view. I think this is your problem:
var Model = new PriveBerichten();
return View(Model);
I assume your class PriveBerichten contains the SelectedOption property? If you do not change/initialize this property value in the constructor of PriveBerichten it is 0 by default, and so it will be 0 in your actionlink.

How pass int list from action to view, then from view to method in mvc 4?

In MVC4 application in Create(post) action I want to pass int type list to view if error occur. And then, from there to pass it to other method in same controller with ajax post. So, TempData, ViewData and ViewBag don't help me.
public ActionResult Create(CreateModel model)
{
if(hasCustomError)
{
List<int> selectedItems = new List<int>() { 1, 2, 8 }; //for example.
ViewBag.VB = selectedItems;
//ViewData["VD"] = selectedItems;
//TempData["TD"] = selectedItems;
return View(model);
}
return RedirectToAction("Index");
}
After return View(model);, list of selectedItems passed to Create.cshtml view. It has value here I checked. But from here I should pass that list to GetTreeData method via ajax post:
#{
if (ViewBag.VB != null)
{
TempData["SelectedItems"] = ViewBag.VB as List<int>;
}
}
$("#myTree").jstree({
json_data: {
"ajax": {
url: "#Url.Action("GetTreeData", "MyController")",
type: "POST",
dataType: "json",
contentType: "application/json charset=utf-8"
}
},
checkbox: {
real_checkboxes: true,
checked_parent_open: true
},
plugins: ["themes", "json_data", "ui", "checkbox"]
});
In the MyController, in GetTreeData method TempData["SelectedItems"] is null .
public string GetTreeData()
{
List<int> selecteds = null;
if (TempData["SelectedItems"] != null)
{
selecteds = TempData["SelectedItems"] as List<int>;
TempData["SelectedItems"] = null;
}
......................................
}
I tried this for all (TempData, ViewData and ViewBag). nothing changed.
How can pass that list from action to view and then from that view to method?
Create a viewmodel, in that viewmodel set your model that you are using now as a field, and add an extra field for that list

How to pass a object from ajax to the server in MVC?

I've got two models, there are.
public class CreateAssignmentViewModel {
...
public List<CreateAssignmentSelectedItem> SelectedItems { get; set; }
}
public class CreateAssignmentSelectedItem {
...
}
Now I've got a view where contains CreateAssignmentViewModel, as you can see above this class contains a property where is a List<CreateAssignmentSelectedItem>
#model Contoso.MvcApplication.Models.Assignment.CreateAssignmentViewModel
#{
ViewBag.Title = "Create Assignment";
...
}
#using (Html.BeginForm()) {
...
}
Inside of the Html.BeginForm, I've got a partial view. And in it I've got a button using ajax where updates the partial view.
Look the following events. Where says data: I do not know what to enter to access only the property SelectedItems
var addQuestionToAssignmentContent = function (questionId)
{
$.ajax({
url: "/Assignment/AddItemToAssignmentContent",
type: "post",
data: { model: $(this).serialize() /* HERE I DON'T KNOW TO ACCESS THE */, itemId: questionId },
success: function (response) {
var $target = $("#assignmentContent");
var $newHtml = response;
$target.replaceWith($newHtml);
}
});
};
public ActionResult AddItemToAssignmentContent(List<CreateAssignmentSelectedItem> model, string itemId)
{
...
PartialView(..);
}
How can I do to pass only the object in the method?
First, give your form an ID:
#using (Html.BeginForm("actionName", "controllerName", FormMethod.Post, new{id = "frmUpdate"})) {
Second, change your code to be like this:
var f = $("#frmUpdate");
$.ajax({
url: f.attr('action'),
type: f.attr('method'),
data: f.serialize(),
//etc..
I use this in most cases and it works just nice. The data should automatically be bound to the model you have in your update action. So, for example... if you have a #model of type MyModel then in the update action it should look something like this:
[HttpPost]
public ActionResult Update(MyModel updatedModel)
Sometimes I work with a front end guy and he might not adhere to pass in the correct model, he might change the form fields or whatever. In this case I just let him serialize the form and pass it to the action an any way he wants.
I then use the FormCollection object to get the data I need.
Your json call
var addQuestionToAssignmentContent = function (questionId)
{
$.ajax({
url: "/Assignment/AddItemToAssignmentContent",
type: "post",
data: { model: $(this).serialize() /* HERE I DON'T KNOW TO ACCESS THE */, itemId: questionId },
success: function (response) {
var $target = $("#assignmentContent");
var $newHtml = response;
$target.replaceWith($newHtml);
}
});
};
Get a form collection object
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult AddItemToAssignmentContent(FormCollection collection)
{
vars someValue = collection.GetValue("somefield").AttemptedValue;
}
But if I would have control of front-end as you do then as Matt suggested you should use an pass a model;

MVC ViewModel issue

I have a viewmodel that has 2 properties, first property is a Model object and the second property is a List . In my View i have 2 parts.
First part populates the data for the first object, Firstname,lastname,email and some other stuff.
The second part of my view is a webgrid that a user adds multiple address.
Now what is my problem, i have a JSON action on my controller that gets the data from the form, adds them to the viewmodel List property, but nothing happens.
I checked that the data is coming from the view, added to the viewmodel but each time the viewmodel is empty.
[Authorize]
public JsonResult addAddress(Address addr, CustomerViewModel model)
{
if (model.CAddress== null)
model.CAddress= new List<Address>();
model.CAddress.Add(addr);
return Json(model, JsonRequestBehavior.AllowGet);
}
I am using Javascript :
function AddAddress()
{
var addID = $("#lstID option:selected").val();
var addName = $("#lstAddName option:selected").text();
var Address =
{
addID : addID.toString(),
addName : addName.toString()
};
$.ajax({
type: "POST",
url: "#Url.Action("addAddress","Customer")",
dataType: "json", contentType: "application/json; charset=utf-8",
data: JSON.stringify(Address),
success: function (data) {} }); };
Alright, start by writing a real view model, not some hybrids:
public class CustomerViewModel
{
public List<AddressViewModel> Addresses { get; set; }
... some other properties you already had
}
public class AddressViewModel
{
public string Id { get; set; }
public string Name { get; set; }
}
then adapt your controller action to take your real view model, and not some hybrids and mixtures between view models and domain models:
[Authorize]
[HttpPost]
public ActionResult AddAddress(CustomerViewModel model)
{
return Json(model);
}
and finally adapt your AJAX call:
function AddAddress() {
$.ajax({
url: '#Url.Action("AddAddress", "Customer")',
type: 'POST',
contentType: 'application/json; charset=utf-8',
data: JSON.stringify({
addresses: [
{
id : $('#lstID').val(),
name : $('#lstAddName option:selected').text()
}
],
someOtherPropertyOnYourViewModel: 'some other value'
}),
success: function (data) {
}
});
}

Resources