MVC ViewModel issue - asp.net-mvc

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) {
}
});
}

Related

getting null form value in controller action method passing through ajax post request in asp.net

function register() {
var jsObj = {};
var data = $('#register').serializeArray();
$.each(data,function(index,feild){
jsObj[feild.name] = feild.value;
console.log(feild.name+" -- "+feild.value);
});
$.ajax({
url: '/Signup/Registeration',
type: 'POST',
contentType: "application/json; charset=utf-8",
dataType: "json",
data: JSON.stringify(jsObj),//this is my data in json format
async: false,
success: function (data) {
alert(data);
}
});
}
this my controller action method
[HttpPost]
public JsonResult Registeration(SignUp data)
{
return Json(data);
}
this is my signup class
public class SignUp
{
public string username { get; set; }
public string password { get; set; }
public string cpassword { get; set; }
}
In your very bottom image, the Request parameters for password and cpassword have an extra whitespace after them. I.e They are currently "password " and "cpassword " instead of "password" and "cpassword" respectively.

Sending a 2d array to the controller from ajax

I am sending name, which is a string, and table data which is a 2d array
And I get the name just fine in th controller, but I can't seem to get the tableData.
This is how I create the table data
TableData
var tableData = new Array();
$('table tbody tr').each(function () {
var tableRow = new Array();
tableRow.push({ 'id: $(this).data('id') });
tableRow.push({ 'item': $(this).data('item') });
tableData.push(tableRow);
});
JavaScript
var data = { Name: name, TableData: tableData };
$.ajax({
type: 'POST',
url: url,
data: data
});
Controller
[HttpPost]
public void Add(string Name, string[][] TableData)
{
// Stuff
}
As always in an ASP.NET MVC application you could start by defining a view model that will reflect to your view logic:
public class MyViewModel
{
public string Name { get; set; }
public Ilist<MyViewModelItem> TableData { get; set; }
}
public class MyViewModelItem
{
public string Id { get; set; }
public string Item { get; set; }
}
then fix the way you are constructing your data on the client:
var tableData = [];
$('table tbody tr').each(function () {
tableData.push({
id: $(this).data('id'),
item: $(this).data('item')
});
});
and then the way you are sending this information to the controller (send it as a JSON payload to ensure that complex objects will be properly bound on the server as long as your view model respect the proper format):
$.ajax({
type: 'POST',
url: url,
data: JSON.stringify({ name: name, tableData: tableData }),
contentType: 'application/json'
});
and the last piece of the puzzle - the signature of your controller action:
[HttpPost]
public void Add(MyViewModel model)
{
// Stuff
}

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);
}

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;

Model binder does not convert json to IEnumerable<T>

I am sending json data to my controller action via jquery ajax post. The IEnumerable in my action is alway null.
Is my json wrong or why does the model binder not convert the json to the IEnumerable ?
public ActionResult Update(IEnumerable<Teststep> teststeps)
{
//
}
$.ajax({
url: '#Url.Action("Update", "Teststep")',
type: 'POST',
data: [{ "errortext": "oh something bad happended.", "unitid": "10" }, { "errortext": "you got it man.", "unitid": "20"}],
success: function (response) {
debugger;
if (response.success) {
dlg.dialog("close");
// Update UI
}
else {
// Reload the dialog with the form to show model/validation errors
dlg.html(response);
}
}
});
public class Teststep
{
[HiddenInput(DisplayValue = false)]
public int UnitId { get; set; }
public string ErrorText { get; set; }
// some other props removed for readability
}
In order to get collections (arrays, ienumerables, etc) to pass correctly through the modelbinder to the action method, I've always had to set the traditional: true option on the ajax call:
$.ajax({
url: '#Url.Action("Update", "Teststep")',
type: 'POST',
traditional: true,
...
Now it works! I get 1 item in the IEnumerable. The problem was the messed up json ;-)
var data = { teststeps: [{ ErrorText: 'bla', UnitId: 10}] };
$.ajax({
url: '#Url.Action("Update", "Teststep")',
type: 'POST',
data: JSON.stringify(data),
dataType: 'json',
contentType: 'application/json'
});
[HttpPost]
public ActionResult Update(IEnumerable<Teststep> teststeps)
{
}

Resources