要件は、クラスをシリアル化してサーバーに送信します。
開発環境:
MonoDevelop 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クラスによってサーバーに送信されますが、モノマックでは機能しない追加のコード(ハック)があります
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インスタンスを作成し、文字列を使用して作成してみました。
また、構成で次のコードを使用してみました。
<uri>
<schemeSettings>
<clear/>
<add name="http" genericUriParserOptions="DontUnescapePathDotsAndSlashes"/>
</schemeSettings>
</uri>
ただし、どのメソッドも機能せず、リクエストが作成されるとエンコーディングが失われます。
これを機能させるためのアイデアはありがたいです。
アップデート:
サードパーティのオープンソースコードを使用したテストなど、さまざまなことを試しましたが、エンコードされたURLを送信するときに同じ問題が発生しました。
WebRequestの代わりにWebClientを使用するようにコードを変更しましたが、それでもうまくいきません。
したがって、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);
}
}
}
}