How to bind multiple classes in web api - asp.net-mvc

$.ajax({
type: "POST",
data: "{myEvents: " + JSON.stringify(myEvents) + ", myRecurrences: " + JSON.stringify(myRecurrences) + "}",
url: "/signupadmin/api/SignupAdminAPI/SaveEvent",
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (obj)
{
alert("success");
},
error: function (obj)
{
alert(obj.error());
}
});
[HttpPost]
public bool SaveEvent(EvancedEventData myEvents,RecurrenceData myRecurrences)
{
return true;
}
I have used two class files(evancedeventdata and recurrencedata) as mentioned and trying to bind the json objects to two classes from ajax but it throws the error "cannot bind multiple parameters" can you one suggest a reason why its not getting binded

Would be better to support questions like this with examples of the data, such as the JSON string you're posting and the Exception report.
However, try creating a wrapper class to encapsulate myEvents and myRecurrences, something like:
public class MyWrapperClass
{
EvancedEventData myEvents {get;set;}
RecurrenceData myRecurrences {get;set;}
}
Then change your POST action to expect the wrapper class:
[HttpPost]
public bool SaveEvent(MyWrapperClass data)
{
return true;
}
Then you should be able to read the data like this:
[HttpPost]
public bool SaveEvent(MyWrapperClass data)
{
var events = data.myEvents
//do stuff with the events
var recurrences = data.myRecurrences
//do stuff with the recurrences
return true;
}
(above is just an example - you no need to create and use separate variables to access the data).
Hope this helps.
Ben

Related

Posting object AJAX to MVC controller results in all properties being null

I am trying to post an object from jquery to MVC controller. The object is passed successfully but all the properties are null (or false for bools).
fwiw, if I JSON.stringify myObect then it does not pass at all, theObect in the controller is null.
I am using MVC4, .net 4.5, jQuery 1.9.1
Any help appreciate.
jQuery function
var myObject =
{
Property1: true,
Proerty2: true
};
$.ajax({
type: 'POST',
url: '/myController/StartProcess/',
data: { theObject: myObject }
});
Controller
private async void StartProcess(myObject theObject)
{
// theObect can be seen successfully but property1 and property2 are false
// if I change them to strings they are null
...
}
Class
public class myObject
{
public bool Property1 { get; set; }
public bool Property2 { get; set; }
}
EDIT:
The solution was:
$.ajax({
type: 'POST',
url: '/myController/StartProcess/',
data: myObject
});
If anyone can shed some light as to why this works and nothing else does it would be greatly appreciated. It is not a great solution because I have to put all my parameters in myObject, I cannot pass any additional parameters using this technique. also curious as to why all the info I find online, including official tutorials, say to use data: JSON.Strinify(myObect) but for me this causes all the properties of myObject to be null (or false).
Thanks to Roar all the same, at least I can move past this.
Get this JSON library and stringify() the object like this:
$.ajax({
type: 'POST',
url: '/myController/StartProcess/',
data: JSON.stringify(myObject)
});
try this
$.ajax({
type: 'POST',
url: '/myController/StartProcess/',
data: myObject
});
If you tried to POST your object to an API controller, it would probably work. I had some trouble with this myself. If you're using jQuery, you need to specify that you're sending JSON so the MVC controller will correctly interpret the data.
You could try this:
$.ajax({
contentType: 'application/json',
data: { theObject: myObject },
dataType: 'json',
type: 'POST',
url: '/myController/StartProcess/'
});
Here's what can also make all properties null :
public ActionResult GetPaymentView(CardModel Card)
{
}
If the view is a collection of a model, when you pass a serialized form of one element in the collection to ajax call, the controller expects the same name instance as the class name. I assume that this is the same way without collection but never tried. In this code example we serialize one element of the collection
$.ajax({
url: '/Shipments/GetPaymentView',
type: 'POST',
data: $('#' + ID).serialize(),
success: { onSuccess(); },
error: { onError(jqXHR, textStatus, errorThrown); }
});
The reason why this happens is because the view model is a collection of the CardModel and the serialization is adding CardModel before each properties like this : CardModel.ID=foo&CardModel.bar The model binder takes it as granted and tries to match the instance sent with the property of the controller which it can't and instantiate a new instance for you hence all properties are nulls.
Try adding contentType: "application/json; charset=utf-8" to your ajax call.
OK, finally figured it out. Here is a full and proper solution showing how to pass additional parameters along with the object:
jQuery:
var myString= "my paramter";
var myObject =
{
Property1: true,
Property2: true
};
var DTO = { param1: myString, param2: myObject };
$.ajax({
contentType: "application/json; charset=utf-8",
type: 'POST',
url: 'myController/StartProcess',
data: JSON.stringify(DTO)
});
Controller:
[HttpPost] // notice this additional attribute!
private async void StartProcess(string param1, myObject param2)
{
// param2 parameters are all true! param1 shows correctly too.
...
}
Class
public class myObject
{
public bool Property1 { get; set; }
public bool Property2 { get; set; }
}

