C#/Blazor

[Blazor] Github API 이용해 Repository 조회하기

kjun.kr 2023. 2. 7. 21:49
728x90
728x170

사용할 Model 추가

SearchResult.cs

using System.Text.Json.Serialization;

namespace Blazor.GitTest.Models
{
    public class SearchResult<T>
    {
        [JsonPropertyName("total_count")]
        public int TotalCount { get; set; }

        [JsonPropertyName("incomplete_results")]
        public bool IncompleteResults { get; set; }

        [JsonPropertyName("items")]
        public List<T> Items { get; set; }
    }
}


Repository.cs

using System.Text.Json.Serialization;

namespace Blazor.GitTest.Models
{
    public class Repository
    {
        [JsonPropertyName("id")]
        public int Id { get; set; }

        [JsonPropertyName("name")]
        public string Name { get; set; }

        [JsonPropertyName("full_name")]
        public string FullName { get; set; }

        [JsonPropertyName("owner")]
        public Owner Owner { get; set; }

        [JsonPropertyName("private")]
        public bool Private { get; set; }

        [JsonPropertyName("html_url")]
        public string HtmlUrl { get; set; }

        [JsonPropertyName("description")]
        public string Description { get; set; }

        [JsonPropertyName("fork")]
        public bool Fork { get; set; }

        [JsonPropertyName("url")]
        public string Url { get; set; }

        [JsonPropertyName("forks_url")]
        public string ForksUrl { get; set; }

        [JsonPropertyName("keys_url")]
        public string KeysUrl { get; set; }

        [JsonPropertyName("collaborators_url")]
        public string CollaboratorsUrl { get; set; }

        [JsonPropertyName("teams_url")]
        public string TeamsUrl { get; set; }

        [JsonPropertyName("hooks_url")]
        public string HooksUrl { get; set; }

        [JsonPropertyName("issue_events_url")]
        public string IssueEventsUrl { get; set; }

        [JsonPropertyName("events_url")]
        public string EventsUrl { get; set; }

        [JsonPropertyName("assignees_url")]
        public string AssigneesUrl { get; set; }

        [JsonPropertyName("branches_url")]
        public string BranchesUrl { get; set; }

        [JsonPropertyName("tags_url")]
        public string TagsUrl { get; set; }

        [JsonPropertyName("blobs_url")]
        public string BlobsUrl { get; set; }

        [JsonPropertyName("git_tags_url")]
        public string GitTagsUrl { get; set; }

        [JsonPropertyName("git_refs_url")]
        public string GitRefsUrl { get; set; }

        [JsonPropertyName("trees_url")]
        public string TreesUrl { get; set; }

        [JsonPropertyName("statuses_url")]
        public string StatusesUrl { get; set; }

        [JsonPropertyName("languages_url")]
        public string LanguagesUrl { get; set; }

        [JsonPropertyName("stargazers_url")]
        public string StargazersUrl { get; set; }

        [JsonPropertyName("contributors_url")]
        public string ContributorsUrl { get; set; }

        [JsonPropertyName("subscribers_url")]
        public string SubscribersUrl { get; set; }

        [JsonPropertyName("subscription_url")]
        public string SubscriptionUrl { get; set; }

        [JsonPropertyName("commits_url")]
        public string CommitsUrl { get; set; }

        [JsonPropertyName("git_commits_url")]
        public string GitCommitsUrl { get; set; }

        [JsonPropertyName("comments_url")]
        public string CommentsUrl { get; set; }

        [JsonPropertyName("issue_comment_url")]
        public string IssueCommentUrl { get; set; }

        [JsonPropertyName("contents_url")]
        public string ContentsUrl { get; set; }

        [JsonPropertyName("compare_url")]
        public string CompareUrl { get; set; }

        [JsonPropertyName("merges_url")]
        public string MergesUrl { get; set; }

        [JsonPropertyName("archive_url")]
        public string ArchiveUrl { get; set; }

        [JsonPropertyName("downloads_url")]
        public string DownloadsUrl { get; set; }

        [JsonPropertyName("issues_url")]
        public string IssuesUrl { get; set; }

        [JsonPropertyName("pulls_url")]
        public string PullsUrl { get; set; }

        [JsonPropertyName("milestones_url")]
        public string MilestonesUrl { get; set; }

        [JsonPropertyName("notifications_url")]
        public string NotificationsUrl { get; set; }

        [JsonPropertyName("labels_url")]
        public string LabelsUrl { get; set; }

        [JsonPropertyName("releases_url")]
        public string ReleasesUrl { get; set; }

        [JsonPropertyName("created_at")]
        public string CreatedAt { get; set; }

        [JsonPropertyName("updated_at")]
        public string UpdatedAt { get; set; }

        [JsonPropertyName("pushed_at")]
        public string PushedAt { get; set; }

        [JsonPropertyName("git_url")]
        public string GitUrl { get; set; }

        [JsonPropertyName("ssh_url")]
        public string SshUrl { get; set; }

        [JsonPropertyName("clone_url")]
        public string CloneUrl { get; set; }

        [JsonPropertyName("svn_url")]
        public string SvnUrl { get; set; }

        [JsonPropertyName("homepage")]
        public object Homepage { get; set; }

        [JsonPropertyName("size")]
        public int Size { get; set; }

