1

My code (intended for searching for steam market items using an API call) is supposed to read the response from an API call into my program and this works great, however, when the API call fails I want to display a separate error message letting the user know that something has gone wrong but currently it will simply crash the code.

An example of a successful API call is:

https://steamcommunity.com/market/priceoverview/?currency=2&appid=730&market_hash_name=Glock-18%20%7C%20Steel%20Disruption%20%28Minimal%20Wear%29

This results in the following;

{"success":true,"lowest_price":"\u00a31.39","volume":"22","median_price":"\u00a31.40"}

So far this works perfectly fine, the problem arises when an incorrect link is used, like this:

https://steamcommunity.com/market/priceoverview/?currency=2&appid=730&market_hash_name=this-skin-does-not-exist

This results in an error like so;

{"success":false}

I want to know when this happens so I can display a message to the user however in my code's current state it simply crashes when this is returned. Here's my current code:

webpage = "https://steamcommunity.com/market/priceoverview/?currency=2&appid=730&market_hash_name=" + Model.category + Model.weapon + " | " + Model.skin + " (" + Model.wear + ")";

System.Net.WebClient wc = new System.Net.WebClient();
byte[] raw = wc.DownloadData(webpage);
string webData = System.Text.Encoding.UTF8.GetString(raw);

if (webData.Substring(11, 1) == "t")
{
    int lowestPos = webData.IndexOf("\"lowest_price\":\"");
    int volumePos = webData.IndexOf("\",\"volume\":\"");
    int medianPos = webData.IndexOf("\",\"median_price\":\"");
    int endPos = webData.IndexOf("\"}");

    Model.lowestPrice = webData.Substring(lowestPos + 16, volumePos - lowestPos - 16);
    if (Model.lowestPrice.IndexOf("\\u00a3") != -1)
    {
        Model.lowestPrice = "£" + Model.lowestPrice.Substring(6);
    }

    Model.medianPrice = webData.Substring(medianPos + 18, endPos - medianPos - 18);
    if (Model.medianPrice.IndexOf("\\u00a3") != -1)
    {
        Model.medianPrice = "£" + Model.medianPrice.Substring(6);
    }

    Model.volume = webData.Substring(volumePos + 12, medianPos - volumePos - 12);
}
else
{
    Console.WriteLine("An error has occurred, please enter a correct skin");
}

The error occurs at byte[] raw = wc.DownloadData(webpage);

Any help would be appreciated :)

DuBzGaMeRz
  • 11
  • 2
  • 1
    How does it "crash"? What is the "error"? – David Aug 28 '20 at 14:05
  • 2
    Because WebClient is obsolete and replaced by HttpClient since 2012. This is one of the reasons - it will *always* throws an exception when a non-success status code is returned, even a 3xx. It's neither thread-safe either – Panagiotis Kanavos Aug 28 '20 at 14:06
  • 1
    Don't use WebClient at all. Use HttpClient instead. A single HttpClient instance can be reused by multiple threads too. Use eg `HttpClient.GetAsync` to retrieve a response and check its `StatusCode` property, [like the example in the docs](https://learn.microsoft.com/en-us/dotnet/api/system.net.http.httpclient?view=netcore-3.1) – Panagiotis Kanavos Aug 28 '20 at 14:09
  • 1
    WebClient was built for the desktop applications of 2002, before HTTP APIs and REST. Its methods are suitable for downloading pages and files and posting to forms. That's why they are called `DownloadString` or `DownloadData` etc, and why some verbs are simply missing. That's why asynchronous operations use events too - they were built to call a Winforms event handler – Panagiotis Kanavos Aug 28 '20 at 14:11
  • Does this answer your question? [WebClient - get response body on error status code](https://stackoverflow.com/questions/15346362/webclient-get-response-body-on-error-status-code) – GSerg Aug 28 '20 at 14:12
  • Thank you all for your help! My code now works as intended. I was not aware that WebClient was so outdated, I'll be sure to remember that for next time. – DuBzGaMeRz Aug 28 '20 at 14:31

1 Answers1

0

Webclient is deprecated and you should consider using HttpClient if possible. Webclient throws an exception. So you should wrap your code inside a try/catch block to catch the exception and react accordingly:

try
{
  System.Net.WebClient wc = new System.Net.WebClient();
  byte[] raw = wc.DownloadData(webpage);
  string webData = System.Text.Encoding.UTF8.GetString(raw);
}
catch(System.Net.WebException e)
{
  //handle the error here
}
BlackBrain
  • 970
  • 6
  • 18