첨부 실행 코드는 나눔고딕코딩 폰트를 사용합니다.
728x90
반응형
728x170

TestSolution.zip
0.01MB

[TestServer 프로젝트]

▶ Properteis/launchSettings.json

{
    "$schema"     : "http://json.schemastore.org/launchsettings.json",
    "iisSettings" :
    {
        "windowsAuthentication"   : false,
        "anonymousAuthentication" : true,
        "iisExpress"              :
        {
            "applicationUrl" : "http://localhost:41483",
            "sslPort"        : 44362
        }
    },
    "profiles" :
    {
        "IIS Express" :
        {
            "commandName"          : "IISExpress",
            "launchBrowser"        : true,
            "launchUrl"            : "swagger",
            "environmentVariables" :
            {
                "ASPNETCORE_ENVIRONMENT" : "Development"
            }
        },
        "TestServer" :
        {
            "commandName"          : "Project",
            "dotnetRunMessages"    : "true",
            "launchBrowser"        : true,
            "launchUrl"            : "swagger",
            "applicationUrl"       : "https://localhost:5001;http://localhost:5000",
            "environmentVariables" :
            {
                "ASPNETCORE_ENVIRONMENT" : "Development"
            }
        }
    }
}

 

▶ appsettings.json

{
    "Logging" :
    {
        "LogLevel" :
        {
            "Default"                    : "Information",
            "Microsoft"                  : "Warning",
            "Microsoft.Hosting.Lifetime" : "Information"
        }
    },
    "AllowedHosts" : "*",
    "APIKey"       : "A7A54AD3-91E1-4C3A-98C6-A17E39C9EA3D"
}

 

▶ APIKeyAttribute.cs

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Threading.Tasks;

namespace TestServer
{
    /// <summary>
    /// API 키 어트리뷰트
    /// </summary>
    [AttributeUsage(validOn: AttributeTargets.Class)]
    public class APIKeyAttribute : Attribute, IAsyncActionFilter
    {
        //////////////////////////////////////////////////////////////////////////////////////////////////// Field
        ////////////////////////////////////////////////////////////////////////////////////////// Static
        //////////////////////////////////////////////////////////////////////////////// Public

        #region Field

        /// <summary>
        /// API 키명
        /// </summary>
        public static readonly string API_KEY_NAME = "APIKey";

        #endregion

        //////////////////////////////////////////////////////////////////////////////////////////////////// Method
        ////////////////////////////////////////////////////////////////////////////////////////// Static
        //////////////////////////////////////////////////////////////////////////////// Public

        #region 액션 실행시 처리하기 (비동기) - OnActionExecutionAsync(context, nextAction)

        /// <summary>
        /// 액션 실행시 처리하기 (비동기)
        /// </summary>
        /// <param name="context">액션 실행 컨텍스트</param>
        /// <param name="nextAction">다음 액션 실행 대리자</param>
        /// <returns>태스크</returns>
        public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate nextAction)
        {
            if(!context.HttpContext.Request.Headers.TryGetValue(API_KEY_NAME, out var sourceAPIKey))
            {
                context.Result = new ContentResult()
                {
                    StatusCode = 401,
                    Content    = "API Key was not provided."
                };

                return;
            }

            IConfiguration configuration = context.HttpContext.RequestServices.GetRequiredService<IConfiguration>();

            string targetAPIKey = configuration.GetValue<string>(API_KEY_NAME);

            if(!targetAPIKey.Equals(sourceAPIKey))
            {
                context.Result = new ContentResult()
                {
                    StatusCode = 401,
                    Content    = "API Key is not valid."
                };

                return;
            }

            await nextAction();
        }

        #endregion
    }
}

 

▶ WeatherForecast.cs

using System;

namespace TestServer
{
    /// <summary>
    /// 일기 예보
    /// </summary>
    public class WeatherForecast
    {
        //////////////////////////////////////////////////////////////////////////////////////////////////// Property
        ////////////////////////////////////////////////////////////////////////////////////////// Public

        #region 날짜 - Date

        /// <summary>
        /// 날짜
        /// </summary>
        public DateTime Date { get; set; }

        #endregion
        #region 섭씨 온도 - TemperatureC

        /// <summary>
        /// 섭씨 온도
        /// </summary>
        public int TemperatureC { get; set; }

