0

I am trying to convert my Python code into C# code but I got some exceptions during the translation.

What I want is to fetch json/string data from the url. I am new to C# network programming. I tried several ways, read there documents, google their usages, but I still couldn't find out the correct way, as I keep getting the exceptions in the title.

This is my Python code that works:

    url = 'https://c.y.qq.com/soso/fcgi-bin/client_search_cp'
    params = {
        'ct': 24,
        'qqmusic_ver': 1298,
        'new_json': 1,
        'remoteplace':'sizer.yqq.lyric_next',
        'searchid': 63514736641951294,
        'aggr': 1,
        'cr': 1,
        'catZhida': 1,
        'lossless': 0,
        'sem': 1,
        't': 7,
        'p': 1,
        'n': 1,
        'w': keyword,
        'g_tk': 1714057807,
        'loginUin': 0,
        'hostUin': 0,
        'format': 'json',
        'inCharset': 'utf8',
        'outCharset': 'utf-8',
        'notice': 0,
        'platform': 'yqq.json',
        'needNewCode': 0
    }
    headers = {
        'content-type': 'application/json',
        'User-Agent': 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:22.0) Gecko/20100101 Firefox/22.0',
        'referer':'https://y.qq.com/portal/search.html'
    }
    result = requests.get(url, params = params, headers = headers)

This is the C# code that I have tried:

    public static async Task<string> SearchLyrics(string keyword)
    {
        keyword = Uri.EscapeUriString(keyword);
        // method 1
        string uri = $"https://c.y.qq.com/soso/fcgi-bin/client_search_cp?ct=24&qqmusic_ver=1298&new_json=1&remoteplace=sizer.yqq.lyric_next&searchid=63514736641951294&aggr=1&cr=1&catZhida=1&lossless=0&sem=1&t=7&p=1&n=1&w={keyword}&g_tk=1714057807&loginUin=0&hostUin=0&format=json&inCharset=utf8&outCharset=utf-8&notice=0&platform=yqq.json&needNewCode=0";
        using (var client = new HttpClient())
        {
            client.BaseAddress = new Uri(uri);
            client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
            using (var request = new HttpRequestMessage(HttpMethod.Get, uri))
            {
                request.Headers.Add("User-Agent", "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:22.0) Gecko/20100101 Firefox/22.0");
                request.Headers.Add("referer", "https://y.qq.com/portal/search.html");
                var response = await client.SendAsync(request);
                //response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
                return await response.Content.ReadAsStringAsync();
            }
        }
        // method 2
        using (var client = new HttpClient())
        {
            client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
            client.DefaultRequestHeaders.Add("ct", "24");
            client.DefaultRequestHeaders.Add("qqmusic_ver", "1298");
            client.DefaultRequestHeaders.Add("new_json", "1");
            client.DefaultRequestHeaders.Add("remoteplace", "sizer.yqq.lyric_next");
            client.DefaultRequestHeaders.Add("searchid", "63514736641951294");
            client.DefaultRequestHeaders.Add("aggr", "1");
            client.DefaultRequestHeaders.Add("catZhida", "1");
            client.DefaultRequestHeaders.Add("lossless", "0");
            client.DefaultRequestHeaders.Add("t", "7");
            client.DefaultRequestHeaders.Add("p", "1");
            client.DefaultRequestHeaders.Add("n", "1");
            client.DefaultRequestHeaders.Add("w", keyword);
            client.DefaultRequestHeaders.Add("g_tk", "1714057807");
            client.DefaultRequestHeaders.Add("loginUin", "0");
            client.DefaultRequestHeaders.Add("hostUin", "0");
            client.DefaultRequestHeaders.Add("format", "json");
            client.DefaultRequestHeaders.Add("inCharset", "utf8");
            client.DefaultRequestHeaders.Add("outCharset", "utf-8");
            client.DefaultRequestHeaders.Add("notice", "0");
            client.DefaultRequestHeaders.Add("platform", "yqq.json");
            client.DefaultRequestHeaders.Add("needNewCode", "0");
            using (var request = new HttpRequestMessage(HttpMethod.Get, "https://c.y.qq.com/soso/fcgi-bin/client_search_cp"))
            {
                request.Headers.Add("User-Agent", "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:22.0) Gecko/20100101 Firefox/22.0");
                request.Headers.Add("referer", "https://y.qq.com/portal/search.html");
                var response = await client.SendAsync(request);
                //response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
                return await response.Content.ReadAsStringAsync();
            }
        }
    }
