MVC 3 jquery ajax post 2 objects - javascript

I have a controller action that takes two objects as arguments. I can't get it to work at all they always come back as null. My latest try looks like below. I have tried many other variations. In this case the FormInfo class is a class with 2 properties that are types for Form1 and Form2. I have also tried having the controller take in the two classes as arguments and the data part looked like { form1: form1Data, form2: form2Data } that was not working as well. I also tried using JSON.stringify to form the data with no luck.
Looking in the network monitor I see the data going back to the server it's just the engine that MVC uses to decode the query string to the objects can't handle what I'm passing back.
Thanks in advance for any information!
ClientSide
var formData = $("#form1").serialize();
var formData2 = $("#form2").serialize();
var formInfo = new Object();
formInfo.FormData = formData;
formInfo.FormData2 = formData2;
$.ajax({
url: 'Controller/Action',
type: 'POST',
data: formInfo,
success: function (data) {
//do stuff
}
});
ServerSide
public ActionResult SaveForms(FormInfo formInfo)
{
//Do Stuff here
}

You could use the a JSON request in conjunction with the .serializeArray() jQuery method. Let's suppose that you have the following model:
public class FormInfo
{
public Form1Data Form1Data { get; set; }
public Form2Data Form2Data { get; set; }
}
where Form1Data and Form2Data are some completely arbitrary complex classes. Now on the client we suppose that you have 2 distinct forms (#form1 and #form2 whose input element names match your complex structures in terms of default model binder wire format). Sending an AJAX request and packing the 2 forms together becomes trivial:
var form1Data = {};
$.each($('#form1').serializeArray(), function () {
form1Data[this.name] = this.value;
});
var form2Data = {};
$.each($('#form2').serializeArray(), function () {
form2Data[this.name] = this.value;
});
$.ajax({
url: '#Url.Action("someaction", "somecontroller")',
type: 'post',
contentType: 'application/json; charset=utf-8',
data: JSON.stringify({
form1Data: form1Data,
form2Data: form2Data
}),
success: function (result) {
// TODO: do something with the result
}
});
And of course the controller action you are POSTing to looks like this:
[HttpPost]
public ActionResult SomeAction(FormInfo formInfo)
{
...
}

I am doing something like this but i have a object and other Formdata to pass my Controller
var discrepancy = self.newCptyReply();
if ($('#UploadFile')[0]) {
var upload = new FormData(),
file = $('#UploadFile')[0].files[0];
upload.append('id', self.globalMessageId());
upload.append('discrepancy', ko.toJSON(discrepancy));
upload.append('doc', file);
}
datacontext.saveCptyToReply(self, upload);
And in controller signature
public ActionResult SaveCptyToReply(Guid id, Trade discrepancy, HttpPostedFileBase doc)
But when it reaches Controller id , doc are ok but discrepancy is null... It has data when funciton is called..
What to do...

Related

passing an array from ajax call to controller, array empty in controller

Can anyone suggest what I need to change here?
I'm getting classes from elements that contain the class 'changed', the classes I get contain id's that I want to pass to the controller method.
When I look in the network tab I can see the data I want in the payload, it looks like this:
{"list":["GroupId-1","SubGroupId-2","changed"]}
but when I put a breakpoint on the controller the list is null.
This is the class I'm expecting in the controller method:
public class MemberGroups
{
public string GroupId { get; set; }
public string SubGrouId { get; set; }
public string Status { get; set; }
}
javascript for the save
function Savechanges() {
var spans = document.getElementsByClassName("changed");
var list = [];
$.each(spans,
function (key, value) {
$.each(value.classList,
function (key, value) {
list.push(value);
});
});
var dataToPost = JSON.stringify({ list: list });
$.ajax({
url: "/umbraco/Api/OrganisationMemberGroupsDashboardApi/UpdateMemberToGroup",
data: JSON.stringify({ list }),
type: "POST",
contentType: "application/json; charset=utf-8", // specify the content type
})
.done(function (data) {
});
}
controller
public string UpdateMemberToGroup( List<MemberGroups> list)
{
// save records
}
The spans are created dynamically and added to a treeview. When they are dragged and dropped all classes are removed then the 'changed' class is added along with the id classes so I only pass the ones I need to to the controller
var s = document.createElement('span');
s.classList.add('node-facility');
s.classList.add('ui-droppable');
s.classList.add('GroupId-' + value.GroupId);
s.classList.add('SubGroupId-0');
s.id=('GroupId-' + value.GroupId);
s.appendChild(document.createTextNode(value.GroupName));
This variant was tested using postman body json -
["GroupId-1","SubGroupId-2","changed"]
Change your ajax data to this:
data: list,
and your controller action:
public string UpdateMemberToGroup([FromBody] []string list)
{
var memberGroups = new MemberGroups
{
GroupId =list[0],
SubGrouId =list[1],
Status =list[2]
};
// save records
}
This variant was tested in postman using
{"GroupId":"GroupId-1","SubGroupId": "SubGroupId-2", "Status":"changed"}
you can put the code in javascript:
var data={GroupId:list[0],SubGroupId:list[1], Status:list[2]}
......
....
data:data,
.....
your controler action in this case:
public string UpdateMemberToGroup([FromBody] MemberGroups memberGroups)
{
// save records
}
And I don't know what version MVC you use , but for some versions instead of [FromBody] better to use [FromForm] or don't use anything at all.

I want to send a class array with ajax but, when I make a request, the request does not reach the backend side

I want to send a class array with ajax but, when I make an ajax request, the request does not reach the backend side. When I sent a string array request. It works great. But If the Array contains a class, it is as if no request is made.
This is my javascript class:
var image_base64_code = [];
class images_base64 {
constructor(id, base64, name) {
this.id = id;
this.base64 = base64;
this.name = name;
}
}
//***************************************
// there are some codes here. For information.
//***************************************
image_base64_code.push(new images_base64(preview_intex, image_base64,name));
This is my ajax request:
$('#Ajax').click(function () {
var ImageJsonText = JSON.stringify({ image_base64_code: image_base64_code});
$.ajax({
url: 'main.aspx/ImageSave',
dataType: 'json',
type: 'POST',
data: ImageJsonText,
traditional: true,
contentType: 'application/json; charset=utf-8',
success: function (data) {
alert(data.d);
}
});
});
});
And my backend function:
[WebMethod]
public static bool ImageSave(RequestImage[] image_base64_code)
{
return 1;
}
public class RequestImage{
public string id;
public string base64;
public string name;
}
Use an object
var image_base64_code = {}; // object.
image_base64_code["images"] = [];
image_base64_code["images"].push( ... ); // add new here.
var ImageJsonText = JSON.stringify(image_base64_code);
JSON.stringify turns objects into strings, so change public static bool ImageSave(RequestImage[] image_base64_code) to accept a string.
public static bool ImageSave(string image_base64_code)
{
return 1;
}
Inside this method you can convert the string to RequestImage objects (deserialize) with built-in javascript deserializer or a library like JSON.NET (Newtonsoft).
Also see: JSON.stringify doesn't work with normal Javascript array