        [JsonPropertyName("stargazers_count")]
        public int StargazersCount { get; set; }

        [JsonPropertyName("watchers_count")]
        public int WatchersCount { get; set; }

        [JsonPropertyName("language")]
        public object Language { get; set; }

        [JsonPropertyName("has_issues")]
        public bool HasIssues { get; set; }

        [JsonPropertyName("has_downloads")]
        public bool HasDownloads { get; set; }

        [JsonPropertyName("has_wiki")]
        public bool HasWiki { get; set; }

        [JsonPropertyName("has_pages")]
        public bool HasPages { get; set; }

        [JsonPropertyName("forks_count")]
        public int ForksCount { get; set; }

        [JsonPropertyName("mirror_url")]
        public object MirrorUrl { get; set; }

        [JsonPropertyName("open_issues_count")]
        public int OpenIssuesCount { get; set; }

        [JsonPropertyName("forks")]
        public int Forks { get; set; }

        [JsonPropertyName("open_issues")]
        public int OpenIssues { get; set; }

        [JsonPropertyName("watchers")]
        public int Watchers { get; set; }

        [JsonPropertyName("default_branch")]
        public string DefaultBranch { get; set; }

        [JsonPropertyName("organization")]
        public Organization Organization { get; set; }

        [JsonPropertyName("network_count")]
        public int NetworkCount { get; set; }

        [JsonPropertyName("subscribers_count")]
        public int SubscribersCount { get; set; }
    }
}


GitHubClient.cs 추가

using System.Net.Http.Headers;
using System.Net.Http.Json;

using Blazor.GitTest.Models;

namespace Blazor.GitTest
{
    public class GitHubClient
    {
        public HttpClient HttpClient { get; }

        public GitHubClient(HttpClient httpClient)
        {
            httpClient.BaseAddress = new Uri("https://api.github.com/");

            httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/vnd.github.v3+json"));
            httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/vnd.github.mercy-preview+json"));

            httpClient.DefaultRequestHeaders.UserAgent.Add(new ProductInfoHeaderValue("GitHubClient", "1.0.0"));

            HttpClient = httpClient;
        }

        public async Task<SearchResult<Repository>> SearchRepositories(string text, int? page = null, int? pageSize = null)
        {
            var encoded = Uri.EscapeDataString(text);
            var url = $"search/repositories?q={encoded}";

            if (page > 0)
                url += $"&page={page}";

            if (pageSize > 0)
                url += $"&per_page={pageSize}";

            var result = await HttpClient.GetFromJsonAsync<SearchResult<Repository>>(url);

            return result;
        }
    }
}


Program.cs 에서 GitHubClient 주입

builder.Services.AddScoped<GitHubClient>();


FetchData.razor 화면 처리

@page "/fetchdata"
@using Blazor.GitTest.Models;
@inject HttpClient Http
@inject GitHubClient GitHubClient

<PageTitle>Weather forecast</PageTitle>

<h1>Search Github 'keisoft'</h1>

@if (repositoryList == null)
{
    <p><em>Loading...</em></p>
}
else
{
    <table class="table">
        <thead>
            <tr>
                <th>FullName</th>
                <th>Description</th>
                <th>Statistics</th>
            </tr>
        </thead>
        <tbody>
            @foreach (var repo in repositoryList)
            {
                <tr>
                    <td><div class="github-title">@repo.FullName</div></td>
                    <td><div class="github-description">@repo.Description</div></td>
                    <td>
                        <div class="github-statistics">
                            <div class="github-forks"> @repo.ForksCount Forks</div>
                            <div class="github-stargazers"> @repo.StargazersCount Stars</div>
                            <div class="github-watchers"> @repo.SubscribersCount Watchers</div>
                        </div>
                    </td>
                </tr>
            }
        </tbody>
    </table>
}

@code {
    private List<Repository>? repositoryList;

    protected override async Task OnInitializedAsync()
    {
        var result = await GitHubClient.SearchRepositories("keisoft", 1, 20);

        repositoryList = result.Items;
    }
}

 

wwwroot/css/app.css 에 Github Style  추가

/* GitHub */
.github-repository {
    padding-top: 4px;
    padding-bottom: 3px;
}

.github-avatar {
    float: left;
    width: 60px;
    margin-right: 10px;
}

    .github-avatar img {
        width: 100%;
        height: auto;
        border-radius: 2px;
    }

.github-meta {
    margin-left: 70px;
}

.github-title {
    color: black;
    font-weight: 700;
    word-wrap: break-word;
    line-height: 1.1;
    margin-bottom: 4px;
}

.github-description {
    font-size: 13px;
    color: #777;
    margin-top: 4px;
}

.github-forks,
.github-stargazers,
.github-watchers {
    display: inline-block;
    color: #aaa;
    font-size: 11px;
}

.github-forks,
.github-stargazers {
    margin-right: 1em;
}


결과

* 추후 paging 기능을 처리하기 위해 page 관련 필드 및 인자가 추가되 있는 상태입니다.

[Source]
https://github.com/kei-soft/Blazor.AppTest/tree/master/Blazor.GitTest

 

GitHub - kei-soft/Blazor.AppTest

Contribute to kei-soft/Blazor.AppTest development by creating an account on GitHub.

github.com

 

728x90
그리드형