0

For the past 5 hours I've been trying to get JSON data from an API that requires login using .net C#. Every combination I try results in "error 401 - unauthorized". I have a working example in Javascript, maybe this would help.

       function signin(){
        username = $('#inputUsername').val();
        pass = $('#inputPassword').val();
        if(pass.length > 0 && username.length > 0){
            //Build post request
            $.post( source+"/login", {username: username, password:pass}, function( data, textStatus, jqxhr ) {
                $("header div h4#header_username").html(username);
                token = data.auth;
                $('#main-content').show()
                $('#form-signin').hide()
                populateVehicles();
            });
        }
    }

On c# I've tried many code combinations including:

NetworkCredential netCredential = new NetworkCredential("USERNAME", "PASSWORD");

        HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
        request.Credentials = netCredential;
        request.Method = "POST";
        String encoded = System.Convert.ToBase64String(System.Text.Encoding.GetEncoding("ISO-8859-1").GetBytes("USERNAME" + ":" + "PASSWORD"));
        //request.PreAuthenticate = false;
        //request.Proxy.Credentials = CredentialCache.DefaultCredentials;
        //request.UseDefaultCredentials = true;

        //string base64Credentials = GetEncodedCredentials();
        //request.Headers.Add("Authorization", "Basic " + base64Credentials);
        try
        {
            WebResponse response = request.GetResponse();
            using (Stream responseStream = response.GetResponseStream())
            {
                StreamReader reader = new StreamReader(responseStream, System.Text.Encoding.UTF8);
                return reader.ReadToEnd();
            }
        }
        catch (WebException ex)
        {
            WebResponse errorResponse = ex.Response;
            using (Stream responseStream = errorResponse.GetResponseStream())
            {
                StreamReader reader = new StreamReader(responseStream, System.Text.Encoding.GetEncoding("utf-8"));
                String errorText = reader.ReadToEnd();
                // log errorText
            }
            throw;
        }
    }

Some of the code has "//" because I've tried various variations.

I'm clueless.

Thanks in advance!

  • The Javascript version just passes the username and password as post data. I'm not sure what the NetworkCredential class is for, but I'm guessing you just want to post the data to /login without trying to use that. Just pass it as a plain object (`JsonConvert.SerializeObject()`), exactly like you do in Javasacript – Reinstate Monica Cellio Jul 24 '18 at 19:51
  • Thank you. Could you please add an example code? I've tried doing it and I'm running into trouble. not sure what lines to keep and what to delete. Thanks. – user10129875 Jul 24 '18 at 21:16
  • https://stackoverflow.com/questions/4015324/how-to-make-http-post-web-request – Reinstate Monica Cellio Jul 24 '18 at 21:24

2 Answers2

0

Using doetnet core 2.1, here's a basic example. I checked jquery docs and I think your js example sends form encoded data. You can easily check that in your browsers developer tools > network tab.

Form Encoded

        using (var client = new HttpClient())
        {
            var response = await client.PostAsync("https://myaddress.com/path", new FormUrlEncodedContent(new Dictionary<string, string>()
            {
                { "username", "user" },
                { "password", "mypass" }
            }));

            if (response.StatusCode == HttpStatusCode.OK)
            {
                var responseString = await response.Content.ReadAsStringAsync();
                // do something
            }
        }

"form url encoded" means, it will generate a request that looks like this:

 say=Hi&to=Mom

with header Content-Type: application/x-www-form-urlencoded

s.a. https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST

Json Content

        using (var client = new HttpClient())
        {
            var response = await client.PostAsync("https://myaddress.com/path", new StringContent(JsonConvert.SerializeObject(new
            {
                username = "user",
                password = "password"
            }), Encoding.UTF8, "application/json"));

            if (response.StatusCode == HttpStatusCode.OK)
            {
                var responseString = await response.Content.ReadAsStringAsync();
                // do something
            }
        }

"json" means, it will generate a request, that looks like this

 { "say": "Hi", "to": "Mom" }

with header Content-Type: application/json

Note that HttpClient is thread safe and you should prefer a single instance if you do multiple requests.

If your're on dotnet core the following article will help you getting started with HttpClient: https://learn.microsoft.com/en-us/aspnet/core/fundamentals/http-requests?view=aspnetcore-2.1

See https://stackoverflow.com/a/4015346/2085502 mentioned by @Archer to get an overview over different http client libs in c#.

Christoph Lütjen
  • 5,403
  • 2
  • 24
  • 33
  • I get "Method Not Allowed" and not the JSON file. What am I doing wrong? :| – user10129875 Jul 24 '18 at 20:48
  • "Method not allowed" should be the answer of the server. "method" is the "POST/GET/.." info in a request. So here it should mean: Your are not allowed to send a POST message to this path. Due to the fact that your js example uses post and works, I guess you're using the wrong url. I'd double check the request object in debugger. – Christoph Lütjen Jul 25 '18 at 10:09
-1
  1. To troubleshot if your backend working properly, check it by try sumbit the form with real usename and password and wrong email/password by clicking inside the . username and password must be inside the form too. Also in your form must be have action="" attribute with value of login url.
  2. Try to set up, if login success some word. example, simply print 'success'
  3. Then if failed, print another message. example 'failed', 'wrong password', 'email not exist' aor etc.

So after that. use this Javascript code.

function signin(){

   var formData      = new FormData();
     formData.append('userame', document.getElementById('inputUsername').value);
     formData.append('password', document.getElementById('inputPassword').value);
     var xhr = new XMLHttpRequest();
     xhr.open('POST', 'https://www.yoursite.com/login-url-here', true);
     xhr.onreadystatechange = function() {
          if (xhr.readyState === 4){
                    var data = xhr.responseText;

                    if(data){
                       if(data == 'success'){
                          // yes your login page return success, do something below
                          document.getElementById('main-content').style.display = 'block';
                          document.getElementById('form-signin').style.display = 'none';
                          populateVehicles();
                          alert('login success')
                       } else {
                           alert('ops, failed to login, the page print this messages '+ data)
                       }
                    } else {
                       alert('ops your login page not print anything')
                    }
          }
     }
     xhr.send(formData);

}