Minor trouble with AJAX POST method passing to C# MVC controller method

Hello denizens of stackoverflow, I've been debugging a pesky ajax POST method for a bit too long now, and was hoping I could get some input. I have a JavaScript function that collects an array of strings to box up and send off to a controller method of mine, but unfortunately the parameter data is not being sent, and I cannot figure out why.
Here is the JS function:
$.ajax({
url: 'CancelDoc',
method: 'POST',
datatype: 'json',
headers: addAntiForgeryHeader(),
data: { datakeys : DataKeys }
}).done(function (data) {
if (data.status == 0) {
alert("DOCUMENT CANCELLED SUCCESSFULLY");
}
});
To clarify a little:
DataKeys is the array of strings. It is coming through to this point as it should.
Looks something like:
["1432long-crazy4297-jumbled5826string|9000|1|1|NEW",
"1432and2-another03-jumbled1594string|9000|1|1|NEW"]
addAntiForgeryHeader() is an extra client validation method that I add on to all POSTs. The problem should not lie here because I have commented this out to try the call and it still does not pass data.
The C# controller method this goes to:
Note: the code DOES make it this far, the datakeys parameter is null though.
public ActionResult CancelDoc(string[] datakeys)
{
DocObject Doc = new DocObject();
List<string> Datakeys = datakeys.ToList();
foreach (var dk in Datakeys)
{
...
Some model logic here (not even making it here so no worries)
...
}
return Json(new { status = 0 });
}
I have tried:
Data conversion to JSON in numerous ways: ko.mapping.toJS(data), JSON.stringify(data), and literal writing of a JSON object for this.
Stripping the call down to the most basic form: I have tried commenting out the datatype and headers properties. This had a couple more properties before I posted as well.
Any input is greatly appreciated.
The dataKeys payload need to be stringify as :
$.ajax({
//prev code
data: { datakeys : JSON.stringify(DataKeys) }
}).done(function (data) {
//success
});
In the MVC controller, desearlze the json as:
public ActionResult CancelDoc(string[] datakeys)
{
dynamic sourceJson = JsonConvert.DeserializeObject(dataKeys, typeof(object));
DocObject Doc = new DocObject();
List<string> Datakeys = sourceJson.ToList();
}

