ASMX web方法接收参数JSON中未转义的双引号

时间:2022-09-15 16:21:48

My HTTP REQUEST contains a valid JSON string having the double quote in the middle of the name "jo\"hn" escaped as seen here (captured by Fiddler Web Debugger)

我的HTTP请求包含一个有效的JSON字符串,在名称“jo\”hn”中间有双引号,如这里所示(被Fiddler Web调试器捕获)

{"name":"firstName","value":"jo\"hn"},

Note: The request submission process uses the standard jQuery $.ajax(..) call as seen in this article without issue.

注意:请求提交过程使用标准的jQuery $.ajax(.. .)调用,如本文中所示,没有问题。


Server side issue

My C# ASMX web service method receives the following C# string value that has the middle double quote unescaped (i.e. backslash has been removed). This cannot be deserialized without causing the error seen below.

我的c# ASMX web服务方法接收以下c#字符串值,其中中间的双引号没有转义(即反斜杠已被删除)。如果不导致下面看到的错误,就无法对其进行反序列化。

This is where the disjoint in the process happens, before I receive the value into my web method. It's as if ASP.NET is processing the string internally by unescaping it and putting it back together with no escapes, altering the original value instead of providing it verbatim to the web method parameter.

在我将值接收到web方法之前,这就是过程中出现的脱节。好像是ASP。NET正在内部处理字符串,方法是取消转义并将其重新组合在一起,不使用转义,更改原始值,而不是将其逐字提供给web方法参数。

C# String is:

c#字符串:

