WebAPI Model Binding from JSON - json

I am creating an application using Durandal, with WebAPI as the server. I have a KendoUI grid that displays the data from the server correctly and functions properly until the POST or PUT methods are called. Here is my GET method:
and you can see that that data binds to the UI (used the data-bind extensibility in Durandal to change to kendo bindings):
Then I edit the data in the Grid and it passes the changes inside the request to the server as you can see in this Fiddler result:
On the server side I cannot get the data that is passed from the client to bind to anything I place as a parameter for the method on the POST or PUT.
I realize this is a couple different technologies to troubleshoot (e.g. Durandal, KnockoutJs, Kendo DataBinding, and WebAPI) but I think the fundamentals are working, the data is retrieved and bound to the UI and it is posted back when changed, but the WebAPI endpoint cannot bind to the data.
How can I get the passed "models" array to bind through the ModelBinding structure in WebAPI?
UPDATE- Here is the helpful JSFiddle that gave me the correct Content-Type to add: http://jsfiddle.net/Xhrrj/1/
new kendo.data.DataSource({
transport: {
read: {
type: "POST",
url: "../cccs/service.svc/SupplierSearch",
contentType: "application/json; charset=utf-8",
dataType: 'json'...
this is coming from the Telerik forum here

It looks as if it was mixing up form-urlencoded with json format - if you lookat the decoded string it is sending models= and then urlencoded JSON objects follow.

From my experience I think that your PUT end point declaration needs to look like this:
[HttpPut]
public void Put([FromBody]IEnumerable<Product> models) { }
So you need the FromBody attribute because your product array is in the body (I think?) and not in the url of the request.

Related

pass ajax response (json)data in php

So, I am stuck here and feel like banging my head.
My problem is I query a database by ajax and returned its response in json form. Now I have this response in the form of javascript variable but I want to pass it to a php variable for further use.
How can I do that ??
function getJson(url){
return JSON.parse($.ajax({
type:'GET',
url: url,
dataType:'json',
global:false,
async:false,
success: function(data){
return data;
}
}).responseText);
}
Here how do I pass data to php ??
FIrstly I gave you -1 for not learning the basics!
- You can send client values to server (php) as querystring
example: /server_link?json=JSON_VAL
(not recommended for whole json string)
- Send it as post body (look for jquery ajax post) and parse it with php json library.
- if you have just single level json ({name:'John', sname:'Smith)} you can send it to php server(as mentioned before ajax post) and read as request variable in php ($_POST, $_...).
As I never programmed in php you'll have to do it you're self.
A again: LEARN THE BASICS (client side, server side, post, get,...).

Tell modelbinding that MVC action parameter is JSON

I am using an upload control to send a file to a JsonResult, but I am also sending up a JSON string as a second parameter. This is all getting posted with the Content-Type:multipart/form-data;
[HttpPost]
public JsonResult UploadDocument(HttpPostedFileBase file, DocumentViewModel model)
{ ... }
I know MVC is capable of binding directly to a viewmodel if the content type is set to application/json but I don't think it's possible for me to set that in this case.
Is there any way for me to get MVC to automatically bind my posted json string to model?
That's not possible out-of-the-box. You will have to manually deserialize the JSON string parameter that you would read from the request to your view model inside the controller action or write a custom model binder for it that will do the job. Ideally you shouldn't be posting the model data as a JSON string but rather respect the content type you specified : multipart/form-data. So the correct way to handle this scenario is to modify the client code that is sending the request in order to respect the content type.
As I was unable to change the content-type I found this blog to be exactly what i needed.
"... our whole request stream(data) won’t be json string. Only the guest parameter will be supplied as json string..."
http://ishwor.cyberbudsonline.com/2012/07/fun-with-aspnet-mvc-3-custom-json-model-binder.html

Calling .Net web service from jQuery+Ajax

I'm trying to call a homemade vb.net web service using jQuery+Ajax and I'm struggling with the specifics.
Here's a small function exposed as a web method:
<WebMethod()> <ScriptMethod(ResponseFormat:=ResponseFormat.Xml, UseHttpGet:=True)> _
Public Function GetAllVotes() As XmlDocument
Dim theVotes = getVotes()
Dim strResult As String = theVotes.XMLSerialize
Dim doc As XmlDocument = New XmlDocument()
doc.LoadXml(strResult)
Return doc
End Function
After looking the web I've added the ScriptMethod attributes since i was returning XML but feel free to tell me i don't need them if that's the case.
Then, on the client side, this is the code :
function getVotes() {
$.support.cors = true;
$.ajax({
type: "GET",
contentType: "application/json",
url: "http://nhrd635:8008/votingmanager.asmx/GetAllVotes",
data: {},
dataType: "xml text jsonp",
success: function(msg) {
// Hide the fake progress indicator graphic.
// Insert the returned HTML into the <div>.
$('#myPlaceHolder').html(msg);
},
error: function(msg) {
$('#myPlaceHolder').html(msg);
// alert(msg);
}
});
}
I've tried many .. many variations of this code, using post or get, changing the content-type, with or without charset=utf-8. with and without double quotes on data: {}.
i use firebug to trace the output my request. only when i set dataType to jsonp do i ever get a result, but in all instances, the code ends up on the "error" function, even when status give 200 OK. but i know that setting it to jsonp is wrong since that gets my xml treated as actual javascript...
I've read very useful blog entries from a guy on encosia.
(sample: http://encosia.com/3-mistakes-to-avoid-when-using-jquery-with-aspnet-ajax/)
but even following his examples i am unable to get a proper return.
am i doing something wrong that's very obvious? is it the fact that i am returning an xml string rather than a json serialized string?
With more perusing of Stack Overflow and the help of Dave Ward from Encosia, I've managed to solve my problem. I've thought I should post my final solution here, in case that helps someone in the future.
First of all, Web Services were a bad way of doing it, I went with the HttpHandler solution, as suggested by Dave Ward in reply to my original question.
Returning XML was also a poor choice, that I wasn't really aware of. I added a reference to JSon.net to my project and used it to transform my object into a Json string.
I really wanted to stick to ".net only" to transform into a json string, as suggested in Dave's blog post, but somehow I struggled to learn how to instruct .net to automatically transform into Json as in Dave's example, so i took an easy way out with Json.net to "get it working"
Then, in my HttpHandler, I had the response string follow the instructions on this post from StackOverflow:
https://stackoverflow.com/a/3703221/1060133
in my case, it was :
context.Response.Write(String.Format("{0}({1});", context.Request("callback"), jsonVotes))
The jquery call also used the instructions in the above post.
Interesting note, even in a parameter-less call, you have to send empty data like so:
$.getJSON('http://url/httpHandler.ashx?callback=?', {},
function(data) {
alert(data);
}
);
Best of luck...
I think most of your trouble here probably stems from the cross-origin request (even making a request across different ports on the same machine counts). That's why you were able to get a glimmer of it working when you switched to JSONP. Unfortunately, ASMX "ScriptServices" don't support JSONP, so the data your WebMethod returned wouldn't be a valid parameter to the JSONP callback function that jQuery injects.
The best solution, if at all possible, is to get the service running on the same domain as the page that's calling it. There are various solutions to the cross-origin problem, but none of them are as widely compatible/reliable as a simple XHR request to the same domain that the page making the request resides on.
If you can't do that, consider enabling CORS support for the site serving up votingmanager.asmx. That doesn't work in most versions of IE, but will allow cross-origin requests in other browsers. More info on how to do that here: http://encosia.com/using-cors-to-access-asp-net-services-across-domains/
Tangentially, I'd avoid the extra XML serialization layer if possible. If getVotes() returns something like a List, use that as your return type and let ASP.NET automatically serialize the collection as JSON and then jQuery will automatically convert that to a JavaScript array in your success handler. More info about that here: http://encosia.com/asp-net-web-services-mistake-manual-json-serialization/

How can I get DotNetNuke 6.2 Service Framework to modelbind json data

DotNetNuke Serviceframework is based on ASP.NET MVC 2, and therefore does not include json modelbinding out of the box.
I've tried a number of approaches:
MVC3 jsonvalueprovider
custom json model binder
custom value provider
The code to register these was called, however the methods on these objects themselves were not called.
Registering these is an interesting area in itself as in DotNetNuke, we don't have access to the global.asax file.
I've also attempted to deserialize the request input stream, in the the controller, but I get a nullreferenceexception there, and I get the correct data size, but all nulls!
Any ideas?!
Ok,
I have a workaround that is clean and functional.
I'm using a jquery plugin from here .This converts json into a standard forms form post for you.
using this with jquery & knockout looks like this:
$.ajax({
url: '<%= ModulePath %>Api/Register/Search',
type: 'POST',
data: $.toDictionary(ko.mapping.toJS($root),"",true),
success: function (data) { //do something });
Leaving the question open, in case anyone has any ideas to get json working directly.
You need to register a JSON value provider to get this to work. See http://haacked.com/archive/2010/04/15/sending-json-to-an-asp-net-mvc-action-method-argument.aspx for details.
The best way to register the value provider is to do it in your route mapper. Be sure to guard the registration to ensure it occurs only once, as the route mapper is occasionally called more than once. If you are going to do this in a module deployed to servers you don't control you should probably inspect the contents of the factories collection to ensure no other service has already registered the value provider.
Services Framework in DNN 7 is based on WebAPI and natively supports JSON, so this hassle will go away soon.

Play Framework Cross Domain Web Service

I've been trying to create a Web Service with play framework. I've searched some tutorial and resource about this and end up using the renderJSON() method to provide JSON RESTful web service.
But, there seems to be a problem with that when I try to consume the web service with JQuery. If I use JSON, it fails with this error Origin http://localhost is not allowed by Access-Control-Allow-Origin. Which seems to be a cross-domain problem. Then I try to use JSONP as the datatype when JQuery trying to consume the web service, again there's an parseError problem.
After some research, I found that to provide a web service to the JSONP request. We need to provide something like a callback function. So it's not enough to return only the JSON object to the client. If I'm not mistaken, The format should look something like {#callback-function}{#JSON-data}
How to make a Cross-Domain web service in Play Framework? Is there any workaround for this?
Is there anyway to keep the JSON format of a/a list of object to a string instead of render the object as JSON directly as done by calling renderJSON()?
Here is what I did. In my routes I set the format of the response to javascript with:
GET /api/projects.json Api.projects(format:'json')
Then for the controller in Api I used flexjson and did this:
public static void projects(String p) {
JSONSerializer json = new JSONSerializer();
List<Project> projects = Project.all().fetch(3);
renderJSON(p + '(' + json.serialize(projects) + ')');
}
So now jsonp calls can be made by hitting /api/projects.json?p=whatever and the return will be:
whatever([{"your":"json"}])
You can also use flexjson to only serialize the parts of the object that you want to expose.
Testing it with jquery:
$.ajax({
url: "http://api/projects.json",
dataType: "jsonp",
jsonp : 'p',
crossDomain : true,
success: function(data){
console.log(data);
}
});
This is working great but you can use Gson object directly instead of the flexjson object.