Почему DataContractJsonSerializer и toSource дают разные результаты? - PullRequest
3 голосов
/ 14 октября 2011

Мне нужно передать объект javascript в ASP.NET MVC, и я думаю сделать это так:

var p = { account:'123', page:'item' }; 
var message = escape(p.toSource());
// pass message to action method

Это выдает что-то вроде этого (без возможности чтения):

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

А в ASP.NET MVC я пытаюсь десериализовать его и потерпеть неудачу. Во-первых, DataContractJsonSerializer жаловался на круглые скобки, никаких проблем с этим не было, перед передачей:

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

Тогда он пожаловался на «вместо», поэтому я попытался сериализовать datacontract, используя его, и получил:

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

Итак, вопрос в том, могу ли я использовать что-то в ASP.NET MVC, которое будет работать с javascripts в формате Source, или я делаю это с нуля неправильно?

Ответы [ 3 ]

3 голосов
/ 14 октября 2011

Итак, вопрос в том, могу ли я использовать что-то в ASP.NET MVC, чтобы это работало с javascripts в формате источника, или я делаю это с нуля неправильно?

Класс DataContractJsonSerializer довольно строг с точки зрения формата JSON и соответствует спецификации. Например:

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

является недействительным JSON в соответствии со спецификацией. Вы должны поставить двойные кавычки вокруг имен свойств. Вы можете использовать JSON.stringify, чтобы получить действительный JSON:

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

, который выдаст {"account":"123","page":"item"}, который теперь является действительным JSON. Функция JSON.stringify изначально встроена в современные браузеры, и если вы хотите поддерживать устаревшие браузеры, вы можете включить json2.js на свою страницу.

При этом вы можете использовать менее строгий JavaScriptSerializer класс или Json.NET , который примет вашу недопустимую строку JSON:

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);
    }
}

И как говорится, я не знаю, почему вы десериализуете JSON вручную вместо того, чтобы полагаться на встроенный JsonValueProviderFactory :

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

и для вызова из JavaScript с использованием 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
    }
});

Видите, теперь вам больше не нужно беспокоиться о какой-либо ручной сериализации / десериализации. Все обрабатывается фреймворком для вас.

1 голос
/ 14 октября 2011

Метод .toSource() не возвращает JSON. В вашем случае, допустимое JSON-представление вашего объекта будет:

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

Формат, который возвращает .toSource(), поясняется в документации MDN .

Чтобы сериализовать ваши объекты в вашем JavaScript, я рекомендую использовать стороннюю библиотеку для большей совместимости. В частности, вы можете использовать json2.js . Однако, если вы используете современный браузер, вы также можете использовать метод .stringify() нового объекта JSON . Но, опять же, наиболее универсальным подходом является сторонняя библиотека.

0 голосов
/ 17 октября 2011

Если кому-то это нужно, я сделал это так:

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(); }        

Обратите внимание, что у него есть несколько ограничений / отличий от оригинала toSource ():

a) myМодель, которую я передаю, всегда плоская, это означает, что все свойства предполагаются как строки. Если ваша модель имеет сложные свойства, вам нужно изменить код, чтобы использовать рекурсию для сложных свойств.
b) Я использую одинарные кавычки, в то время как оригинальный toSource использует двойные кавычки.
c) Я заменяю ":" на "~~", потому что даже в кодировке это нарушало URL, поэтому перед сериализацией на стороне сервера вам нужно заменить.
d) оригинальный toSource возвращал результат в замыканиях, которые мне не нужны, поэтому моя функция возвращает результат без них.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...