I have read quite some blogs and stackoverflow answers on how to send a JavaScript object to an asp.net MVC controller. But all examples I have seen so far require you to know which properties the JavaScript object will have (because they all convert the JavaScript object to a C# object).
When I was using PageMethods in asp.net webforms I could send any complex JavaScript object or array (even hierarchical data) and it would be converted to a Dictionary which I could iterate. Any chance I can do something similar in asp.net MVC?
I now found a way which works for me.
I am converting my data to json and receive it as a string in my ASP.net MVC controller.
Then I use the json.net library to read the data - since this library allows me to read the data without converting it to a C# (or VB) object.
JavaScript code:
//first include the json2 library for older browsers and jQuery
$.post(url, {json: JSON.stringify(mydata)});
Server side code:
public void xyz(string json)
{
JObject j = JObject.Parse(json);
string name = (string)j.SelectToken("Products[0].Name");
//...
}
The good thing: it is "normal" json which means it is not some uncommon format or interface-type.
EDIT: I found out that I don't even need the C# json-library if I am using .net 4 - since I can convert any json string to a Dictionary with the help of the JavaScriptSerializer:
JavaScriptSerializer jss = new JavaScriptSerializer();
Dictionary<string, object> data = (Dictionary<string, object>) jss.Deserialize<dynamic>(json_string);
What you can do is use jQuery plugin toDictionary, this plugin will transform your object to dictionary that asp.net MVC default model binder can understand
e.g.
$.ajax({
url: "/SomeURL",
type: "POST",
data: $.toDictionary(dataToSend)
});
Remember dataToSend is your object
This will be converted to a dictionary:
[{"key":0, "value":"something"},{"key":2, "value":"something else"},]
Obviously, you could do string,string or int, bool or etc...
For example, I have a method like this:
public int CollabSortFolder(int FolderId, Dictionary<int, int> Items)
I would call is using a GET:
/CollabSortFolder?FolderId=111111&Items=[{"Key":3685,"Value":0},{"Key":3670,"Value":1},{"Key":3687,"Value":2}]
Now as a GET it's not very elegant, but a post would work the same way.
Have you tried using the Request.Forms dictionary?
public ActionResult MyAction(FormCollection formValues)
{
}
Iterate over formValues
Related
I want to pass a java object to javascript. I am using spring as backend. For html I just passed the object to my model and I can call them in html through the "$" parameter. But in javascript it seems that this will not work.
So my question is. How can I call a passed object (which is already a json string) in javascript?
// java side
model.addAttribute("data", jsonObject);
// javascript side
// ???
You need to use ajax and call the api in the from spring controller.
#RequestMapping(value = 'url', method = RequestMethod.methodType)
public #ResponseBody List < SomeClass > getAllData(pass parameter here) {
return someResultFromHere;
}
You should add an ajax call for that specific api endpoint and use the name of the model to extract anything with in.. As brk stated you will call it and it will get value.Then you can use that to parse the data comming from the beckend of your server this is an example of the code.
// java side
model.addAttribute("data", jsonObject);
//ajax side
$getJSON('http://<yourserverip>:<yourport>/myapi/values/', function(data){
console.log(data.<yourValue>);
});
I'm using Blazor(3.0.0-preview4) and trying to pass an object from javascript through DotNet.invokeMethod. I tested this way and it succesfully passes simple types (strings, int). But if i pass JS object, i get weird object type
I can write it to Console.WriteLine, it looks like JSON, but not string.
So i cant make anything with this, i can't even parse it and there is no information about SimpleJson assembly from Microsoft. How can i deal with this type?
Thanks in advance.
Code example
Blazor:
[JSInvokable]
public static void SetPlayerState(object[] args)
{
Console.WriteLine(args[0]);
Console.WriteLine(args[0].GetType().Name);
}
JS:
window.cInvoke = (methodName, json) => {
DotNet.invokeMethod("ui", methodName, JSON.parse(json));
};
The DotNet.InvokeMethod will send a JSON string as you see in your WASM console log to your JSInvokable method in the Blazor .razor page.
To deserialize it in the blazor page use
[JSInvokable]
public static void SetPlayerState(string msg)
{
var deserialized = Microsoft.JSInterop.Json.Deserialize<myobject>(msg);
}
I found that blazor uses this library
Thanks to this answer
Related issue
I have been trying to send string arrays to a restful services without any luck. I have written this
#GET
#Produces(MediaType.TEXT_PLAIN)
public String getBackgroundImages(#QueryParam("missions") String[] missions,
#QueryParam("objects")String[] objects,
#QueryParam("dates")String[] dates) {
........
return generateTxt();
}
on the javascript side I have this
var missions = new Array("One", "Two");
var objects = new Array("objOne" ,"objTwo");
var dates = new Array("1967-11-07","1977-12-17");
$.ajax({
url: "myurl/rest/UploadBackgroundFile/",
data: {'missions':missions,'objects':objects,'dates':dates},
success: function (data) {
arr = JSON.parse(data);
$('.container-fluid').css('background-image','url('+arr[0].img+')');
}
});
my problem is that this is not working and I am getting this exception
org.apache.catalina.core.ApplicationContext.log StandardWrapper.Throwable
org.glassfish.jersey.server.model.ModelValidationException: Validation of the application resource model has failed during application initialization.
[[FATAL] No injection source found for a parameter of type
public java.lang.String UploadBackgroundFile.getBackgroundImages(java.lang.String[],java.lang.String[],java.lang.String[])
if I change the parameters to normal string and send strings from the javascript side than the method will work.
so the question is how to send and receive string arrays from the jquery ajax to the jersey restful method.
with regards,
es
Server side, you have to change the string array to a List<String> to make it work.
Client side, you can see this to help you how to send the datas. I know in title it's write PHP, but it's well explained.
I want to do this:
public ActionResult SaveStuff(dynamic vm) {
StoreTheValue(vm.myvalue);
return Content("Saved :)");
}
This doesn't work, MVC doesn't seem to want to create a dynamic object with properties that correspond to the post data of the request.
Now I know that the whole point of properly defined view models is to create strongly typed data structures and have MVC bind data into them, but given that I'm posting data from javascript using ajax it's not strongly typed data anyway, so I don't see that I'm loosing any maintainability by doing this, and it will save me time and effort creating view model classes.
Can anyone help suggest how I can bind post data to a dynamic object, posssibly using a custom model binder?
One possible way to achieve this would be to use a custom model binder, assuming that you are posting Json to the action
public class DynamicBinder : IModelBinder
{
public object BindModel( ControllerContext controllerContext, ModelBindingContext bindingContext )
{
using( var streamReader = new StreamReader( controllerContext.HttpContext.Request.InputStream ) )
{
return JsonConvert.DeserializeObject< dynamic >( streamReader.ReadToEnd() );
}
}
}
then in your action you can tell it, to use the custom binder
public ActionResult SaveStuff([ModelBinder(typeof(DynamicBinder))]dynamic vm) {
StoreTheValue(vm.myvalue);
return Content("Saved :)");
}
then post your json as such :
{
"myvalue":{...}
}
dynamic type and ajax request that you do with javascript is not corresponding.
You always can create your strongly typed object properties on javascript side.
Anyway you can use FormCollection like this:
[HttpPost]
public ActionResult yourAction(FormCollection collection)
{
StoreTheValue(Convert.ToString(collection["myvalue"]));
return Content("Saved :)");
}
But I think it's better to think of a strongly typed way.
For some reason, in ASP.NET AJAX, when I do this:
Sys.Serialization.JavaScriptSerializer.serialize({attachToValidators:true});
This is the result:
"{"attachToValidators":true}"
I try reversing the result:
Sys.Serialization.JavaScriptSerializer.deserialize("{\"attachToValidators\":true}");
or:
Sys.Serialization.JavaScriptSerializer.deserialize("{attachToValidators:true}");
I get this result:
Sys.ArgumentException: Cannot deserialize. The data does not correspond to valid JSON.
Parameter name: data
Why is that?
Thanks.
Answer posted here, though in 3.5, it was working great for me, I didn't need JSON.parse, so I don't know quite what happened: http://forums.asp.net/t/1631638.aspx
What are you trying to deserialize it to? This is how JavaScriptSerializer works, for deserialization:
public class ValidatorInfo
{
public bool attachToValidators { get; set; }
}
public void yourFunction()
{
var js = new JavaScriptSerializer();
ValidatorInfo info = js.Deserialize<ValidatorInfo>("{\"attachToValidators\":true}");
// True.
info.attachToValidators == true;
}
In your question, you're serializing an anonymous type, so you get away with not having an underlying type to serialize. That doesn't work on the way back in though.
If you need more dynamic behavior, Json.Net provides something like that with its LINQ implementation.