kr.bbon.AspNetCore Package
π’ Overview
.NET 5 μμ API μΉ μμ©νλ‘κ·Έλ¨ νλ‘μ νΈ (webapi ν νλ¦Ώ κΈ°μ€)λ₯Ό μμν λ, λ°λ³΅μ μΌλ‘ μμ±νλ μ¬νμ ν¨ν€μ§λ‘ μ 리νμ΅λλ€.
π Namespace
kr.bbon.AspNetCore
μΉ μμ©νλ‘κ·Έλ¨μμ μ¬μ©λλ κΈ°λ₯κ³Ό νμ₯ λ©μλλ₯Ό ν¬ν¨ν©λλ€.
kr.bbon.Core ν¨ν€μ§λ‘ μ΄λλμμ΅λλ€.
kr.bbon.AspNetCore.Filters
ASP.NET Core Mvc Filtersλ₯Ό μ§μνλ κΈ°λ₯μ ν¬ν¨ν©λλ€.
kr.bbon.AspNetCore.Mvc
ASP.NET Core MVCλ₯Ό μ§μνλ κΈ°λ₯μ ν¬ν¨ν©λλ€.
π― Features
Exception classes
HttpStatusException class
kr.bbon.Core ν¨ν€μ§λ‘ μ΄λλμμ΅λλ€.
HTTP μμΈλ₯Ό νννκΈ° μν΄ μ¬μ©λ©λλ€.
kr.bbon.Core ν¨ν€μ§λ‘ μ΄μ λμμ΅λλ€.
// Exception handling in action method
try
{
// ...
}
catch(HttpStatusException ex)
{
return StatusCode(ex.StatusCode, ex.Message, ex.GetDetails());
}
catch(Exception ex)
{
// ...
}
HttpStatusException class
kr.bbon.Core ν¨ν€μ§λ‘ μ΄λλμμ΅λλ€.
HTTP μμΈμ μμΈ μ 보λ₯Ό νννκΈ° μν΄ μ¬μ©λ©λλ€.
kr.bbon.Core ν¨ν€μ§λ‘ μ΄μ λμμ΅λλ€.
throw new HttpStatusException(HttpStatusCode.BadRequest, new SomeDetails
{
Id = "err111",
Message = "AAA μμ±μ κ°μ΄ μ μκ° μλλλ€.",
});
SomethingWrongException
kr.bbon.Core ν¨ν€μ§λ‘ μ΄λλμμ΅λλ€.
μ¬μ©μ μ μ μμΈλ₯Ό νννκΈ° μν΄ μ¬μ©ν©λλ€.
kr.bbon.Core ν¨ν€μ§λ‘ μ΄μ λμμ΅λλ€.
// Exception handling in action method
try
{
// ...
}
catch(SomethingWrongException ex)
{
return StatusCode(HttpStatusCode.Forbidden, ex.Message, ex.GetDetails());
}
catch(Exception ex)
{
// ...
}
SomethingWrongException
kr.bbon.Core ν¨ν€μ§λ‘ μ΄λλμμ΅λλ€.
μ¬μ©μ μ μ μμΈμ μμΈ μ 보λ₯Ό νννκΈ° μν΄ μ¬μ©ν©λλ€.
kr.bbon.Core ν¨ν€μ§λ‘ μ΄μ λμμ΅λλ€.
throw new SomethingWrongException("λ°μ΄ν°λ₯Ό μ²λ¦¬νμ§ λͺ»νμ΅λλ€.", new SomeDetails
{
Id = "err111",
Message = "AAA μμ±μ κ°μ΄ μ μκ° μλλλ€.",
});
Extension methods
IApplicationBuilder.UseSwaggerUIWithApiVersioning() method
IApplicationBuilder μΈν°νμ΄μ€μ UseSwaggerUIWithApiVersioning λ©μλλ₯Ό μΆκ°ν©λλ€.
Swagger λ₯Ό μ¬μ©νκΈ° μν΄ νμν μ½λ μ‘°κ°μ΄ μ 리λμ΄ μμ΅λλ€.
// Configure() on Startup.cs
app.UseSwaggerUIWithApiVersioning();
Object.ToJson() method
Object ν΄λμ€μ ToJson λ©μλλ₯Ό μΆκ°ν©λλ€.
κ°μ²΄μ μΈμ€ν΄μ€λ₯Ό JSON λ¬Έμμ΄λ‘ μ§λ ¬ννλ κΈ°λ₯μ μ 곡ν©λλ€.
kr.bbon.Core ν¨ν€μ§λ‘ μ΄μ λμμ΅λλ€.
var sample = getSampleModel();
sample.ToJson();
JsonSerializerOptions λ§€κ°λ³μκ° μ§μ λμ§ μμ κ²½μ° μλ κΈ°λ³Έκ°μ μ¬μ©ν©λλ€.
var defaultOptions = new JsonSerializerOptions
{
WriteIndented = true,
Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping,
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
};
IServiceCollection.AddApiVersioningAndSwaggerGen() method
IServiceCollection μΈν°νμ΄μ€μ AddApiVersioningAndSwaggerGen λ©μλλ₯Ό μΆκ°ν©λλ€.
ApiVersioning, Swagger λ₯Ό μ¬μ©νκΈ° μν΄ νμν μ½λμ‘°κ°μ΄ μ 리λμ΄ μμ΅λλ€.
// ConfigureService() on Startup.cs
var defaultApiVersion = new ApiVersion(1, 0);
services.Configure<AppOptions>(Configuration.GetSection(AppOptions.Name));
services.AddApiVersioningAndSwaggerGen(defaultApiVersion);
Filter classes
ApiExceptionHandlerFilter class
컨νΈλ‘€λ¬μμ μ²λ¦¬λμ§ μμ μμΈκ° λ°μνλ©΄ μμΈλ₯Ό μ²λ¦¬νλ νν°λ₯Ό μ 곡ν©λλ€.
μμΈ μ²λ¦¬ νν°λ₯Ό 컨νΈλ‘€λ¬μμ μ¬μ©νλ €λ©΄ μλμ κ°μ΄ ν΄λμ€ νΉμ±μΌλ‘ μΆκ°ν©λλ€.
[ApiExceptionHandlerFilter]
// ...
public class SomeController : ApiControllerBase
{
// ...
}
μμΈ μ²λ¦¬ νν°λ₯Ό μ‘μ μμ μ¬μ©νλ €λ©΄ μλμ κ°μ΄ ν΄λμ€ νΉμ±μΌλ‘ μΆκ°ν©λλ€.
[HttpGet]
[ApiExceptionHandlerFilter]
public IActionResult SomeAction()
{
// ...
}
μμΈ μ²λ¦¬ νν°λ₯Ό μ μμΌλ‘ μ¬μ©νλ €λ©΄ μλμ κ°μ΄ ꡬμ±ν©λλ€.
// ConfigureService() on Startup.cs
services.AddControllers(options =>
{
options.Filters.Add<ApiExceptionHandlerFilter>();
});
Model classes
ApiResponseModel classes
λμΌν μλ΅μ μ 곡νκΈ° μν΄ μ¬μ©λλ μλ΅ λͺ¨λΈμ λλ€.
μλμ κ°μ νμμΌλ‘ HTTP μλ΅ λ³Έλ¬Έμ μ 곡ν©λλ€.
{
statusCode: number
message: string
instance: string
path: string
method: string
data: T
}
ErrorModel class
μ¬μ©μ μ μ μ€λ₯λ₯Ό ννν©λλ€.
kr.bbon.Core ν¨ν€μ§λ‘ μ΄μ λμμ΅λλ€.
var error = new ErrorModel
{
Code = "Some code",
Message = "Some message",
InnerError = new ErrorModel
{
Code = "Some inner code",
Message = "Some inner message",
}
});
ControllerBase classes
ApiControllerBase class
μΉ μμ©νλ‘κ·Έλ¨ μλ΅μ λμΌνκ² μ 곡νκΈ° μν μ½λμ‘°κ°μ΄ μ 리λμ΄ μμ΅λλ€.
β ApiControllerBase ν΄λμ€λ₯Ό μμνλ ApiController λApiVersionAttribute
,AreaAttribute
,RouteAttribute
λ₯Ό νμμ μΌλ‘ μ¬μ©ν΄μΌ ν©λλ€.
[ApiVersion(DefaultValues.ApiVersion)]
[ApiController]
[Area(DefaultValues.AreaName)]
[Route(DefaultValues.RouteTemplate)]
[ApiExceptionHandlerFilter]
public class WeatherForecastController : ApiControllerBase
{
// ...
}
컨νΈλ‘€λ¬μ μ‘μ λ©μλμμ μλμ κ°μ΄ μλ΅μ ꡬμ±ν©λλ€.
var responseData = GetResponseData();
return StatusCode(HttpStatusCode.OK, responseData)
HTTP μλ΅λ³Έλ¬Έμ μλμ κ°μ΄ μ 곡λ©λλ€.
{
"statusCode": 200,
"message": null,
"data": {
// ...responseData
}
}
Etc classes
AppOptions class
μμ© νλ‘κ·Έλ¨ κ΅¬μ±κ°μ ννν©λλ€.
appsettings.json μ μλμ κ°μ΄ ꡬμ±νκ³ , μλΉμ€ ꡬμ±μμ ꡬμ±κ°μ μ½μ΄μ μ²λ¦¬ν©λλ€.
OpenApiInfo ν΄λμ€λ λμΌν κ°μΌλ‘ ꡬμ±λ©λλ€.
// appsettings.json
{
"App": {
"Title": "Awesome api",
"Description": "My awesome api !!"
},
// ...
}
// ConfigureService() on Startup.cs
services.Configure<AppOptions>(Configuration.GetSection(AppOptions.Name));
ConfigureSwaggerOptionsBase class
Swagger ꡬμ±κ°μ μν κΈ°λ³Έ ν΄λμ€μ λλ€.
μλμ κ°μ΄ ConfigureSwaggerOptionsBase
λ₯Ό μμνλ λ³ΈμΈμ ConfigureSwaggerOptions
ν΄λμ€λ₯Ό μ μνμΈμ.
public class MyConfigureSwaggerOptions : ConfigureSwaggerOptionsBase {
public MyConfigureSwaggerOptions(IApiVersionDescriptionProvider provider, IOptionsMonitor<AppOptions> optionsAccessor)
: base(provider)
{
options = optionsAccessor.CurrentValue;
}
public override string AppTitle => options.Title;
public override string AppDescription => options.Description;
private readonly AppOptions options;
}
ConfigureSwaggerOptions class
ConfigureSwaggerOptionsBase ν΄λμ€λ₯Ό ꡬννλ ν΄λμ€μ λλ€.
Constants
DefaultValues class
RouteTemplate:
ν΄λμ€ λΌμ°νΈ ν
νλ¦Ώμ κΈ°λ³Έκ°μ
λλ€. [area]/v{version:apiVersion}/[controller]
ApiVersion:
κΈ°λ³Έ λ²μ λ¬Έμμ΄ μ
λλ€. 1.0
AreaName:
μμ κΈ°λ³Έκ°μ
λλ€. api