        #endregion
        #region 화씨 온도 - TemperatureF

        /// <summary>
        /// 화씨 온도
        /// </summary>
        public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);

        #endregion
        #region 요약 - Summary

        /// <summary>
        /// 요약
        /// </summary>
        public string Summary { get; set; }

        #endregion
    }
}

 

▶ Controllers/WeatherForecastController.cs

using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;

namespace TestServer.Controllers
{
    /// <summary>
    /// 일기 예보 컨트롤러
    /// </summary>
    [ApiController]
    [Route("[controller]")]
    [APIKey]
    public class WeatherForecastController : ControllerBase
    {
        //////////////////////////////////////////////////////////////////////////////////////////////////// Field
        ////////////////////////////////////////////////////////////////////////////////////////// Static
        //////////////////////////////////////////////////////////////////////////////// Private

        #region Field

        /// <summary>
        /// 로거
        /// </summary>
        private readonly ILogger<WeatherForecastController> _logger;

        /// <summary>
        /// 요약 배열
        /// </summary>
        private static readonly string[] _summaryArray = new[]
        {
            "Freezing",
            "Bracing",
            "Chilly",
            "Cool",
            "Mild",
            "Warm",
            "Balmy",
            "Hot",
            "Sweltering",
            "Scorching"
        };

        #endregion

        //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor
        ////////////////////////////////////////////////////////////////////////////////////////// Public

        #region 생성자 - WeatherForecastController(logger)

        /// <summary>
        /// 생성자
        /// </summary>
        /// <param name="logger">로거</param>
        public WeatherForecastController(ILogger<WeatherForecastController> logger)
        {
            _logger = logger;
        }

        #endregion

        //////////////////////////////////////////////////////////////////////////////////////////////////// Method
        ////////////////////////////////////////////////////////////////////////////////////////// Public

        #region 구하기 - Get()

        /// <summary>
        /// 구하기
        /// </summary>
        /// <returns>일기 예보 열거 가능형</returns>
        [HttpGet]
        public IEnumerable<WeatherForecast> Get()
        {
            Random random = new Random();

            return Enumerable.Range(1, 5).Select
            (
                index => new WeatherForecast
                {
                    Date         = DateTime.Now.AddDays(index),
                    TemperatureC = random.Next(-20, 55),
                    Summary      = _summaryArray[random.Next(_summaryArray.Length)]
                }
            )
            .ToArray();
        }

        #endregion
    }
}

 

▶ Startup.cs

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.OpenApi.Models;

namespace TestServer
{
    /// <summary>
    /// 시작
    /// </summary>
    public class Startup
    {
        //////////////////////////////////////////////////////////////////////////////////////////////////// Property
        ////////////////////////////////////////////////////////////////////////////////////////// Public

        #region 구성 - Configuration

        /// <summary>
        /// 구성
        /// </summary>
        public IConfiguration Configuration { get; }

        #endregion

        //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor
        ////////////////////////////////////////////////////////////////////////////////////////// Public

        #region 생성자 - Startup(configuration)

        /// <summary>
        /// 생성자
        /// </summary>
        /// <param name="configuration">구성</param>
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        #endregion

        //////////////////////////////////////////////////////////////////////////////////////////////////// Method
        ////////////////////////////////////////////////////////////////////////////////////////// Public

        #region 서비스 컬렉션 구성하기 - ConfigureServices(serviceCollection)

        /// <summary>
        /// 서비스 컬렉션 구성하기
        /// </summary>
        /// <param name="serviceCollection">서비스 컬렉션</param>
        public void ConfigureServices(IServiceCollection serviceCollection)
        {
            serviceCollection.AddControllers();

            serviceCollection.AddSwaggerGen
            (
                options =>
                {
                    options.SwaggerDoc("v1", new OpenApiInfo { Title = "TestServer", Version = "v1" });
                }
            );
        }

        #endregion
        #region 구성하기 - Configure(applicationBuilder, webHostEnvironment)

        /// <summary>
        /// 구성하기
        /// </summary>
        /// <param name="applicationBuilder">애플리케이션 빌더</param>
        /// <param name="webHostEnvironment">웹 호스트 환경</param>
        public void Configure(IApplicationBuilder applicationBuilder, IWebHostEnvironment webHostEnvironment)
        {
            if(webHostEnvironment.IsDevelopment())
            {
                applicationBuilder.UseDeveloperExceptionPage();

                applicationBuilder.UseSwagger();

                applicationBuilder.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "TestServer v1"));
            }