Seaky Lone
  • 992
  • 1
  • 10
  • 29
  • You can use free tools like [Fiddler](https://www.telerik.com/download/fiddler-everywhere) to look what your requests actually look like "on the wire" and compare your two program outputs. – nvoigt Mar 28 '20 at 07:21
  • @nvoigt I cannot compare results because I don't know c# network programming. – Seaky Lone Mar 28 '20 at 07:24
  • You don't need to know programming. You run both programs and you will see the http messages they send. Then you can compare the messages and see what is missing from the message sent by your C# program. – nvoigt Mar 28 '20 at 07:25
  • Agree with nvoigt; you use wire shark or fiddler to examine the http request the python makes and the c# makes. You eg realize the difference is that the c# sends referer but the Python changes the case of it to Referer, you change the c# code so it sets Referer, everything works, hooray. It’s not about c# or php even network programming per se; it’s just a “sending foo gets an error, sending bar gets a result, let’s find out why c# sends foo and make sure we send bar” – Caius Jard Mar 28 '20 at 07:30
  • I notice that python maybe has a chance to encode the keyword parameter but c# version it is just concat straight into the url. Are you sure the value of keyword in c# is safe? No invalid chars etc – Caius Jard Mar 28 '20 at 07:39
  • @CaiusJard I am not sure. I might use any utf-8 characters. – Seaky Lone Mar 28 '20 at 07:41
  • I think it would be wise to stick an Encode() around that keyword, at least. Here’s a compare of the various million different ways c# can do it https://stackoverflow.com/questions/575440/url-encoding-using-c-sharp – Caius Jard Mar 28 '20 at 07:49
  • @CaiusJard Thanks I have encoded the `keyword` but it doesn't seem to be the problem. – Seaky Lone Mar 28 '20 at 07:57
  • It wasn't guaranteed to be! Encoding it is wise though, so leave it in. Now, about that wireshark/fiddler thing we mentioned... – Caius Jard Mar 28 '20 at 08:11
  • The method 1 in your post works on my Windows 10 / Net Core 3.0.1 and retrieves results. What are you passing in as the `keyword`? – Oguz Ozgul Mar 28 '20 at 09:20
  • @OguzOzgul Can I see you results? I passed several keywords, eg, "Shake it off". And I am developing a UWP app. I am not sure whether our environments will be a huge difference. – Seaky Lone Mar 28 '20 at 09:28
  • I've passed "On the brink" (I don't know why), and the return is like: `"{\"code\":0,\"data\":{\"keyword\":\"On the brink\",\"lyric\":{\"curnum\":1,\"curpage\":1,\"list\":[{\"action\":{\"alert\":24,\"icons\":9977724,\"msg\":23,\"switch\":1},\"album\":{\"id\":647929,\"mid\":\"000Lw92J481c6A\",\"name\":\"Waking Up (Deluxe Version) [Explicit]\",\"subtitle\":\` – Oguz Ozgul Mar 28 '20 at 09:31
  • On what platform does your UWP app run? And on what platform does the python code run? Can it be that, the IP address where your UWP app run is blacklisted by c.y.qq.com – Oguz Ozgul Mar 28 '20 at 09:33
  • @OguzOzgul Your results look good to me. I don't know why I am getting exceptions in SendAsync. My UWP app and Python code both run on my Win10 computer. – Seaky Lone Mar 28 '20 at 09:34
  • Then install Fiddler (very simple), run it. it will act as an Http Proxy and registers itself to your operating system as such. The your web request will go through it and you can analyze your actual web request with all its headers etc. and will also see if there are any more details in the response, other than 401 error. – Oguz Ozgul Mar 28 '20 at 09:39
  • What the other guys recommend is, first run your UWP app, let Fiddler intercept it, the run your python code and again let fiddler intercept it. You will now have both request. Just compare these two request in a text editor or on fiddler itself to see what is different, – Oguz Ozgul Mar 28 '20 at 09:40
  • You might need to specify the proxy (127.0.0.1: 8888) on python and may be on your UWP app if they don't use the default system settings – Oguz Ozgul Mar 28 '20 at 09:42

1 Answers1

0

The problem is that I didn't enable network access ability for my uwp app. Adding it in the Package.appxmanifest would solve this issue.

My code is right but I have made some improvements according to the Microsoft Document:

public static async Task<string> SearchLyrics(string keyword)
{
    string uri = $"https://c.y.qq.com/soso/fcgi-bin/client_search_cp?ct=24&qqmusic_ver=1298&new_json=1&remoteplace=sizer.yqq.lyric_next&searchid=63514736641951294&aggr=1&cr=1&catZhida=1&lossless=0&sem=1&t=7&p=1&n=1&w={Uri.EscapeUriString(keyword)}&g_tk=1714057807&loginUin=0&hostUin=0&format=json&inCharset=utf8&outCharset=utf-8&notice=0&platform=yqq.json&needNewCode=0";
    using (var client = new HttpClient())
    {
        client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
        client.DefaultRequestHeaders.UserAgent.TryParseAdd("Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:22.0) Gecko/20100101 Firefox/22.0");
        var response = await client.GetAsync(uri);
        response.EnsureSuccessStatusCode();
        var content = await response.Content.ReadAsStringAsync();
        Windows.Data.Json.JsonObject json = Windows.Data.Json.JsonObject.Parse(content);
        return json.GetNamedObject("data").GetNamedObject("lyric").GetNamedArray("list").GetObjectAt(0).GetNamedString("content");
        }
    }
Seaky Lone
  • 992
  • 1
  • 10
  • 29