Received parameter from ajax POST empty in controller + passed parameter in firebug MVC 4

I have looked over the net to figure out what my mistake is. All suggestions I found I tried, without any succes. I access the httppost action in my controller but the parameters stays empty.
AJAX function
var dataPost = { 'id': id, 'val': val };
debugger;
$.ajax({
type: 'POST',
url: '/Extensions/UpdateJson',
data: dataPost ,
contentType: 'json',
success: function () {
alert("succes");
},
error: function () {
alert("error");
}
});
On debug DataPost is populated.
Controller
[HttpPost]
public ActionResult UpdateJson(string id, string val)
{
//do stuff
return Json(true);
}
The parameters I used in my controller have the same name as in my Ajax function. The format passed is json, I have also tried populating my data with:
var dataPost = { 'id': 'id', 'val': 'val' };
But this doesn't make any difference. I have also tried to work with a Class, like -->
Class
public class ScheduleData
{
public string id { get; set; }
public string val { get; set; }
}
Controller
public ActionResult UpdateJson(ScheduleData data)
{//Do something}
Any help would be appreciated. Thanks in advance
The format passed is json
No, not at all. You are not sending any JSON. What you do is
data: { 'id': id, 'val': val }
But as the documentation clearly explains this is using the $.param function which in turn uses application/x-www-form-urlencoded encoding.
So get rid of this contentType: 'json' property from your $.ajax call.
Or if you really wanna send JSON, then do so:
var dataPost = { 'id': id, 'val': val };
$.ajax({
type: 'POST',
url: '/Extensions/UpdateJson',
data: JSON.stringify(dataPost),
contentType: 'application/json',
success: function () {
alert("succes");
},
error: function () {
alert("error");
}
});
Things to notice:
usage of JSON.stringify(dataPost) to ensure that you are sending a JSON string to the server
contentType: 'application/json' because that's the correct Content-Type value.

Passing IEnumerable through Json

I'm making a "Like" button in a simple comment database MVC program.
I'm passins the ID of the comment through to a ActionResult in the HomeController when I hover over the "Like" button. The problem (I think) is that I don't know how to pass the IEnumerable list of Likes to the ajax.
The script and HTML part:
HTML:
Like this
Script:
$(".likes").hover(function (event) {
var Liker = { "CID": event.target.id };
$.ajax({
type: "POST",
contentType: "application/json; charset=utf-8",
url: "/Home/ShowLike/",
data: JSON.stringify(Liker),
dataType: "json",
success: function (data) {
$.each(data.Name, function (value) {
alert(value);
});
},
error: function (xhr, err) {
// Note: just for debugging purposes!
alert("readyState: " + xhr.readyState +
"\nstatus: " + xhr.status);
alert("responseText: " + xhr.responseText);
}
});
});
HomeController -> ShowLike
[HttpPost]
public ActionResult ShowLike(Liker ids)
{
LikesRepository lkrep = new LikesRepository();
IEnumerable<Like> list = lkrep.GetLikes(ids.CID);
return Json(list);
}
LikesRepository
public class LikesRepository
{
CommentDBDataContext m_db = new CommentDBDataContext();
public IEnumerable<Like> GetLikes(int iden)
{
var result = from c in m_db.Likes
where c.CID == iden
orderby c.Name ascending
select c;
return result;
}
public void AddLike(Like c)
{
m_db.Likes.InsertOnSubmit(c);
m_db.SubmitChanges(); //This works
}
}
After diving into the problem more, we found it was actually triggering an internal server error (500). This was caused by a circular reference from serializing the LINQ to SQL objects to JSON. This issue is discussed several times...
How to remove circular reference in Entity Framework?
How did I solve the Json serializing circular reference error?
Circular Reference exception with JSON Serialisation with MVC3 and EF4 CTP5w
An alternate solution is to return the data as lists of strings as they only required the names.

jQuery.parseJSON not working for JsonResult from MVC controller action

I am trying to use jQuery.parseJSON to parse out the return value from an MVC3 controller action.
Controller:
[HttpPost]
public JsonResult LogOn(LogOnModel model, string returnUrl)
{
.. do stuff ..
if (errors.Count() < 0)
{
return Json(new object[] { true, model, errors });
}
return Json(new object[] { false, model, errors });
}
jQuery:
$.ajax({
url: form.attr('action'),
type: "POST",
dataType: "json",
data: form.serialize(),
success: function (data) {
var test = jQuery.parseJSON(data);
}
});
Json result from fiddler:
Content-Type: application/json; charset=utf-8
[false,{"UserName":"1","Password":"2","RememberMe":false},[{"Key":"","Errors":[{"Exception":null,"ErrorMessage":"The
user name or password provided is incorrect."}]}]]
Fiddler can parse the results:
The call to jQuery.parseJSON is returning null.
My questions is, how can I parse the json return value into an object?
Thanks!
You don't need to call parseJSON in your success handler, because ajax will have already parsed the JSON result (it does this automatically because you specified dataType:'json') into your array.
However, I'd recommend returning some sort of result object (whether you create an actual class in C# or use an anonymous type).
[HttpPost]
public JsonResult LogOn(LogOnModel model, string returnUrl)
{
.. do stuff ..
if (errors.Count() < 0)
{
return Json(new { success=true, model, errors });
}
return Json(new { success=false, model, errors });
}
and at the client
$.ajax({
url: form.attr('action'),
type: "POST",
dataType: "json",
data: form.serialize(),
success: function (result) {
alert(result.success);
// also have result.model and result.errors
}
});
You are actually returning an array of objects and they shoould be accessed like this in the success function:
var booleanValue = data[0];
var yourModel = data[1];
var yourErrors = data[2];
I did give #HackedByChinese an up vote because naming the properties might be a better way to go about it in the end. Howvbere this will solve your immediate problem.

MVC ajax json post to controller action method

I am trying to achieve a JQuery AJAX call to a controller action method that contains a complex object as a parameter.
I have read plenty blogs and tried several techniques learned from these. The key post on which I have constructed my best attempt code (below) is the stackoverflow post here .
I want to trigger an asynchronous post, invoked when the user tabs off a field [not a Form save post – as demonstrated in other examples I have found].
My intention is to:
Instantiate an object on the client [not the ViewModel which provides the type for the View];
Populate the object with data from several fields in the view;
Convert this object to JSON;
Call the controller action method using the jQuery.Ajax method, passing the JSON object.
The results will be returned as a JSON result; and data will be loaded into fields in the view depending on results returned.
The problems are:
If the action method is attributed with the HttpPost attribute, the controller Action method is not invoked (even though the AJAX call type is set to ‘POST’).
If the action method isattributed with HttpGet, the values of properties of the parameter are null
The ReadObject method throws the error: "Expecting element 'root' from namespace ''.. Encountered 'None' with name 'namespace'".
Hopefully someone can help. Thanks. Code below:
Client js file
var disputeKeyDataObj = {
"InvoiceNumber": "" + $.trim(this.value) + "",
"CustomerNumber": "" + $.trim($('#CustomerNumber').val()) + ""
};
var disputeKeyDataJSON = JSON.stringify(disputeHeadlineData);
$.ajax({
url: "/cnr/GetDataForInvoiceNumber",
type: "POST",
data: disputeKeyDataJSON,
dataType: 'json',
contentType: "application/json; charset=utf-8",
success: EnrichedDisputeKeyData(result)
});
Action Filter and class for the type associated with the Action method parameter
[DataContract]
public class DisputeKeyData
{
[DataMember(Name = "InvoiceNumber")]
public string InvoiceNumber { get; set; }
[DataMember(Name = "CustomerNumber")]
public string CustomerNumber { get; set; }
}
Action method on the controller
//[HttpPost]
[ObjectFilter(Param = "disputeKeyData", RootType = typeof(DisputeKeyData))]
public ActionResult GetDataForInvoiceNumber(DisputeKeyData disputeKeyData)
{
//Blah!
//....
return Json(disputeKeyData, JsonRequestBehavior.AllowGet);
}
Below is how I got this working.
The Key point was:
I needed to use the ViewModel associated with the view in order for the runtime to be able to resolve the object in the request.
[I know that that there is a way to bind an object other than the default ViewModel object but ended up simply populating the necessary properties for my needs as I could not get it to work]
[HttpPost]
public ActionResult GetDataForInvoiceNumber(MyViewModel myViewModel)
{
var invoiceNumberQueryResult = _viewModelBuilder.HydrateMyViewModelGivenInvoiceDetail(myViewModel.InvoiceNumber, myViewModel.SelectedCompanyCode);
return Json(invoiceNumberQueryResult, JsonRequestBehavior.DenyGet);
}
The JQuery script used to call this action method:
var requestData = {
InvoiceNumber: $.trim(this.value),
SelectedCompanyCode: $.trim($('#SelectedCompanyCode').val())
};
$.ajax({
url: '/en/myController/GetDataForInvoiceNumber',
type: 'POST',
data: JSON.stringify(requestData),
dataType: 'json',
contentType: 'application/json; charset=utf-8',
error: function (xhr) {
alert('Error: ' + xhr.statusText);
},
success: function (result) {
CheckIfInvoiceFound(result);
},
async: true,
processData: false
});

Resources