MVC: How to serialize a knockout object into a JSON property through AJAX - ajax

I'm trying to serialize a knockout object and pass it into a JSON property called multipleCharge.
This is the ajax code to send data though Get method to a mvc controller
$.ajax({
url: _url,
type: 'GET',
//data: { multipleCharge: ko.mapping.toJS(_vm)},
data: { multipleCharge : { AccountId : 2 } },
dataType: 'json'});
And this is the method
[HttpGet]
public HttpResponseMessage GetSalesInvoiceMultipleCharge
([FromUri]MultipleChargeDto multipleCharge)
{
...
}
Please, note that the ajax method has a comment line. Using the hardcoded line, it works, multipleCharge object is not null, but if I uncomment the another line, it's a bad request in my browser.
Look at this.
Any idea about what's happening. Using the Chrome console, it looks ok; so I can't identify the error.

It is may be IIS problems with very long URL.
See this Issue with URL length in IIS7 (Windows Server 2008) question and related answers.
Also see this http://www.iis.net/configreference/system.webserver/security/requestfiltering documentation.
You could try to solve this problem by editing web.config. But also you could use POST method instead of GET and send your data in request body.

Related

$.extend ignoring 'traditional' flag

I'm working in an ASP.NET MVC4 application, and as such, all array data sent to the server over ajax must be sent using the traditional option. (no [] for POST variables).
The problem is, I also have a filter set-up which requires an AntiforgeryToken to be sent with each ajax POST.
I have fixed this using an ajaxPrefilter like this:
$.ajaxPrefilter(function (options, originalOptions) {
if (options.type.toUpperCase() == "POST") {
options.data = $.param($.extend(originalOptions.data, { __RequestVerificationToken: "antiForgeryToken" }));
}
});
This works great, and adds the __RequestVerificationToken to all POSTs.
However, it also causes my data not to be parametrized according to the traditional flag.
Does anybody know how I can modify my prefilter to account for this?
Example can be found here:
http://jsbin.com/IxoKIKA/2/edit
You forgot to pass the traditional argument to $.param(). You should write:
options.data = $.param($.extend(originalOptions.data, {
__RequestVerificationToken: "antiForgeryToken"
}), true);

Need to design a custom route in ASP.NET MVC 3?

I have designed a custom route which looks like below
"\client\{CLIENTCODE}\{Controller}\{View}\{id}"
other than this route I also have default MVC route intact.
The {CLIENTCODE} is 4 character length string in the URL,which will be used to detect a connection string and do operation on respective database.
I am facing two issues
All Ajax request take default route when I use AJAX URL as 'Controller\View'. How can I append {CLIENTCODE} to every AJAX request.
I am loosing {CLIENTCODE} from URL after the session expires and I am unable to get it in Global.ASAX.
If u need append this route to ajax request you need set the ajax url with your route.
$.ajax({
type: "POST",
url: '#Url.RouteUrl("routeName", new { code="code", controller="controller", action="action"})',
dataType: "html",
success: function (data) {
$("#product-attribute-values").append(data);
}
})
And what you mean 'loosing when session expired'? You can acces all route values with code like this in global.asax
protected void Application_BeginRequest()
{
string code = Request.RequestContext.RouteData.Values["code"].ToString();
}

Ajax request, should it be POST or PUT

