Asp.net mvc deserialize ajax.beginForm - json

I need to pass my model, built in this form:
using (Ajax.BeginForm("Index", null, new AjaxOptions() { UpdateTargetId = "FormContainer", HttpMethod = "Post", InsertionMode = InsertionMode.Replace, OnSuccess = "successFunc" }, new { id = "UpdateForm" }))
To this method:
public ActionResult SavePreset(DocumentFilterModel model, string name)
{
//Do some magic
return PartialView("Partial/FilterListPartial", model);
}
The point is that by default, this form will collect report presets, however i need to add and option to save preset in my DB, that is why SavePreset method is needed.
I have tried to use this script:
$("#SavePresetButton").on("click", function () {
$.ajax({
type: "POST",
url: '#Url.Action("SavePreset", "Reports")',
data: {
name: $("#PresetNameEditor").val(),
model: $("#UpdateForm").serialize()
}
}).success(function(result) {
$("#FilterSettingsContainer").html(result);
});
});
But i have encountered a problem, where i either get null in DocumentFilterModel model either (if change model parametr's type to string) can't deserialize it. Things i have tried:
var SettingsModel = new JavaScriptSerializer().Deserialize<DocumentFilterModel>(model);
var a = JsonConvert.DeserializeObject<DocumentFilterModel>(model);
By the way, (these filters located in separate partial view) i would like to keep my form as it is, because i still need to update my second partial view with lists of record, and DocumentFilterModel is too big to parse it manually.

The serialize method reads your form and generates a url encoded string with your input element names and values. So basically it will be a big querystring. When you pass that as the data property of the $.ajax call, jquery will use that for the request body (like FormData)
So when you try something like this
data:{
name: $("#PresetNameEditor").val(),
model: $("#UpdateForm").serialize()
}
It it trying to send an object like this
{name: "Abc", model: "FirstName=Scott&Email=someEmail"}
You can see that you have a js object with 2 properties and the second property has all your input values in a query string format. The model binder cannot read this data and map to your DocumentFilterModel object!.
You cannot mix the result of serialize method to build a js object you want to send as data.
Simply use the result of serialize as the data property value of the ajax call and pass name in querystring.
$("#SavePresetButton").on("click", function () {
$.ajax({
type: "POST",
url: '#Url.Action("SavePreset", "Reports")?name='+$("#PresetNameEditor").val(),
data: $("#UpdateForm").serialize()
}).done(function(result) {
console.log(result);
});
});

Related

ASP MVC Areas and JSON POST

I have a project with areas and would like to post a view model as JSON to a controller method.
This is what I have, with performance being generated in the default area and passed to the view in area SeatSelection:
$("#addToCartButton").click(function () {
var json = #Html.Raw(Json.Encode(performance));
$.ajax({
url: 'https://#(Request.Url.Host)/SeatSelection/Home/AddToCart',
type: 'POST',
dataType: 'json',
data: json,
contentType: 'application/json; charset=utf-8',
success: function (data) {
alert(data);
}
});
});
And the action method for testing:
[System.Web.Http.Route("SeatSelection_AddToCart")]
[System.Web.Http.HttpPost]
public JsonResult AddToCart(PerformanceViewModel performance)
{
return Json(performance.Name);
}
I created the following route:
context.MapRoute(
"SeatSelection_AddToCart",
"SeatSelection/Home/AddToCart",
new { action = "AddToCart", controller = "Home", id = UrlParameter.Optional },
namespaces: new string[] { "myProject.Areas.SeatSelection.Controllers" }
);
But all I get is a internal server error 500. I also tried to use [FromBody] and setting a breakpoint to the method, but it is not invoked. I can't figure out what's wrong or missing, please help.
UPDATE
This is the json / performance:
PerformanceID=00000000-0000-0000-0000-000000000000&Name=Performance+15&StartDate=%2FDate(1360364400000)%2F&EndDate=%2FDate(1500328800000)%2F&LatestDateBookable=%2FDate(1450911600000)%2F&Organizer=Organizer+15&Location=Location+15&Availability=75&IsFull=false&IsBookable=true&HasPrice=true&BookableSeats=11&BookedSeats=94&Description=Description+of+Performance+15&Price=443
I found an error: "invalid json primitive: performanceid"
First of all, I would recommend you to use #Url.Action helper method instead of generating url like this: https://#(Request.Url.Host)/SeatSelection/Home/AddToCart.
Secondly, always validate params which comes from the browser. return Json(performance.Name) looks suspicious. What is performance will be null? This might be a problem of your internal server error 500.
If this is not a problem then try to send string instead of JSON to the server and validate and parse JSON on the server side.
You can use Url.Action method like this. I suppose SeatSelection is an area in your project.
$.ajax({
url: '#Url.Action("AddToCart", "Home", new { Area = "SeatSelection"})',

Trying to pass list of ids to the M-V-C Action through Ajax Function

I am trying to get and store the Ids of all the selected check-boxes in the JavaScript object. And then passing this object as a data to my JSON Action. I am able to successfully get the Ids of all the selected check-boxes, but when I am passing this object to my action I am getting null. Following is my code:
$("#btnSave").on('click', function () {
var selected = [];
$('input:checked').each(function () {
selected.push($(this).attr('id'));
});
$.ajax({
url: '#Url.Action("SaveRecords", "Users")',
data: { ids: selected },
cache: false,
type: "GET",
success: function (data) {}
});
});
My Action:
public JsonResult SaveRecords(List<int> ids) //Here I'm getting Null.
{
return Json(true, JsonRequestBehavior.AllowGet);
}
As suggested in the comments, since you are saving data POST is more appropriate than GET. Also, I think you will save yourself some trouble by using JSON as input - you're already using it as output format from the action. This means your AJAX call will look like this:
$.ajax({
type: 'POST',
url: '#Url.Action("SaveRecords", "Users")',
contentType: 'application/json',
data: JSON.stringify(selected),
success: function (data) { /* ... */ }
});
When I say "save yourself trouble by using JSON as input" I mean that model binding collections and complex types in MVC can be a bit tricky when sending data as a form post - google it and you'll see that there are several implementation characteristics to be aware of. In my experience, using JSON for structured data posted with AJAX just works much more like what you would expect.

How to send multiple parameters from kendo data source read operation to WebApi controller

I have the following scenario: I have a kendo.dataSource which is populated via read request to a WebApi Controller. In addition to the read, I am sending a couple of parameters, which then I use in my controller to do some server logic. I was able to send as many simple parameters as I want via the parameterMap property of the transport function. Till now it was a simple get request. However now I need to send additional json object to the controller as a parameter. I read that I have to transform the Get request to Post and put the Json onto the body of the request but I don't know how to do it.
The code that I have so far:
var gridDataSource = new kendo.data.DataSource({
type: 'odata-v4',
transport: {
read: {
url: wave.alarmsAndEvents.api('api/alarmsAndEventsSearch/post'),
type: "POST",
data: {
SearchModel: JSON.stringify(vm.searchModel)
},
contentType: 'application/json; charset=utf-8',
},
parameterMap: function (data, operation) {
if (operation === "read") {
data.startDate = kendo.toString(vm.selectedTimeInterval.start, "G");
data.endDate = kendo.toString(vm.selectedTimeInterval.end, "G");
data.alarmsToDisplay = vm.maxRecords;
}
return kendo.stringify(data);
}
},
pageSize: vm.maxRecords,
error: function (e) {
alert(e.xhr.responseText);
}
});
The SearchModel is the thing that I want to send as JSon. The rest are simple DateTime and int parameters.
My controller:
[HttpPost]
public IQueryable<AlarmsSearchViewModel> Post(DateTime startDate, DateTime endDate, int alarmsToDisplay, [FromBody]JToken jsonbody)
{
....
return something;
}
I end up with Not Found 404, but I am pretty sure that I have messed up the parameters. And from the Network window I can see that the json object is not sent at all. Any help will be much appreciated!

Passing Multiple Parameters to Ajax.ActionLink

I have a view and partial View in my MVC 4 Project. I have 3 textbox, one check box and a dropdown in view.I am using ajax.actionlink method, to call my controller, Action and pass the parameters and get the result from the partial view and display them in the div tag of the view page.
Here is my code.
#Html.TextBoxFor(m=>m.searchParameter.cityName)
#Html.TextBoxFor(m=>m.searchParameter.CountryName)
#Html.TextBoxFor(m=>m.searchParameter.StateName)
#Ajax.ActionLink("submit", "DisplaySearchResult", "Home"
, new { searchParameter = Model.searchParameter }
, new AjaxOptions() { HttpMethod = "Post", UpdateTargetId = "Results", InsertionMode = InsertionMode.Replace }, new { id = "DisplaySearchResult" }).
The problem is am not able to pass the parameters to the model. I am new to MVC4. Is there any way to pass the parameters using jquery or javascript?. I don't want to load the page during my search result.
As I see, you're trying to implement a search form. In this case I avoid using a ViewModel and usually do this:
#Html.TextBox("CityName", string.Empty)
#Html.TextBox("CountryName", string.Empty)
#Html.TextBox("StateName", string.Empty)
Then you can use a bit of jQuery to pass the values to your action method:
$("#submit").click(function() {
var $form = $('form');
$.ajax({
type: "GET",
cache: false,
url: '#Url.Action(ActionName, ControllerName)',
data: $form.serialize(),
success: loadResult
});
function loadResult(data)
{
$("#container").html(data);
}
Just make sure your action method has the appropriate parameters CityName, CountryName, StateName so that the values bind correctly.

ASP MVC 3 complex multi parameters kno

in my previos question Asp MVC 3 json complex object not initialize properties
My mistake was in JSON convert from Knockout and after one more time with JSON.stringify(data).
Now evering working fine with one parameter,
but I wonder about if I need send to MVC controller two or more parameters one of them is knowckout data = ko.toJSON(viewModel); variable other one is some text.
var settings = ko.toJSON(viewModel);
var parameters = JSON.stringify({ id : *"guid"*, data : settings });
$.ajax({
url: '/KioskAjax/SaveSettings/',
type: "POST",
data: parameters,
dataType: "JSON",
contentType: "application/json; charset=UTF-8",
success: function (result) {
alert('ok');
}
});
[HttpPost]
public JsonResult SaveKiosksSettings(Guid id, GlobalData data)
{
return Json(false.ToString(), JsonRequestBehavior.AllowGet);
}
In this example id is getting value, but GlobalData parameters is null again,
i think this is because I use JSON.stringify again, but how build correct JSON for controller call if I have knowckout object ?
thanks.
ko.toJSON(myObject) does a ko.toJS(myObject) and then a JSON.stringify(myObject).
So, you could choose to use ko.toJS(myObject) to get a clean copy of your data and then JSON.stringify it with your other data, as you are already doing.