开发者

Why DataContractJsonSerializer and toSource produces different results?

开发者 https://www.devze.com 2023-04-12 20:33 出处:网络
I need to pass javascript object to ASP.NET MVC and I\'m thinking do it like this: var p = { account:\'123\', page:\'item\' };

I need to pass javascript object to ASP.NET MVC and I'm thinking do it like this:

var p = { account:'123', page:'item' }; 
var message = escape(p.toSource());开发者_如何转开发
// pass message to action method

That produces something like this (unescaped for readability):

({account:"123", page:"item"})

And in ASP.NET MVC I'm trying to deserialize it and fail. First, DataContractJsonSerializer was complaining about parenthesis, no problem with that, removed before passing:

{account:"123", page:"item"}

Then it complained about a instead of ", so I've tried to serialize datacontract using it, and got:

{"account":"123", "page":"item"}

So, question is, can i use something in ASP.NET MVC, that would work with javascripts toSource format, or am I doing it from scratch wrong?


So, question is, can i use something in ASP.NET MVC, that would work with javascripts toSource format, or am I doing it from scratch wrong?

The DataContractJsonSerializer class is pretty strict in terms of JSON format and it adheres to the specification. For example:

{account:"123", page:"item"}

is invalid JSON according to the specification. You must put double quotes around property names. You could use JSON.stringify in order to produce valid JSON:

var p = { account:'123', page:'item' }; 
var message = JSON.stringify(p);

which will produce {"account":"123","page":"item"} which is now valid JSON. The JSON.stringify function is natively built into modern browsers and if you want to support legacy browsers you could include json2.js into your page.

This being said, you could use the less strict JavaScriptSerializer class, or Json.NET which will accept your invalid JSON string:

public class MyModel
{
    public string Account { get; set; }
    public string Page { get; set; }
}

class Program
{
    static void Main()
    {
        var json = "{account:\"123\", page:\"item\"}";
        var serializer = new JavaScriptSerializer();
        var model = serializer.Deserialize<MyModel>(json);
        Console.WriteLine("account = {0}, page = {1}", model.Account, model.Page);
    }
}

And this being said I don't know why you are deserializing manually the JSON instead of relying on the built in JsonValueProviderFactory:

[HttpPost]
public ActionResult MyAction(MyModel model)
{
    ...
}

and to invoke from javascript using AJAX:

$.ajax({
    url: '@Url.Action("MyAction", "Home")',
    type: 'POST',
    contentType: 'application/json',
    data: JSON.stringify({ account: "123", page: "item" }),
    success: function(result) {
        // TODO: process the results
    }
});

See, now you now longer have to worry about any manual serialization/deserialization. Everything is handled by the framework for you.


The .toSource() method does not return JSON. In your case, the valid JSON representation of your object would be:

{"account": 123, "page": "item"}

The format that .toSource() returns is explained in the MDN documentation.

To serialize your objects in your JavaScript, I recommend using a third party library for the most compatibility. Specifically, you could use json2.js. However, if you are using a modern browser, you could also use the .stringify() method of the new JSON object. But, again, the most versatile approach is the third party library.


In case anybody needs it, I've done it like this:

function getSource(o) { var r = [], t; for (var i in o) if (o.hasOwnProperty(i)) { t = i + "~~" + "'" + o[i] + "'"; r.push(t); }; return r.join(); }        

Notice, that it has several limitations/differences from original toSource():

a) my model, that I'm passing is always flat, that means all properties are assumed as strings, if your model has complex properties, you need to change code to use recursion for complex properties.
b) I'm using single quotes, while original toSource uses double quotes.
c) I'm replacing ":" to "~~", because even encoded it was breaking the url, so before serializing on server side, you need to do replace.
d) original toSource was returning result in closures, which i don't needed, so my function returns result without them.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号