Отправка сериализованного объекта json, содержащего экранированную строку, с использованием HttpWebRequest в моно

Требование сериализовать класс и отправить его на сервер.

Среда разработки:

МоноДевелопмент 3.0.6

Время выполнения: Mono 2.10.9 (tarball)

GTK 2.24.10

GTK# (2.12.0.0)

Операционная система:

Mac OS X 10.7.4

Класс содержит строку с экранированной двойной кавычкой.

class CustomClass
{
    public string foo = "hi!\""; 
}

Проблема в том, что когда я сериализую его, кодирую и создаю объект URI, обратная косая черта, используемая для выхода из двойной кавычки в переменной foo, преобразуется в прямую косую черту, тем самым нарушая json.

Ниже приведены значения различных переменных экземпляра URI.

Uri:
http://myserver/hello_world/0/{"foo":"hi!/""}

AbsoluteUri:
http://myserver/hello_world/0/%7B%22foo%22%3A%22hi%21/%22%22%7D

OriginalString:
http://myserver/hello_world/0/%7B%22foo%22%3A%22hi%21%5C%22%22%7D

HttpWebRequest отправляет значение "http://myserver/hello_world/0/{"foo":"hi!/""}" на сервер, но по моему требованию он должен использовать OriginalString для получения действительного ответа от сервера.

Если я тестирую код на .NET, OriginalString отправляется на сервер классом HttpWebRequest, но есть дополнительный код (хак), который не работает на моно Mac

string paq = requestUri.PathAndQuery;
FieldInfo flagsFieldInfo = typeof(Uri).GetField("m_Flags", BindingFlags.Instance | BindingFlags.NonPublic);
ulong flags = (ulong)flagsFieldInfo.GetValue(requestUri);
flags &= ~((ulong)0x30); // Flags.PathNotCanonical|Flags.QueryNotCanonical
flagsFieldInfo.SetValue(requestUri, flags);

Код :

object messageObject = new CustomClass();

//try 1
//string jsonString = Uri.EscapeUriString(JsonConvert.SerializeObject(message2));

//try 2
//string jsonString = Uri.EscapeDataString(JsonConvert.SerializeObject(message2));

//try 3

string jsonString = System.Web.HttpUtility.UrlEncode(JsonConvert.SerializeObject(messageObject));

Uri uri = new Uri(string.Format("http://myserver/hello_world/0/{0}", jsonString)); 

//try 4:
//HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri.AbsoluteUri);

//try 5
//HttpWebRequest request =(HttpWebRequest)WebRequest.Create(string.Format("http://myserver/hello_world/0/{0}",jsonString));

//try 6
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri.OriginalString);

try
{
    using (HttpWebResponse resp = request.GetResponse() as HttpWebResponse)
    {
        var reader = new StreamReader(resp.GetResponseStream());
        string jsonResponse = reader.ReadToEnd();
    }
} 
catch (WebException wex)
{
    Debug.WriteLine(wex.ToString());
}

Как видите, я пытался использовать Uri.EscapeUriString, Uri.EscapeDataString и System.Web.HttpUtility.UrlEncode, а также использовать AbsouluteUri и OriginalString для создания экземпляра WebRequest, а также создать его с помощью строки.

Я также попытался использовать следующий код в файле config.

<uri>
    <schemeSettings>
        <clear/>
        <add name="http" genericUriParserOptions="DontUnescapePathDotsAndSlashes"/>
    </schemeSettings>
</uri> 

Но ни один из методов не работает, и кодировка теряется при создании запроса.

Любые идеи, чтобы заставить это работать, будут оценены.

Обновление:

Я пробовал много вещей, включая тестирование с некоторым сторонним открытым исходным кодом, но все равно сталкивался с той же проблемой при отправке закодированного URL-адреса.

Я изменил код, чтобы использовать WebClient вместо WebRequest, но все равно не повезло.

Таким образом, решение, которое сработало для меня как на MonoMac, так и на MonoTouch (симулятор, я не тестировал его на устройстве), заключалось в создании запроса с использованием TcpClient.

using (TcpClient tc = new TcpClient()) {
tc.Connect ("myserver", 80);

using (NetworkStream ns = tc.GetStream()) {
    using (System.IO.StreamWriter sw = new System.IO.StreamWriter(ns)) {
                    using (System.IO.StreamReader sr = new System.IO.StreamReader(ns)) {
                        sw.Write("GET /hello_world/0/%7B%22foo%22:%22hi!%5C%22%22%7D HTTP/1.1 Host:myserver \r\n\r\n");
                        sw.Flush ();
                        string line;
                        while ((line=sr.ReadLine())!=null)
                            Console.Write (line);
                    }
                }
            }
        }

person Roger K    schedule 18.02.2013    source источник
comment
Также испытайте такое же поведение на MonoTouch   -  person Roger K    schedule 19.02.2013
comment
Что вам дает foo = @"hi!""";?   -  person ruffin    schedule 19.02.2013
comment
@ruffin, спасибо за ответ. Это дает мне тот же результат в Uri, но отличается AbsoluteUri и OriginalString. HttpWebRequest по-прежнему отправляет значение "http://myserver/hello_world/0/{"foo":"hi!/""}" на сервер URI http://myserver/hello_world/0/{"foo":"hi!/""} OriginalString http://myserver/hello_world/0/%7B%22foo%22%3A%22hi%21%5C%22%22%7D AbsoluteUri http://myserver/hello_world/0/%7B%22foo%22:%22hi!/%22%22%7D.   -  person Roger K    schedule 19.02.2013


Ответы (1)


Я пробовал много вещей, включая тестирование с некоторым сторонним открытым исходным кодом, но все равно сталкивался с той же проблемой при отправке закодированного URL-адреса.

Я изменил код, чтобы использовать WebClient вместо WebRequest, но все равно не повезло.

Таким образом, решение, которое сработало для меня как на MonoMac, так и на MonoTouch (симулятор, я не тестировал его на устройстве), заключалось в создании запроса с использованием TcpClient.

using (TcpClient tc = new TcpClient()) {
tc.Connect ("myserver", 80);

using (NetworkStream ns = tc.GetStream()) {
    using (System.IO.StreamWriter sw = new System.IO.StreamWriter(ns)) {
        using (System.IO.StreamReader sr = new System.IO.StreamReader(ns)) {
            sw.Write("GET /hello_world/0/%7B%22foo%22:%22hi!%5C%22%22%7D HTTP/1.1 Host:myserver \r\n\r\n");
            sw.Flush ();
            string line;
            while ((line=sr.ReadLine())!=null)
                Console.Write (line);
            }
        }
    }
}
person Roger K    schedule 05.10.2016