{"name":"firstName","value":"jo"hn"},

The ASMX Web method is roughly:

ASMX Web方法大致是:

using System.Web.Script.Serialization;
using System.Web.Script.Services;

[WebMethod]
[ScriptMethod(ResponseFormat = System.Web.Script.Services.ResponseFormat.Json)]
public string saveData(string values)
{
    JavaScriptSerializer json = new JavaScriptSerializer();
    request = json.Deserialize<List<NameValuePair>>(values.ToString());
                // ^^^ KABOOM! 

The exception message understandably is:

可以理解的例外信息是:

{"Invalid object passed in, ':' or '}' expected. (423): [{\"name\":\"plc$lt$zoneHeaderTopNav$searchBoxTopNav$txtWord\",\"value\":\"\"},{\"name\":\"salutation\",\"value\":\"Mr\"},{\"name\":\"firstName\",\"value\":\"joh\"n\"},{\"name\":\"lastName\",\"value\":\"smith\"},{\"name\":\"initial\",\"value\":\"d\"}]"}

{“无效的对象传入”,“或”预期。(423):[{ \“\”,\“plc lt zoneHeaderTopNav searchBoxTopNav美元美元txtWord \”,\“价值\”,\“\”},{ \“\”:\“称呼\”,\“价值\”,\“\先生”},{ \“\”:\“firstName \”,\“价值\”,\“乔\ n \”},{ \“\”:\“lastName \”,\“价值\”,\“史密斯\”},{ \“\”:\“初始\”,\“价值\”,\“d \”}]" }

How do I best go about solving this problem without changing away from classic ASMX web services?

如何在不改变传统ASMX web服务的情况下最好地解决这个问题?

I might consider a front handler that cleans up the incoming request, or maybe running a string cleanup at the beginning of the web service method. Maybe a different JSON library.

我可以考虑使用前端处理程序来清理传入的请求,或者在web服务方法的开头运行字符串清理。也许是另一个JSON库。

However I wonder if there is an easy answer: tweak configuration, use an Attribute, a setting or overload method that might solve the problem?

但是,我想知道是否有一个简单的答案:微调配置、使用属性、设置或重载方法来解决这个问题?

I've done quite a bit of poking around the Internet but most articles cover returning JSON data from the server to the client and dealing with issues in that area.

我已经在Internet上做了很多探索,但是大多数文章都涉及从服务器返回JSON数据到客户端以及处理该领域的问题。


Addendum Note: full client-side call details requested by Darin Dimitrov

补充说明:达林·迪米特洛夫请求的完整客户端调用详细信息

UPDATE: Darin's Answer posted here inline, for easy reference

function SaveDraft() {

    $.checklist.checkvalid();
    var formObj = $(':input:not([type=hidden])').serializeArray();

    var request = JSON.stringify(formObj);
    request = request.replace(/'/g, "");

    $.ajax({
        url: "/Service.asmx/saveData",
        type: "POST",

        // *** Original erroneous line: uses string concat - commented out
        // data: "{'values':'" + request + "'}",

        // *** CORRECTED LINE: provides an object instead of a string and calls JSON stringify.
        data: JSON.stringify({ values: request }), 

        dataType: "json",
        contentType: "application/json; charset=utf-8",
        success: SaveDraftSuccess,
        error: SaveDraftFail
    });
}

Note: This is the embodiment of the call that produces the valid JSON fragment shown at the top of the question.

注意:这是在问题的顶部生成有效的JSON片段的调用的实施例。

1 个解决方案

#1


3  

Why are you doing this horrible manual JSON deserialization in your web service? Let me suggest you a far better approach.

为什么要在web服务中执行这种可怕的手工JSON反序列化?我建议你一个更好的办法。

Start by defining a model:

首先定义一个模型:

public class Person
{
    public string Name { get; set; }
    public string Value { get; set; }
}

then a web method:

然后web方法:

[WebMethod]
[ScriptMethod]
public string SaveData(Person person)
{
    ...
}

and then you could invoke it from javascript. For example using jQuery:

然后你可以从javascript调用它。例如使用jQuery:

$.ajax({
    url: 'foo.asmx/SaveData',
    type: 'POST',
    contentType: 'application/json',
    data: JSON.stringify({
        person: {
            name: 'firstName',
            value: ' jo\"h\'n'
        }
    }),
    success: function(result) {
        alert(result.d);
    }
});

No kabooms anymore.

没有大爆炸了。

The JSON.stringify method shown here is built-in modern browsers but if you need to support legacy browsers you could include the json2.js script to your page.

JSON。这里显示的stringify方法是内置的现代浏览器,但是如果需要支持遗留浏览器,可以包括json2。js脚本到您的页面。


UPDATE:

更新:

Now that you have shown your code it seems that you are not encoding your request. Try like this:

现在您已经显示了您的代码,似乎您没有对您的请求进行编码。试试这样:

var formObj = $(':input:not([type=hidden])').serializeArray();
var request = JSON.stringify(formObj);
$.ajax({
    url: "/Service.asmx/saveData",
    type: "POST",
    data: JSON.stringify({ values: request }),
    dataType: "json",
    contentType: "application/json; charset=utf-8",
    success: SaveDraftSuccess,
    error: SaveDraftFail
});

Things to notice: you don't need regeular expressions to remove single quotes and you should use JSON.stringify to properly encode your request values.

注意事项:不需要regeular表达式来删除单引号,应该使用JSON。stringify正确地编码您的请求值。

#1


3  

Why are you doing this horrible manual JSON deserialization in your web service? Let me suggest you a far better approach.

为什么要在web服务中执行这种可怕的手工JSON反序列化?我建议你一个更好的办法。

Start by defining a model:

首先定义一个模型:

public class Person
{
    public string Name { get; set; }
    public string Value { get; set; }
}

then a web method:

然后web方法:

[WebMethod]
[ScriptMethod]
public string SaveData(Person person)
{
    ...
}

and then you could invoke it from javascript. For example using jQuery:

然后你可以从javascript调用它。例如使用jQuery:

$.ajax({
    url: 'foo.asmx/SaveData',
    type: 'POST',
    contentType: 'application/json',
    data: JSON.stringify({
        person: {
            name: 'firstName',
            value: ' jo\"h\'n'
        }
    }),
    success: function(result) {
        alert(result.d);
    }
});

No kabooms anymore.

没有大爆炸了。

The JSON.stringify method shown here is built-in modern browsers but if you need to support legacy browsers you could include the json2.js script to your page.

JSON。这里显示的stringify方法是内置的现代浏览器,但是如果需要支持遗留浏览器,可以包括json2。js脚本到您的页面。


UPDATE:

更新:

Now that you have shown your code it seems that you are not encoding your request. Try like this:

现在您已经显示了您的代码,似乎您没有对您的请求进行编码。试试这样:

var formObj = $(':input:not([type=hidden])').serializeArray();
var request = JSON.stringify(formObj);
$.ajax({
    url: "/Service.asmx/saveData",
    type: "POST",
    data: JSON.stringify({ values: request }),
    dataType: "json",
    contentType: "application/json; charset=utf-8",
    success: SaveDraftSuccess,
    error: SaveDraftFail
});

Things to notice: you don't need regeular expressions to remove single quotes and you should use JSON.stringify to properly encode your request values.

注意事项:不需要regeular表达式来删除单引号,应该使用JSON。stringify正确地编码您的请求值。