making .ajax request to mvc controller - but .done function never executes

So basically Here is what I do:
in body - onload method I call this javascript function
function TestN() {
var list = new Array();
var allElements = document.getElementsByTagName('*');
$("*[wordNum]").each(function ()
{
var endRes = {
ControllerName: this.id,
WordNumber: this.getAttribute("wordNum")
};
list.push(endRes);
});
jQuery.ajax({
url:' #Url.Action("Translate")' ,
contentType: "application/json",
dataType: "json",
data: { List : JSON.stringify(list) }
,
traditional: true
})
}
what it does - it searches all the controlls with attribute "WrdNum" and then I make an ajax request to the MVC Translate action!
In the Translate Action I make a request to a web service which populates a list of type - TranslateModel
public ActionResult Translate(string List)
{
List<TranslateModel>listto = WebServiceBea.TranslateList(1, List);
return View(listto);
}
Also Here is my TranslateModel
public class TranslateModel
{
public string ControllerName { get; set; }
public string WordNumber { get; set; }
public string Description { get; set; }
}
So basically my question is -> what type should I return to a view - > and how to return this list to a javascript or jquery function which has to set the innerHtml property of some html controls with the record from this list.**
I now that it's strange but that's my task
EDIT
Thanks so much for the help. But now I've got another problem:
After I changed my javascript and put. Done method so I could get the data from the server it looks something like this :
$(document).ready(function () {
var list = new Array();
$("*[wordNum]").each(function () {
var endRes = {
ControllerName: this.id,
WordNumber: this.getAttribute("wordNum")
};
list.push(endRes);
});
jQuery.ajax({
url: ' #Url.Action("Translate")',
contentType: "application/json",
dataType: "json",
data: { List: JSON.stringify(list) }
,
traditional: true,
}).done(function (result)
{
alert ("HII") ;
});
});
no matter what I put in the .done function it never executes. It seems like the controller doesn't know where to return the result. |I| don't now. Can something happen from the fact that I'm making this request from the .layout page - on document ready. s
this looks like a greet place to use knockout js.
here is a great step by step for using knockout with the mvc view
so the method will only return json, the view will not have a model just a call to get the json
if you are going to use $.post to pull your data you could return your list as json
[AcceptVerbs(HttpVerbs.Get|HttpVerbs.Post)]
public ActionResult Translate(string List)
{
List<TranslateModel>listto = WebServiceBea.TranslateList(1, modelObj);
return Json(listto);
}
Looking at what you are posting to the action method, it should already be a list of that type. MVC should do the heavy lifting and transform it to the objects you have.
if however you would like to handle the return yourself you can do something like
jQuery.ajax({
url:' #Url.Action("Translate")' ,
contentType: "application/json",
dataType: "json",
data: { List : JSON.stringify(list) },
traditional: true
}).success(function( returnData, returnStatus)
{
//some code to handle the list of objects reutrned
});
You've already got an answer, but consider the following for cases where you may have controller actions called by javascript:
public ActionResult GetItems(string id)
{
var MyList = db.GetItems(id);//returns a list of items
if (Request.IsAjaxRequest())//called from javascript via AJAX
{
return Json(MyList, JsonRequestBehavior.AllowGet);
}
else //regular hyperlink click
{
return View(MyList);
}
}
To use the list, do the following
$.ajax({url: "'#Url.Content("~/controllername/GetItems")?id=' + id"})
.done(function(result){
var mylist = result.responseText.evalJSON();//this is your list of items
for(i=0;i<mylist .length;i++)
{
var myitem = mylist[i];
}
});
NEVERRRR NEVERRR Forge to put jsonRequestBehavior.AllowGet
Thanks alot for everyone for the help

