skip to Main Content

I am trying a simple display of github repositories. The url “https://api.github.com/search/repositories?q=pluralsight” works in my browser return json and works in fiddler but the following in my .NET Web App is getting a 403 Forbidden error. Can anyone help me understand a fix? My controller is as follows:

public class HomeController : Controller
    {
    public ActionResult Index()
        {
        Tweets model = null;
        var client = new HttpClient();
        var task = client.GetAsync("https://api.github.com/search/repositories?q=pluralsight")
            .ContinueWith((taskwithresponse) =>
            {
                var response = taskwithresponse.Result;
                response.EnsureSuccessStatusCode();
                var readtask = response.Content.ReadAsAsync<Tweets>();
                readtask.Wait();
                model = readtask.Result;

            });
        task.Wait();
        return View(model.results);
        }
    }

I have a class defined as follows (ignore that it is called Tweets) originally was trying to access twitter api.

namespace HttpClientMVCDemo.Controllers
{
public class Tweets
    {
    public Tweet[] results;
    }
public class Tweet
    {
    [JsonProperty("name")]
    public string UserName { get; set; }
    [JsonProperty("id")]
    public string id { get; set; }
    }
}

Code view auto generated based on Amit’s classes below:

@model IEnumerable<HttpClientMVCDemo.Controllers.Gits>

@{
ViewBag.Title = "Index";
}

<h2>Index</h2>

<p>
@Html.ActionLink("Create New", "Create")
</p>
<table class="table">
<tr>
    <th>
        @Html.DisplayNameFor(model => model.total_count)
    </th>
    <th>
        @Html.DisplayNameFor(model => model.incomplete_results)
    </th>
    <th></th>
</tr>

@foreach (var item in Model) {
<tr>
    <td>
        @Html.DisplayFor(modelItem => item.total_count)
    </td>
    <td>
        @Html.DisplayFor(modelItem => item.incomplete_results)
    </td>
    <td>
        @Html.ActionLink("Edit", "Edit", new { /* id=item.PrimaryKey */ }) |
        @Html.ActionLink("Details", "Details", new       { /*id=item.PrimaryKey*/ }) |
        @Html.ActionLink("Delete", "Delete", new { /* id=item.PrimaryKey */ })
    </td>
</tr>
}

3

Answers


  1. Well here are some modification in your model class

    First Json string contain array of items not results

    and you forget to provide get and set propertyin model class.

    So This is new modified model class.

    public class Tweets
        {
            public int total_count { get; set; }
            public bool incomplete_results { get; set; }
            public List<Item> items { get; set; }
        }
    
        public class Item
        {
            public int id { get; set; }
            public string name { get; set; }
            public string full_name { get; set; }
        }
    

    And to get data from that url, You need to add User-Agent header in request.
    And also add this in your web.cofig file

    <system.net>
        <settings>
          <httpWebRequest useUnsafeHeaderParsing="true" />
        </settings>
      </system.net>
    

    So here is complete code.

    Tweets model = null;           
                var client = new HttpClient();
                client.DefaultRequestHeaders.TryAddWithoutValidation("User-Agent", "http://developer.github.com/v3/#user-agent-required");
                var task = client.GetAsync("https://api.github.com/search/repositories?q=pluralsight")
                    .ContinueWith((taskwithresponse) =>
                    {
                        var response = taskwithresponse.Result.Content.ReadAsStringAsync();
                        response.Wait();
                        model = JsonConvert.DeserializeObject<Tweets>(response.Result);
                    });
                task.Wait();
                return View(model.items);
    

    And in your view should accept this type of model

    @model IEnumerable<HttpClientMVCDemo.Controllers.Item>
    
    Login or Signup to reply.
  2. Your browser automatically adds several accept headers to the request. You might have to add the headers in your request to avoid the 403.

     httpClient.DefaultRequestHeaders.TryAddWithoutValidation("Accept", "text/html,application/json");
    

    A similar question is here. The easiest way is to use Fiddler to check your request.

    Furthermore you should not call Wait on your async call. Better declare the action as async and call await client.GetAsync();Otherwise you might get a deadlock. See here.

    Login or Signup to reply.
  3. HTTP 403: Forbidden is thrown because of administrative rules from github site.

    Accessing api(https://api.github.com/) from github site expects ‘User-Agent’ header.

    This can be resolved using below code:

    HttpClient Client = new HttpClient();    
    Client.DefaultRequestHeaders.TryAddWithoutValidation("User-Agent", "http://developer.github.com/v3/#user-agent-required");
    var res = Client.GetAsync("https://api.github.com/search/repositories?q=pluralsight").Result.Content.ReadAsStringAsync().Result;
    

    Refernce:
    https://docs.github.com/en/free-pro-team@latest/rest/overview/resources-in-the-rest-api#user-agent-required

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search