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.
Related
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 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.
I am trying to send a value from the client side using javascript or JQuery, to the server (ideally to a method in my codebehind). I am using C# .net 4.0.
In my client side JQuery I have:
$.post("test.aspx/testMethod",
{
name: "Donald Duck",
city: "Duckburg"
}
);
In my server side (test.aspx.cs) method, I have
public void testMethod()
{
string name = Request.Form("name");
string city = Request.Form("city");
}
But with this I get a compilation error: "Non-invocable member 'System.Web.HttpRequest.Form' cannot be used like a method."
How can I rectify this? Or reach the same objective? Using the $.ajax({...}) is not an option as the value is needed by a non-static method.
There is a very simple answer to this. After searching for hours thru dozens of questions posted along the same lines and many people offering overly complicated ajax post back solutions, I came up with this. Basically a one liner. Hope it helps someone:
In your javascript you just call the method:
PageMethods.SomeMethod('test');
Your "SomeMethod" would be a code behind method like this:
[WebMethod]
public static string SomeMethod(string param1)
{
string result = "The test worked!";
return result;
}
Rules:
You have to identify your code behind method with a WebMethod attribute. It has to be static. And you have to register a script manager in your page as follows:
<asp:ScriptManager ID="MyScriptManager" runat="server" EnablePageMethods="true" />
Since I am working with an aspx webforms page to do some really simple javascript functions like retrieving / stashing geo location, I put it inside the Form element as required.
you can use like this - https://rvieiraweb.wordpress.com/2013/01/21/consuming-webservice-net-json-using-jquery/
try it :)
I dont know if Web Forms support this type of JSON request. I have tried long back but I have to add asmx file that time. Currently you have WCF, but if you don't want to change your webforms project and still want restful api, then merge MVC project for your restful task. You dont have to shift everything but it work together. Here it is explained how?
I don't know about latest version of Web Forms but before VS2012, you can't do ajax type call to page. As far as I know.
Please let me know if any further details needed.
Found Solution... (Hope someone finds it useful)
JAVA SCRIPT
function myFunction() {
var str= "fname=Henry&lname=Ford";
log("MyString=" + str);
}
function log(message) {
var client = new XMLHttpRequest();
client.open("POST", "Default.aspx", true); // Default.aspx being the page being posted to
client.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
client.send(message);
}
C# Default.aspx.cs (CODE BEHIND TO Default.aspx)
protected void Page_Load(object sender, EventArgs e)
{
getText();
}
public void getText()
{
if (HttpContext.Current.Request.Form.Keys.Count > 0)
{
string code = HttpContext.Current.Request.Form["MyString"];
// code = "fname=Henry"
// For looping etc, see below
}
}
WHAT ELSE YOU CAN GET....
HttpContext.Current.Request.Form.Count // 2
HttpContext.Current.Request.Form.Keys.Count // 2
HttpContext.Current.Request.Form.AllKeys[0] // "MyString"
HttpContext.Current.Request.Form.Keys[0] // "MyString"
HttpContext.Current.Request.Form.AllKeys[1] // "lname"
HttpContext.Current.Request.Form.Keys[1] // "lname"
HttpContext.Current.Request.Form[0] // "fname=Henry"
HttpContext.Current.Request.Form[1] // "Ford"
Loop through keys...
foreach (string key in Request.Form.Keys)
{
DoSomething(Request.Form[key]);
}
The above code works in that it passes a value(s) from the client side javascript to the server side code-behind, but then unable to use the value because you lose it.
The following modification to the above code is required to use the value (essentially store it in a separate static class until needed).
C# Default.aspx.cs (CODE BEHIND TO Default.aspx)
protected void Page_Load(object sender, EventArgs e)
{
getText();
}
public void getText()
{
if (HttpContext.Current.Request.Form.Keys.Count > 0)
{
// Reset staticValue
Class1.staticValue = "";
Class1.staticValue = HttpContext.Current.Request.Form["MyString"];
// Call Class1.staticValue anywhere else and you get expected answer= "fname=Henry"
}
}
STATIC CLASS (App_Code/Class1.cs) - another object to store value (otherwise the HttpContext object removes it from anything)
public class Class1
{
private static string myValue = "";
public Class1()
{
//
// TODO: Add constructor logic here
//
}
public static string staticValue
{
get
{
return myValue;
}
set
{
myValue = value;
}
}
}
Is it possible to read the value of a dynamic variable like httpRequest.getSession("attr_name") from within a JavaScript?
(With Javascript, I assume that you mean client script in the browser.)
No, that is not possible. The contents of the Session object never leaves the server, so client script can't read Session data directly.
If you want to access it in the browser, you have to read the data out of the Session object and send it along in the response (for example in a hidden field), or provide a web service that reads data from the Session object and returns to the browser.
As I said in my comment, the only way would be some kind of Ajax call and request it from the server. I dont know what backend your using, here's how I would do it in Asp.net MVC and jQuery.
(If there are minor syntax errors, I apologize - not in front of a compiler)
public class HomeController : Controller
{
//abstract the session code away, don't let the evil javascript touch
//it directly. Ideally this would all be in a seperate logic class or something.
public string NameAttribute
{
get
{
return Session["attr_name"] as string ?? string.empty;
}
}
[HttpGet]
public string GetNameAttribute()
{
return NameAttribute;
}
public ActionResult Index()
{
return View();
}
}
<script>
$(function(){
$.get( 'home/GetNameAttribute', function( response ) {
var name = response; //don't forget error checking, ommited
});
});
</script>
Alternatively, you could always write down the values you need into hidden fields, and read them with normal javascript.
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