How to populate javascript variable with JSON from ViewBag?

I have this Index action:
public ActionResult Index()
{
var repo = (YammerClient) TempData["Repo"];
var msgCol = repo.GetMessages();
ViewBag.User = repo.GetUserInfo();
return View(msgCol.messages);
}
GetMessages returns a list of POCO messages and GetUserInfo returns a POCO with the info of the user (id, name, etc).
I want to fill a javascript variable with the JSON representation of the user info.
So I would want to do something like this in the view:
...
<script>
var userInfo = "#ViewBag.User.ToJson()"
</script>
...
I know that doesn't work, but is there a way to do that? I want to avoid having to do an ajax request once the page is loaded just to get the user info.
In View you can do something like this
#{
var jss = new System.Web.Script.Serialization.JavaScriptSerializer();
var userInfoJson = jss.Serialize(ViewBag.User);
}
in javascript you can use it as
<script>
//use Json.parse to convert string to Json
var userInfo = JSON.parse('#Html.Raw(userInfoJson)');
</script>
Was using this solution for simple objects. But I had some problems getting an array to js objects so I'll just leave what I did here.
C#
#{
using Newtonsoft.Json;
ViewBag.AvailableToday = JsonConvert.SerializeObject(list);
}
js
var availableToday = JSON.parse('#Html.Raw(ViewBag.AvailableToday)');
Client-Side Code:
This is an ajax call to a .Net MVC Controller:
var clientStuff;
$.ajax({
type: 'GET',
url: '#Url.Action("GetStuff", "ControllerName")',
data: {},
dataType: "json",
cache: false,
async: false,
success: function (data) {
clientStuff = data;
},
error: function(errorMsg) {
alert(errorMsg);
}
});
Server-Side Code:
CONTROLLER:
public JsonResult GetStuff()
{
return Json(_manager.GetStuff(), JsonRequestBehavior.AllowGet);
}
MANAGER:
public IEnumerable<StuffViewModel> GetStuff()
{
return _unitofWork.GetStuff();
}
UNIT OF WORK:
public IEnumerable<StuffViewModel> GetStuff()
{
var ds = context.Database.SqlQuery<StuffViewModel>("[dbo].[GetStuff]");
return ds;
}
Unit of Work can be a query to a sproc (as I have done), a repository context, linq, etc.
I'm just calling a sproc here for simplicity, although it could be argued that the simplicity lies with Entity Framework and Linq.
You can change this line :
ViewBag.User = repo.GetUserInfo();
To
ViewBag.User = new HtmlString(repo.GetUserInfo());
You should add using Microsoft.AspNetCore.Html; or using System.Web; if HtmlString is not accessible.

Categories

Resources