diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..7e0ba8b
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,3 @@
+obj
+bin
+.vs
diff --git a/FrostSDK.Example/FrostSDK.Example.csproj b/FrostSDK.Example/FrostSDK.Example.csproj
new file mode 100644
index 0000000..eb25ca8
--- /dev/null
+++ b/FrostSDK.Example/FrostSDK.Example.csproj
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+ Exe
+ netcoreapp2.0
+ 7.1
+
+
+
diff --git a/FrostSDK.Example/Program.cs b/FrostSDK.Example/Program.cs
new file mode 100644
index 0000000..b327995
--- /dev/null
+++ b/FrostSDK.Example/Program.cs
@@ -0,0 +1,37 @@
+using System;
+using System.Collections.Generic;
+using System.Net.Http;
+using System.Threading.Tasks;
+
+namespace FrostSDK.Example
+{
+ class Program
+ {
+ static async Task Main(string[] args)
+ {
+ var apiUrl = "http://localhost:8000";
+ var accessToken = "set_your_access_token";
+
+ var requester = new HttpApiRequester(apiUrl);
+
+ while (true)
+ {
+ Console.Write("投稿内容(exit=終了) > ");
+ var text = Console.ReadLine();
+ if (text == "exit") break;
+
+ Console.Write("ポストを投稿しています...");
+ var res = await requester.RequestAsync(HttpMethod.Post, "/posts/post_status", accessToken, new Dictionary { ["text"] = text + text });
+ if (res.StatusCode == 200)
+ {
+ Console.WriteLine("成功しました!");
+ }
+ else
+ {
+ Console.WriteLine("失敗しました。。");
+ Console.WriteLine(res.ContentJson);
+ }
+ }
+ }
+ }
+}
diff --git a/FrostSDK/ApiResponse.cs b/FrostSDK/ApiResponse.cs
new file mode 100644
index 0000000..e94d840
--- /dev/null
+++ b/FrostSDK/ApiResponse.cs
@@ -0,0 +1,14 @@
+namespace FrostSDK
+{
+ public class ApiResponse
+ {
+ public ApiResponse(int statusCode, string contentJson = null)
+ {
+ StatusCode = statusCode;
+ ContentJson = contentJson;
+ }
+
+ public int StatusCode { get; set; }
+ public string ContentJson { get; set; }
+ }
+}
diff --git a/FrostSDK/FrostSDK.csproj b/FrostSDK/FrostSDK.csproj
new file mode 100644
index 0000000..afada82
--- /dev/null
+++ b/FrostSDK/FrostSDK.csproj
@@ -0,0 +1,11 @@
+
+
+
+ netstandard2.0
+
+
+
+
+
+
+
diff --git a/FrostSDK/HttpApiRequester.cs b/FrostSDK/HttpApiRequester.cs
new file mode 100644
index 0000000..cc4c921
--- /dev/null
+++ b/FrostSDK/HttpApiRequester.cs
@@ -0,0 +1,66 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Net.Http;
+using System.Threading.Tasks;
+using System.Web;
+
+namespace FrostSDK
+{
+ public class HttpApiRequester : IApiRequester
+ {
+ public HttpApiRequester(string apiUrl, HttpClient httpClient = null)
+ {
+ ApiUrl = new Uri(apiUrl);
+ _HttpHandler = new HttpClientHandler { UseCookies = false };
+ _Http = httpClient ?? new HttpClient(_HttpHandler);
+ }
+
+ private HttpClient _Http { get; set; }
+ private HttpClientHandler _HttpHandler { get; set; }
+ public Uri ApiUrl { get; set; }
+
+ public async Task RequestAsync(HttpMethod method, string endpoint, string accessToken, Dictionary parameters = null, Dictionary headers = null)
+ {
+ var bodyMode = method != HttpMethod.Get && method != HttpMethod.Head;
+
+ parameters = parameters ?? new Dictionary();
+ headers = headers ?? new Dictionary();
+
+ var query = "";
+
+ if (!bodyMode)
+ {
+ var queryPairs = parameters.Select(p => HttpUtility.UrlEncode(p.Key) + "=" + HttpUtility.UrlEncode(p.Value));
+ var queryContent = string.Join("&", queryPairs);
+ query = "?" + queryContent;
+ }
+
+ if (endpoint[0] == '/')
+ endpoint = endpoint.Remove(0, 1);
+
+ var request = new HttpRequestMessage(method, ApiUrl + endpoint + query);
+ foreach(var header in headers)
+ {
+ request.Headers.Add(header.Key, header.Value);
+ }
+ request.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", accessToken);
+ if (bodyMode)
+ {
+ var bodyJson = Newtonsoft.Json.JsonConvert.SerializeObject(parameters);
+ request.Content = new StringContent(bodyJson);
+ request.Content.Headers.ContentType.MediaType = "application/json";
+ }
+
+ var response = await _Http.SendAsync(request);
+ var responseJson = await response.Content.ReadAsStringAsync();
+
+ if (response.Content.Headers.ContentType.MediaType.ToLower() != "application/json")
+ {
+ throw new Exception("response is not json format");
+ }
+
+ return new ApiResponse((int)response.StatusCode, responseJson);
+ }
+ }
+}
diff --git a/FrostSDK/IApiRequester.cs b/FrostSDK/IApiRequester.cs
new file mode 100644
index 0000000..9c5aa27
--- /dev/null
+++ b/FrostSDK/IApiRequester.cs
@@ -0,0 +1,11 @@
+using System.Collections.Generic;
+using System.Net.Http;
+using System.Threading.Tasks;
+
+namespace FrostSDK
+{
+ public interface IApiRequester
+ {
+ Task RequestAsync(HttpMethod method, string endpoint, string accessToken, Dictionary parameters = null, Dictionary headers = null);
+ }
+}
diff --git a/frost-sdk-dotnet.sln b/frost-sdk-dotnet.sln
new file mode 100644
index 0000000..a744348
--- /dev/null
+++ b/frost-sdk-dotnet.sln
@@ -0,0 +1,53 @@
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 15
+VisualStudioVersion = 15.0.26124.0
+MinimumVisualStudioVersion = 15.0.26124.0
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FrostSDK", "FrostSDK\FrostSDK.csproj", "{53785701-9DCE-403A-A480-4E8CA8FCB1B1}"
+ ProjectSection(ProjectDependencies) = postProject
+ {9F5C6FAE-0E72-4497-B672-705912539D91} = {9F5C6FAE-0E72-4497-B672-705912539D91}
+ EndProjectSection
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FrostSDK.Example", "FrostSDK.Example\FrostSDK.Example.csproj", "{9F5C6FAE-0E72-4497-B672-705912539D91}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Debug|x64 = Debug|x64
+ Debug|x86 = Debug|x86
+ Release|Any CPU = Release|Any CPU
+ Release|x64 = Release|x64
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {53785701-9DCE-403A-A480-4E8CA8FCB1B1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {53785701-9DCE-403A-A480-4E8CA8FCB1B1}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {53785701-9DCE-403A-A480-4E8CA8FCB1B1}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {53785701-9DCE-403A-A480-4E8CA8FCB1B1}.Debug|x64.Build.0 = Debug|Any CPU
+ {53785701-9DCE-403A-A480-4E8CA8FCB1B1}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {53785701-9DCE-403A-A480-4E8CA8FCB1B1}.Debug|x86.Build.0 = Debug|Any CPU
+ {53785701-9DCE-403A-A480-4E8CA8FCB1B1}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {53785701-9DCE-403A-A480-4E8CA8FCB1B1}.Release|Any CPU.Build.0 = Release|Any CPU
+ {53785701-9DCE-403A-A480-4E8CA8FCB1B1}.Release|x64.ActiveCfg = Release|Any CPU
+ {53785701-9DCE-403A-A480-4E8CA8FCB1B1}.Release|x64.Build.0 = Release|Any CPU
+ {53785701-9DCE-403A-A480-4E8CA8FCB1B1}.Release|x86.ActiveCfg = Release|Any CPU
+ {53785701-9DCE-403A-A480-4E8CA8FCB1B1}.Release|x86.Build.0 = Release|Any CPU
+ {9F5C6FAE-0E72-4497-B672-705912539D91}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {9F5C6FAE-0E72-4497-B672-705912539D91}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {9F5C6FAE-0E72-4497-B672-705912539D91}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {9F5C6FAE-0E72-4497-B672-705912539D91}.Debug|x64.Build.0 = Debug|Any CPU
+ {9F5C6FAE-0E72-4497-B672-705912539D91}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {9F5C6FAE-0E72-4497-B672-705912539D91}.Debug|x86.Build.0 = Debug|Any CPU
+ {9F5C6FAE-0E72-4497-B672-705912539D91}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {9F5C6FAE-0E72-4497-B672-705912539D91}.Release|Any CPU.Build.0 = Release|Any CPU
+ {9F5C6FAE-0E72-4497-B672-705912539D91}.Release|x64.ActiveCfg = Release|Any CPU
+ {9F5C6FAE-0E72-4497-B672-705912539D91}.Release|x64.Build.0 = Release|Any CPU
+ {9F5C6FAE-0E72-4497-B672-705912539D91}.Release|x86.ActiveCfg = Release|Any CPU
+ {9F5C6FAE-0E72-4497-B672-705912539D91}.Release|x86.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {E11D9B07-54AB-4CFD-9CC1-1B5E49EF8E25}
+ EndGlobalSection
+EndGlobal