I have created a Spring MVC web app.
The app makes a few calls to the controller. These calls are close/open/end game.
I make these calls using Ajax, so I can handle a response on the top of the page.
ajaxPost = function (url, action, id, onSuccess, onError) {
$.ajax({
type: "POST",
url: url + "?" + action + "=" + id,
success: function(response) {
if(onSuccess !== null) {
onSuccess(response);
}
},
error: function(e) {
if(onError !== null) {
onError(e);
}
}
});
};
The question I have is that I'm using 'POST' for the Ajax request, is that correct, or should it be 'PUT'?
My controller has a default URL, and I'm using the param attribute to decide which method to call, as I have many buttons on the page.
#RequestMapping(params = "open", method = RequestMethod.POST)
#RequestMapping(params = "close", method = RequestMethod.POST)
It doesn't sit well with me that I'm using 'POST' for these calls. Maybe it should be 'PUT'...
Any suggestions? Does it matter?
It depends on what your request should do. So there's no general rule that you should use one over the other, they have different use cases.
POST for creating a record.
PUT for updating an existing record (or putting a record at a specified location/id).
See this wikipedia article for the definitions.
One thing to note is that PUT should be idempotent, doing the same PUT request multiple times should ideally produce the same result as doing a single PUT request. However, POST is not idempotent, so doing several POST requests should (or will) create multiple new records.
So after having read this you should check what your method does, and select the corresponding request method.
Both PUT and POST may create a new record; PUT may also update/change an existing record.
The difference between POST and PUT is that PUT is expected to address the record with it's ID, so that the server knows what ID to use when creating (or updating) the record, while POST expects the server to generate an ID for the record and return it to the client after the record has been created.
Thus, a POST is addressed to the resource as a collection: POST /resource, while PUT is addressed to a single item in the collection: PUT /resource/1
Use POST. Always use POST, unless you're absolutely rock-solid certain that PUT is properly supported by your hosting system.

Deserializing into derived class in ASP.NET Web API

In my last SO question, I asked how to modify the serializer settings for Json.NET, which ASP.NET Web API natively uses for (de)serialization. The accepted answer worked perfectly, and I was, for example, able to embed type information into the serialized JSON string.
However, when I try to throw back this JSON string to a Web API action that's expecting the model's parent class, Web API still deserializes to the parent class, removes all data corresponding to the child class, and prevents casting to and detection of the child class.
class Entity { }
class Person : Entity { }
public Person Get() {
return new Person();
}
public bool Post(Entity entity) {
return entity is Person;
}
A simple use case would be doing something like this in jQuery:
// get a serialized JSON Person
$.ajax({
url : 'api/person' // PersonController
}).success(function (m) {
// then throw that Person right back via HTTP POST
$.ajax({
url : 'api/person',
type : 'POST',
data : m
}).success(function (m) {
console.log(m); // false
});
})
I'd expect that by modifying the JsonSerializerSettings of Json.NET to embed type information that it'd be able to read that and at the very least, try to force deserialization to that type, but apparently it does not.
How should I tackle something like this?
Web API really doesn't do any (de)serialization "natively". It happens to have a few MediaTypeFormatters included in the config.Formatters collection by default. Feel free to remove those and create your own MediaTypeFormatter that handles the serialization the way you want it to be done.
MediaTypeFormatters are really not that hard to create.
Actually the 2nd POST call is sending application/x-www-form-urlencoded data and that's why the type information is not picking up by the JsonMediaTypeFormatter. Try setting the contentType to be "application/json".
Also, the data in the 2nd POST request body seems to be encoded and it needs to be decoded before sending back to the service.
I was able to get this to work:
// get a serialized JSON Person
$.ajax({
url: 'api/person' // PersonController
}).success(function (m) {
// then throw that Person right back via HTTP POST
$.ajax({
url: 'api/person',
type: 'POST',
contentType: "application/json",
data: JSON.stringify(m),
}).success(function (m) {
alert(m); // true!
});
})

ASP.NET MVC Can JSON object be passed to a controller with parameter with dynamic type parameter?

I have code in my javascript, a ajax to post data:
$.ajax({
url: '/Configurations/GetSelectedPageTranslation',
type: 'POST',
data: { inttype: $("#some").val(), objectType:{prop1: 'adsfa', prop2: 'asdf'}},
success: function (result) {
},
error: function () {
alert('error');
}
});
In the contoller i have a method with signature:
public JsonResult GetSelectedPageTranslation(int inttype, dynamic objectType)
I can have the inttype correctly. However the objectType will not be null but if i do like objectType.prop1, it will throw error. If i will JSON.stringify the object type in the javascript, the objectType in the controller will have a string value.
Could this be possible to directly access the JSON data in the controller using the dynamic data type like this: objectType.prop1 ?
Thanks
There is no out of the box support for dynamic action arguments in MVC3.
However MVC is very extensible so you can add this functionality. What you need to do is to create a custom IModelBinder where you can do the JSON deserialization and build up a dynamic object.
Luckily this article: Making MVC 3 a little moreā€¦ dynamic is dealing with the exact same problem, so you can find also sample code and additional links there which should help you get started.

Resources