Post Array from Ext.Net store into ASP.NET MVC - json

I know there are other questions on the forum regarding this but found ho helpful solution up to now.
I have a controller so defined:
[HttpPost]
public ActionResult Update(int id, IList<MyObject> data)
{
return Json(new { success = false, message = "saved!" });
}
A Json Array of MyObject is inside a JsonStore and sent up on the submitData() function call. I can see everything is sent up correctly, the "data" parameter is an array of MyObject, if I manually do JSON.Deserialize<IList<MyObject>>(data) I get exactly what I need, which means that data is a valid json string... in the Headers I can see the "application/json" content-type.
I am using the JsonValueProviderFactory already, but it does not help. From my understanding it seems that the value provider should easily map arrays into IList, so I am wondering if I am doing something wrong...
Thanks!
UPDATE
As noted in one comment I have a slightly different use scenario: I am actually posting this data through a Store.submitData() call... apparently, even though the headers are similar, the store submit does not work because it actually generates a string.
Does anyone have any knowledge on how to force the store to do something similar to JSON.stringify?

You haven't shown your client code but the following should work fine:
Ext.Ajax.request({
url: '#Url.Action("update", new { id = "123" })',
method: 'POST',
headers: { 'Content-Type': 'application/json' },
params: JSON.stringify({
data: [
{ foo: 'value 1' },
{ foo: 'value 2' },
{ foo: 'value 3' }
]
}),
success: function (response) {
alert(response.responseText);
}
});
It assumes that MyObject is defined like this:
public class MyObject
{
public string Foo { get; set; }
}
but of course it could be just any complex object.

Related

How to retrieve JSON data in controller in ASP.net Core?

i need to get data sent with JSON and save to model in asp.net controller
//JSON data
var dataType = 'application/json';
var data = {
ID: 'Zaki',
}
console.log('Submitting form...');
console.log(data);
$.ajax({
type: 'POST',
url: 'Save',
dataType: 'json',
contentType: dataType,
data: data,
success: function (result) {
console.log('Data received: ');
console.log(result);
}
});
Controller
[HttpPost]
public ActionResult Save([FromBody] string ID)
{
return Json (ID);
}
am getting null in console , it supposed to be zaki and from there i wanna write saving code...
Another way to do it is to simply use 'dynamic' type to handle json request data. Take a look:
[HttpPost]
public IActionResult YoutMethod([FromBody] dynamic requestData)
{
Log.Information(requestData.field1);
Log.Information(requestData.field2);
// ...
return Ok();
}
Modify this line in your code data: data, to
data:JSON.stringify(data)
When sending data to a web server, the data has to be a string and JSON.stringify method converts a JavaScript object into a string.
Another approach would be, instead of getting raw string value, wrap your parameter into a class object like this
public class ParamObj
{
public string ID{get;set;}
}
and in your controller get a parameter of this object type like this..
public ActionResult Save([FromBody] ParamObj data)
Thanx
I know that is already marked as answered, but here is another way to do it:
I am not using the binding FromBody attribute.
Controller
public class JsonRequest
{
public string Id { get; set; }
}
[HttpPost]
public ActionResult Save(JsonRequest data)
{
return Json(data.Id);
}
Instead of using dataType I am using accept and you don't need to convert your json into a string.
To avoid problems with relative paths I am using: url: '#Url.Action("Save", "Home")' as well.
Javascript
function send()
{
//JSON data
var dataType = 'application/json';
var data = {
"id": "Zaki"
}
console.log('Submitting form...');
console.log(data);
$.ajax({
type: 'POST',
url: '#Url.Action("Save", "Home")',
accept: dataType,
data: data,
success: function (result) {
console.log('Data received: ');
console.log(result);
}
});
}
Good luck with your project.

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"})',

Asp.net mvc deserialize ajax.beginForm

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

MVC Ajax GET method with JSON object as parameter

I'm trying to make an Ajax request to an action sending a Json object as parameter.
Here is the code of the Jquery:
var jsonObject = {
"Id": 33,
"Name": "TEST"
};
$.ajax({
type: "GET",
url: rootPath + "ScheduledEvents/Edit/",
data: JSON.stringify(jsonObject),
/*contentType: "application/json; charset=utf-8",*/
dataType: "json",
success: function (data) {
$("#defaultModalRightEventContent").html(data);
$("#defaultModalRightEvent").modal("show");
},
error: function (request, status, error) {
alert(request.responseText);
}
});
Here is the class on the server side:
public class TestingClass
{
public int Id { get; set; }
public string Name { get; set; }
}
And here is the controller action:
[HttpGet]
public ActionResult Edit(TestingClass testingClass)
{
return PartialView("_ScheduledEvent", new ScheduledEventVM());
}
What is happening is that even though the object isn't null when hitting the action, both Id and Name as empty.
If I change the method from GET to POST then the object arrives correctly to the action, but then I get a RequiredValidationToken error. And since I don't actually have a form with the token to use I'm really out of options.
Is there a way to use GET or do I really need to use POST.
Thanks in advance for your help.
Since your method reads Edit, it means it is changing the state of the server. Hopefully an update operation in the database.
As far as RequiredValidation Token error is concerned, I think you are talking about AntiForgeryToken. You can avoid this by removing [ValidateAntiForgeryToken] attribute on your post requests or you can provide the same token from client side using a helper method.
If you write Html.AntiForgeryToken() in your views, it will create a hidden field on in html with name __RequestVerificationToken. You can pick up this value and also push this along with ajax request's data and header. After doing this, your problem will go away.

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!