            applicationBuilder.UseHttpsRedirection();

            applicationBuilder.UseRouting();

            applicationBuilder.UseAuthorization();

            applicationBuilder.UseEndpoints
            (
                endpointRouteBuilder =>
                {
                    endpointRouteBuilder.MapControllers();
                }
            );
        }

        #endregion
    }
}

 

▶ Program.cs

using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Hosting;

namespace TestServer
{
    /// <summary>
    /// 프로그램
    /// </summary>
    public class Program
    {
        //////////////////////////////////////////////////////////////////////////////////////////////////// Method
        ////////////////////////////////////////////////////////////////////////////////////////// Static
        //////////////////////////////////////////////////////////////////////////////// Public

        #region 호스트 빌더 생성하기 - CreateHostBuilder(argumentList)

        /// <summary>
        /// 호스트 빌더 생성하기
        /// </summary>
        /// <param name="argumentList">인자 리스트</param>
        /// <returns>호스트 빌더</returns>
        public static IHostBuilder CreateHostBuilder(string[] argumentList) =>
            Host.CreateDefaultBuilder(argumentList)
                .ConfigureWebHostDefaults
                (
                    webBuilder =>
                    {
                        webBuilder.UseStartup<Startup>();
                    }
                );

        #endregion
        #region 프로그램 시작하기 - Main(argumentList)

        /// <summary>
        /// 프로그램 시작하기
        /// </summary>
        /// <param name="argumentList">인자 리스트</param>
        public static void Main(string[] argumentList)
        {
            CreateHostBuilder(argumentList).Build().Run();
        }

        #endregion
    }
}

 

[TestClient 프로젝트]

▶ Program.cs

using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;

namespace TestClient
{
    /// <summary>
    /// 프로그램
    /// </summary>
    class Program
    {
        //////////////////////////////////////////////////////////////////////////////////////////////////// Method
        ////////////////////////////////////////////////////////////////////////////////////////// Static
        //////////////////////////////////////////////////////////////////////////////// Public

        #region HTTP 클라이언트 구하기 - GetHTTPClient(baseAddress)

        /// <summary>
        /// HTTP 클라이언트 구하기
        /// </summary>
        /// <param name="baseAddress">기준 주소</param>
        /// <returns>HTTP 클라이언트</returns>
        private static HttpClient GetHTTPClient(string baseAddress)
        {
            HttpClient client = new HttpClient();

            client.BaseAddress = new Uri(baseAddress);

            client.DefaultRequestHeaders.Add("APIKey", "A7A54AD3-91E1-4C3A-98C6-A17E39C9EA3D");

            client.DefaultRequestHeaders.Accept.Clear();

            client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

            return client;
        }

        #endregion
        #region 리스트 구하기 - GetList(client)

        /// <summary>
        /// 리스트 구하기
        /// </summary>
        /// <param name="client">클라이언트</param>
        /// <returns>리스트</returns>
        private static async Task<List<WeatherForecast>> GetList(HttpClient client)
        {
            string url = string.Format("/WeatherForecast");

            HttpResponseMessage response = await client.GetAsync(url);

            if(response.IsSuccessStatusCode)
            {
                List<WeatherForecast> list = await response.Content.ReadAsAsync<List<WeatherForecast>>();

                return list;
            }
            else
            {
                Console.WriteLine(response.StatusCode);
                Console.WriteLine(await response.Content.ReadAsStringAsync());
            }

            return null;
        }

        #endregion
        #region 프로그램 시작하기 - Main()

        /// <summary>
        /// 프로그램 시작하기
        /// </summary>
        static void Main()
        {
            using(HttpClient client = GetHTTPClient("https://localhost:44362"))
            {
                List<WeatherForecast> list = GetList(client).GetAwaiter().GetResult();

                for(int i = 0; i < list.Count; i++)
                {
                    Console.WriteLine(list[i].Summary);
                }
            }

            Console.WriteLine("--------------------------------------------------");
            Console.WriteLine("아무 키나 눌러 주시기 바랍니다.");
            Console.ReadKey(true);
        }

        #endregion
    }
}
728x90
반응형
그리드형(광고전용)
Posted by icodebroker

댓글을 달아 주세요