푸터 콘텐츠로 바로가기
.NET 도움말

Swashbuckle ASP .NET Core (개발자를 위한 작동 원리)

Swashbuckle은 RESTful 웹 API를 자동으로 문서화하는 C# .NET Core NuGet 패키지입니다. 이 블로그에서는 Swashbuckle ASP.NET Core와 IronPDF 설치 지침 NuGet 패키지를 살펴보고, 현대적인 ASP.NET Core 웹 API 개발을 가능하게 합니다. 함께 최소한의 코드로 달성할 수 있는 다양한 기능들을 제공합니다.

API 문서 페이지는 Swagger UI 도구를 사용하여 표시되며, 이는 웹 API 프로젝트에서 생성된 swagger.json 파일을 사용합니다. 생성된 JSON 문서는 오픈 API 표준을 따릅니다. Swashbuckle은 NuGet 패키지 Swashbuckle.AspNetCore으로 제공되며, 설치 및 구성하면 Swagger JSON을 자동으로 노출합니다. Swagger UI 도구는 API에 작성된 XML 주석에서 생성된 Swagger JSON 파일을 읽습니다. 추가적으로 프로젝트 설정 파일에서 활성화하여 XML 문서 파일을 생성할 수 있습니다. XML 주석은 XML 문서 파일로 변환되며, 여기서 Swagger JSON이 생성됩니다. 그런 후 Swagger 미들웨어가 JSON을 읽고 Swagger JSON 엔드포인트를 노출합니다.

.NET Core 웹 API 프로젝트에서 구현

웹 API 프로젝트를 시작해 봅시다:

dotnet new webapi -n SwashbuckleDemo
cd SwashbuckleDemo
dotnet build
dotnet add package Swashbuckle.AspNetCore --version 6.5.0
dotnet build
dotnet new webapi -n SwashbuckleDemo
cd SwashbuckleDemo
dotnet build
dotnet add package Swashbuckle.AspNetCore --version 6.5.0
dotnet build
SHELL

여기서 'SwashbuckleDemo'라는 웹 API 프로젝트를 생성한 후 패키지 관리자 콘솔을 사용하여 .NET Core 웹 API 프로젝트에 Swashbuckle 패키지를 설치합니다.

Swagger 미들웨어 구성

Swagger 서비스를 Startup.cs 파일에서 구성하십시오.

using System.Reflection;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.AspNetCore.Builder;

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        // Other service configurations...

        // Register the Swagger generator
        services.AddSwaggerGen(c =>
        {
            c.SwaggerDoc("v1", new OpenApiInfo { Title = "My API", Version = "v1" });

            // Optionally, include XML comments for additional information
            var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
            var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
            c.IncludeXmlComments(xmlPath);
        });
    }

    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        // Other app configurations...

        // Enable middleware to serve generated Swagger as a JSON endpoint.
        app.UseSwagger();

        // Enable Swagger UI (HTML, JS, CSS, etc.), specifying the Swagger JSON endpoint.
        app.UseSwaggerUI(c =>
        {
            c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1");
        });
    }
}
using System.Reflection;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.AspNetCore.Builder;

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        // Other service configurations...

        // Register the Swagger generator
        services.AddSwaggerGen(c =>
        {
            c.SwaggerDoc("v1", new OpenApiInfo { Title = "My API", Version = "v1" });

            // Optionally, include XML comments for additional information
            var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
            var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
            c.IncludeXmlComments(xmlPath);
        });
    }

    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        // Other app configurations...

        // Enable middleware to serve generated Swagger as a JSON endpoint.
        app.UseSwagger();

        // Enable Swagger UI (HTML, JS, CSS, etc.), specifying the Swagger JSON endpoint.
        app.UseSwaggerUI(c =>
        {
            c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1");
        });
    }
}
Imports System.Reflection
Imports Microsoft.Extensions.DependencyInjection
Imports Microsoft.AspNetCore.Builder

Public Class Startup
	Public Sub ConfigureServices(ByVal services As IServiceCollection)
		' Other service configurations...

		' Register the Swagger generator
		services.AddSwaggerGen(Sub(c)
			c.SwaggerDoc("v1", New OpenApiInfo With {
				.Title = "My API",
				.Version = "v1"
			})

			' Optionally, include XML comments for additional information
			Dim xmlFile = $"{System.Reflection.Assembly.GetExecutingAssembly().GetName().Name}.xml"
			Dim xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile)
			c.IncludeXmlComments(xmlPath)
		End Sub)
	End Sub

	Public Sub Configure(ByVal app As IApplicationBuilder, ByVal env As IHostingEnvironment)
		' Other app configurations...

		' Enable middleware to serve generated Swagger as a JSON endpoint.
		app.UseSwagger()

		' Enable Swagger UI (HTML, JS, CSS, etc.), specifying the Swagger JSON endpoint.
		app.UseSwaggerUI(Sub(c)
			c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1")
		End Sub)
	End Sub
End Class
$vbLabelText   $csharpLabel

할 일을 목록 API에 대한 컨트롤러를 추가하십시오:

using Microsoft.AspNetCore.Http.HttpResults;
using Microsoft.AspNetCore.Builder;
using Microsoft.EntityFrameworkCore;
using Microsoft.AspNetCore.Mvc;
using System.Threading.Tasks;

// Example to define an entity class
public class Todo
{
    public int Id { get; set; }
    public string Name { get; set; }
    public bool IsComplete { get; set; }
}

// Example to define a DbContext class
public class TodoDb : DbContext
{
    public DbSet<Todo> Todos => Set<Todo>();
}

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

app.MapGet("/", () => "SwashbuckleDemo!");

app.MapGet("/todoitems", async (TodoDb db) =>
    await db.Todos.ToListAsync());

app.MapGet("/todoitems/complete", async (TodoDb db) =>
    await db.Todos.Where(t => t.IsComplete).ToListAsync());

app.MapGet("/todoitems/{id}", async (int id, TodoDb db) =>
    await db.Todos.FindAsync(id) is Todo todo
        ? Results.Ok(todo)
        : Results.NotFound());

app.MapPost("/todoitems", async (Todo todo, TodoDb db) =>
{
    db.Todos.Add(todo);
    await db.SaveChangesAsync();
    return Results.Created($"/todoitems/{todo.Id}", todo);
});

app.MapPut("/todoitems/{id}", async (int id, Todo inputTodo, TodoDb db) =>
{
    var todo = await db.Todos.FindAsync(id);
    if (todo is null) return Results.NotFound();
    todo.Name = inputTodo.Name;
    todo.IsComplete = inputTodo.IsComplete;
    await db.SaveChangesAsync();
    return Results.NoContent();
});

app.MapDelete("/todoitems/{id}", async (int id, TodoDb db) =>
{
    if (await db.Todos.FindAsync(id) is Todo todo)
    {
        db.Todos.Remove(todo);
        await db.SaveChangesAsync();
        return Results.Ok(todo);
    }

    return Results.NotFound();
});

app.Run();
using Microsoft.AspNetCore.Http.HttpResults;
using Microsoft.AspNetCore.Builder;
using Microsoft.EntityFrameworkCore;
using Microsoft.AspNetCore.Mvc;
using System.Threading.Tasks;

// Example to define an entity class
public class Todo
{
    public int Id { get; set; }
    public string Name { get; set; }
    public bool IsComplete { get; set; }
}

// Example to define a DbContext class
public class TodoDb : DbContext
{
    public DbSet<Todo> Todos => Set<Todo>();
}

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

app.MapGet("/", () => "SwashbuckleDemo!");

app.MapGet("/todoitems", async (TodoDb db) =>
    await db.Todos.ToListAsync());

app.MapGet("/todoitems/complete", async (TodoDb db) =>
    await db.Todos.Where(t => t.IsComplete).ToListAsync());

app.MapGet("/todoitems/{id}", async (int id, TodoDb db) =>
    await db.Todos.FindAsync(id) is Todo todo
        ? Results.Ok(todo)
        : Results.NotFound());

app.MapPost("/todoitems", async (Todo todo, TodoDb db) =>
{
    db.Todos.Add(todo);
    await db.SaveChangesAsync();
    return Results.Created($"/todoitems/{todo.Id}", todo);
});

app.MapPut("/todoitems/{id}", async (int id, Todo inputTodo, TodoDb db) =>
{
    var todo = await db.Todos.FindAsync(id);
    if (todo is null) return Results.NotFound();
    todo.Name = inputTodo.Name;
    todo.IsComplete = inputTodo.IsComplete;
    await db.SaveChangesAsync();
    return Results.NoContent();
});

app.MapDelete("/todoitems/{id}", async (int id, TodoDb db) =>
{
    if (await db.Todos.FindAsync(id) is Todo todo)
    {
        db.Todos.Remove(todo);
        await db.SaveChangesAsync();
        return Results.Ok(todo);
    }

    return Results.NotFound();
});

app.Run();
Imports Microsoft.AspNetCore.Http.HttpResults
Imports Microsoft.AspNetCore.Builder
Imports Microsoft.EntityFrameworkCore
Imports Microsoft.AspNetCore.Mvc
Imports System.Threading.Tasks

' Example to define an entity class
Public Class Todo
	Public Property Id() As Integer
	Public Property Name() As String
	Public Property IsComplete() As Boolean
End Class

' Example to define a DbContext class
Public Class TodoDb
	Inherits DbContext

	Public ReadOnly Property Todos() As DbSet(Of Todo)
		Get
			Return [Set](Of Todo)()
		End Get
	End Property
End Class

Private builder = WebApplication.CreateBuilder(args)
Private app = builder.Build()

app.MapGet("/", Function() "SwashbuckleDemo!")

app.MapGet("/todoitems", Async Function(db As TodoDb) Await db.Todos.ToListAsync())

app.MapGet("/todoitems/complete", Async Function(db As TodoDb) Await db.Todos.Where(Function(t) t.IsComplete).ToListAsync())

Dim tempVar As Boolean = TypeOf db.Todos.FindAsync(id) Is Todo
Dim todo As Todo = If(tempVar, CType(db.Todos.FindAsync(id), Todo), Nothing)
app.MapGet("/todoitems/{id}", Async Function(id As Integer, db As TodoDb)If(Await tempVar, Results.Ok(todo), Results.NotFound()))

app.MapPost("/todoitems", Async Function(todo As Todo, db As TodoDb)
	db.Todos.Add(todo)
	Await db.SaveChangesAsync()
	Return Results.Created($"/todoitems/{todo.Id}", todo)
End Function)

app.MapPut("/todoitems/{id}", Async Function(id As Integer, inputTodo As Todo, db As TodoDb)
	Dim todo = Await db.Todos.FindAsync(id)
	If todo Is Nothing Then
		Return Results.NotFound()
	End If
	todo.Name = inputTodo.Name
	todo.IsComplete = inputTodo.IsComplete
	Await db.SaveChangesAsync()
	Return Results.NoContent()
End Function)

app.MapDelete("/todoitems/{id}", Async Function(id As Integer, db As TodoDb)
	Dim tempVar2 As Boolean = TypeOf db.Todos.FindAsync(id) Is Todo
	Dim todo As Todo = If(tempVar2, CType(db.Todos.FindAsync(id), Todo), Nothing)
	If Await tempVar2 Then
		db.Todos.Remove(todo)
		Await db.SaveChangesAsync()
		Return Results.Ok(todo)
	End If

	Return Results.NotFound()
End Function)

app.Run()
$vbLabelText   $csharpLabel

다음과 같은 방식으로 컨트롤러를 추가할 수 있습니다:

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

namespace RestFullMinimalApi.Controllers
{
    [ApiController]
    [Route("[controller]")]
    public class WeatherForecastController : ControllerBase
    {
        private static readonly string[] Summaries = new[]
        {
            "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
        };

        private readonly ILogger<WeatherForecastController> _logger;

        public WeatherForecastController(ILogger<WeatherForecastController> logger)
        {
            _logger = logger;
        }

        /// <summary>
        /// Retrieves WeatherForecast
        /// </summary>
        /// <remarks>Awesomeness!</remarks>
        /// <response code="200">Retrieved</response>
        /// <response code="404">Not found</response>
        /// <response code="500">Oops! Can't lookup your request right now</response>
        [HttpGet(Name = "GetWeatherForecast")]
        public IEnumerable<WeatherForecast> Get()
        {
            return Enumerable.Range(1, 5).Select(index => new WeatherForecast
            {
                Date = DateTime.Now.AddDays(index),
                TemperatureC = Random.Shared.Next(-20, 55),
                Summary = Summaries[Random.Shared.Next(Summaries.Length)]
            })
            .ToArray();
        }
    }

    public class WeatherForecast
    {
        public DateTime Date { get; set; }
        public int TemperatureC { get; set; }
        public string Summary { get; set; }
    }
}
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using System.Collections.Generic;
using System;
using System.Linq;

namespace RestFullMinimalApi.Controllers
{
    [ApiController]
    [Route("[controller]")]
    public class WeatherForecastController : ControllerBase
    {
        private static readonly string[] Summaries = new[]
        {
            "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
        };

        private readonly ILogger<WeatherForecastController> _logger;

        public WeatherForecastController(ILogger<WeatherForecastController> logger)
        {
            _logger = logger;
        }

        /// <summary>
        /// Retrieves WeatherForecast
        /// </summary>
        /// <remarks>Awesomeness!</remarks>
        /// <response code="200">Retrieved</response>
        /// <response code="404">Not found</response>
        /// <response code="500">Oops! Can't lookup your request right now</response>
        [HttpGet(Name = "GetWeatherForecast")]
        public IEnumerable<WeatherForecast> Get()
        {
            return Enumerable.Range(1, 5).Select(index => new WeatherForecast
            {
                Date = DateTime.Now.AddDays(index),
                TemperatureC = Random.Shared.Next(-20, 55),
                Summary = Summaries[Random.Shared.Next(Summaries.Length)]
            })
            .ToArray();
        }
    }

    public class WeatherForecast
    {
        public DateTime Date { get; set; }
        public int TemperatureC { get; set; }
        public string Summary { get; set; }
    }
}
Imports Microsoft.AspNetCore.Mvc
Imports Microsoft.Extensions.Logging
Imports System.Collections.Generic
Imports System
Imports System.Linq

Namespace RestFullMinimalApi.Controllers
	<ApiController>
	<Route("[controller]")>
	Public Class WeatherForecastController
		Inherits ControllerBase

		Private Shared ReadOnly Summaries() As String = { "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching" }

		Private ReadOnly _logger As ILogger(Of WeatherForecastController)

		Public Sub New(ByVal logger As ILogger(Of WeatherForecastController))
			_logger = logger
		End Sub

		''' <summary>
		''' Retrieves WeatherForecast
		''' </summary>
		''' <remarks>Awesomeness!</remarks>
		''' <response code="200">Retrieved</response>
		''' <response code="404">Not found</response>
		''' <response code="500">Oops! Can't lookup your request right now</response>
		<HttpGet(Name := "GetWeatherForecast")>
		Public Function [Get]() As IEnumerable(Of WeatherForecast)
			Return Enumerable.Range(1, 5).Select(Function(index) New WeatherForecast With {
				.Date = DateTime.Now.AddDays(index),
				.TemperatureC = Random.Shared.Next(-20, 55),
				.Summary = Summaries(Random.Shared.Next(Summaries.Length))
			}).ToArray()
		End Function
	End Class

	Public Class WeatherForecast
		Public Property [Date]() As DateTime
		Public Property TemperatureC() As Integer
		Public Property Summary() As String
	End Class
End Namespace
$vbLabelText   $csharpLabel

위 코드는 GitHub - Swashbuckle Demo에서 확인할 수 있습니다.

Swashbuckle은 다음과 같은 기능을 제공합니다

Swagger UI 도구

Swashbuckle ASP .NET Core(개발자를 위한 작동 방법): 그림 1 - Swagger UI 도구

Swagger UI는 웹 API 응용 프로그램의 기본 URL에서 "/swagger/index.html"로 제공됩니다. 코드에 있는 모든 REST API를 나열합니다. Swagger 생성기는 JSON 파일을 읽고 UI에 반영합니다.

Swagger JSON

Swashbuckle.AspNetCore는 API의 구조에 대한 정보, 엔드포인트, 요청 및 응답 유형 등의 세부 사항을 포함한 Swagger JSON 파일을 자동으로 생성합니다. 이 JSON 파일은 Swagger/OpenAPI 표준을 지원하는 다른 도구와 서비스에서 사용할 수 있습니다.

Swagger JSON 파일은 웹 API 애플리케이션의 기본 URL에서 "/swagger/v1/swagger.json"에 있습니다.

Swashbuckle ASP .NET Core(개발자를 위한 작동 방법): 그림 2 - Swagger JSON 파일

코드 주석

개발자는 ASP.NET Core 컨트롤러 내에서 XML 주석과 속성을 사용하여 Swagger 문서에 추가 정보를 제공할 수 있습니다. 여기에는 생성된 Swagger 문서를 개선하는 설명, 예시 및 기타 메타데이터가 포함됩니다.

[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
{
    private static readonly string[] Summaries = new[]
    {
        "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
    };

    private readonly ILogger<WeatherForecastController> _logger;

    public WeatherForecastController(ILogger<WeatherForecastController> logger)
    {
        _logger = logger;
    }

    /// <summary>
    /// Retrieves WeatherForecast
    /// </summary>
    /// <remarks>Awesomeness!</remarks>
    /// <response code="200">Retrieved</response>
    /// <response code="404">Not found</response>
    /// <response code="500">Oops! Can't lookup your request right now</response>
    [HttpGet(Name = "GetWeatherForecast")]
    public IEnumerable<WeatherForecast> Get()
    {
        return Enumerable.Range(1, 5).Select(index => new WeatherForecast
        {
            Date = DateTime.Now.AddDays(index),
            TemperatureC = Random.Shared.Next(-20, 55),
            Summary = Summaries[Random.Shared.Next(Summaries.Length)]
        })
        .ToArray();
    }
}
[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
{
    private static readonly string[] Summaries = new[]
    {
        "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
    };

    private readonly ILogger<WeatherForecastController> _logger;

    public WeatherForecastController(ILogger<WeatherForecastController> logger)
    {
        _logger = logger;
    }

    /// <summary>
    /// Retrieves WeatherForecast
    /// </summary>
    /// <remarks>Awesomeness!</remarks>
    /// <response code="200">Retrieved</response>
    /// <response code="404">Not found</response>
    /// <response code="500">Oops! Can't lookup your request right now</response>
    [HttpGet(Name = "GetWeatherForecast")]
    public IEnumerable<WeatherForecast> Get()
    {
        return Enumerable.Range(1, 5).Select(index => new WeatherForecast
        {
            Date = DateTime.Now.AddDays(index),
            TemperatureC = Random.Shared.Next(-20, 55),
            Summary = Summaries[Random.Shared.Next(Summaries.Length)]
        })
        .ToArray();
    }
}
<ApiController>
<Route("[controller]")>
Public Class WeatherForecastController
	Inherits ControllerBase

	Private Shared ReadOnly Summaries() As String = { "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching" }

	Private ReadOnly _logger As ILogger(Of WeatherForecastController)

	Public Sub New(ByVal logger As ILogger(Of WeatherForecastController))
		_logger = logger
	End Sub

	''' <summary>
	''' Retrieves WeatherForecast
	''' </summary>
	''' <remarks>Awesomeness!</remarks>
	''' <response code="200">Retrieved</response>
	''' <response code="404">Not found</response>
	''' <response code="500">Oops! Can't lookup your request right now</response>
	<HttpGet(Name := "GetWeatherForecast")>
	Public Function [Get]() As IEnumerable(Of WeatherForecast)
		Return Enumerable.Range(1, 5).Select(Function(index) New WeatherForecast With {
			.Date = DateTime.Now.AddDays(index),
			.TemperatureC = Random.Shared.Next(-20, 55),
			.Summary = Summaries(Random.Shared.Next(Summaries.Length))
		}).ToArray()
	End Function
End Class
$vbLabelText   $csharpLabel

구성 옵션

Swashbuckle.AspNetCore는 Swagger 문서 생성 방식을 사용자 정의할 수 있는 다양한 구성 옵션을 제공합니다. 개발자는 어떤 API가 문서화되는지를 제어하고, 명명 규칙을 구성하며, 다른 설정을 조정할 수 있습니다.

Swashbuckle.AspNetCore가 제공하는 주요 구성 옵션은 다음과 같습니다:

SwaggerGen 옵션

c.SwaggerDoc("v1", new OpenApiInfo { Title = "My API", Version = "v1" });
c.SwaggerDoc("v1", new OpenApiInfo { Title = "My API", Version = "v1" });
c.SwaggerDoc("v1", New OpenApiInfo With {
	.Title = "My API",
	.Version = "v1"
})
$vbLabelText   $csharpLabel

이 줄은 Swagger 문서 버전을 지정하고 API의 제목 및 버전과 같은 메타데이터를 포함합니다.

c.IncludeXmlComments(xmlPath);
c.IncludeXmlComments(xmlPath);
c.IncludeXmlComments(xmlPath)
$vbLabelText   $csharpLabel

이 옵션은 코드의 XML 주석을 포함하여 Swagger 문서에 추가 정보를 제공할 수 있게 합니다. xmlPath 변수는 XML 주석 파일의 위치를 가리켜야 합니다.

c.DescribeAllParametersInCamelCase();
c.DescribeAllParametersInCamelCase();
c.DescribeAllParametersInCamelCase()
$vbLabelText   $csharpLabel

이 옵션은 매개 변수 이름에 camelCase를 사용하도록 Swagger 생성기를 구성합니다.

c.OperationFilter<CustomOperationFilter>();
c.OperationFilter<CustomOperationFilter>();
c.OperationFilter(Of CustomOperationFilter)()
$vbLabelText   $csharpLabel

특정 작업에 대해 Swagger 문서를 수정하기 위해 사용자 정의 작업 필터를 등록할 수 있습니다. CustomOperationFilterIOperationFilter를 구현하는 클래스입니다.

Swagger UI 옵션

c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1");
c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1");
c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1")
$vbLabelText   $csharpLabel

이 줄은 Swagger UI가 문서를 표시하도록 구성합니다. 첫 번째 매개변수는 Swagger JSON 파일의 URL이고, 두 번째 매개변수는 사용자가 친숙한 API 버전 이름입니다.

c.RoutePrefix = "swagger";
c.RoutePrefix = "swagger";
c.RoutePrefix = "swagger"
$vbLabelText   $csharpLabel

Swagger UI의 경로 접두사를 설정할 수 있습니다. 이 예에서 Swagger UI는 /swagger에서 사용할 수 있습니다.

c.DocExpansion(DocExpansion.None);
c.DocExpansion(DocExpansion.None);
c.DocExpansion(DocExpansion.None)
$vbLabelText   $csharpLabel

이 옵션은 Swagger UI가 API 문서를 표시하는 방식을 제어합니다. DocExpansion.None는 기본적으로 모든 작업을 축소합니다.

SwaggerOptions

c.SerializeAsV2 = true;
c.SerializeAsV2 = true;
c.SerializeAsV2 = True
$vbLabelText   $csharpLabel

이 옵션은 Swagger 문서를 버전 2.0 형식(true) 또는 3.0 형식(false)으로 직렬화할지 지정합니다. Swagger 2.0을 사용하려면 true로 설정하십시오.

c.DisplayOperationId();
c.DisplayOperationId();
c.DisplayOperationId()
$vbLabelText   $csharpLabel

이 옵션은 Swagger UI에 작업 ID를 표시하여 디버깅 및 API 구조 이해에 유용할 수 있습니다.

c.OAuthClientId("swagger-ui");
c.OAuthClientId("swagger-ui");
c.OAuthClientId("swagger-ui")
$vbLabelText   $csharpLabel

API가 OAuth 인증을 사용하는 경우 Swagger UI에 대한 OAuth 클라이언트 ID를 구성할 수 있습니다.

이것들은 사용 가능한 구성 옵션의 몇 가지 예일 뿐입니다. Swashbuckle.AspNetCore 라이브러리는 매우 사용자 정의 가능하며, 다양한 옵션과 필터를 결합하여 특정 요구에 맞게 Swagger 문서를 조정할 수 있습니다. 항상 공식 문서나 개발 환경의 IntelliSense를 참조하여 사용 가능한 옵션에 대한 최신 및 포괄적인 정보를 확인하십시오.

IronPDF 소개

IronPDF 제품 개요는 PDF 문서를 읽고 생성하는 데 도움이 되는 Iron Software 웹사이트의 C# PDF 라이브러리입니다. 스타일 정보가 포함된 포맷 문서를 쉽게 PDF로 변환할 수 있습니다. IronPDF는 HTML 콘텐츠에서 손쉽게 PDF를 생성할 수 있습니다. URL에서 HTML 콘텐츠를 다운로드한 다음 PDF를 생성할 수 있습니다.

IronPDF는 웹 페이지, URL 및 HTML을 PDF로 변환하는 데 탁월하며 소스를 완벽하게 재현합니다. 보고서 및 송장과 같은 온라인 콘텐츠의 PDF 생성을 위해 이상적이며, 어떤 웹페이지의 PDF 버전을 손쉽게 생성합니다.

using IronPdf;

class Program
{
    static void Main(string[] args)
    {
        var renderer = new ChromePdfRenderer();

        // 1. Convert HTML String to PDF
        var htmlContent = "<h1>Hello, IronPDF!</h1><p>This is a PDF from an HTML string.</p>";
        var pdfFromHtmlString = renderer.RenderHtmlAsPdf(htmlContent);
        pdfFromHtmlString.SaveAs("HTMLStringToPDF.pdf");

        // 2. Convert HTML File to PDF
        var htmlFilePath = "path_to_your_html_file.html"; // Specify the path to your HTML file
        var pdfFromHtmlFile = renderer.RenderHtmlFileAsPdf(htmlFilePath);
        pdfFromHtmlFile.SaveAs("HTMLFileToPDF.pdf");

        // 3. Convert URL to PDF
        var url = "http://ironpdf.com"; // Specify the URL
        var pdfFromUrl = renderer.RenderUrlAsPdf(url);
        pdfFromUrl.SaveAs("URLToPDF.pdf");
    }
}
using IronPdf;

class Program
{
    static void Main(string[] args)
    {
        var renderer = new ChromePdfRenderer();

        // 1. Convert HTML String to PDF
        var htmlContent = "<h1>Hello, IronPDF!</h1><p>This is a PDF from an HTML string.</p>";
        var pdfFromHtmlString = renderer.RenderHtmlAsPdf(htmlContent);
        pdfFromHtmlString.SaveAs("HTMLStringToPDF.pdf");

        // 2. Convert HTML File to PDF
        var htmlFilePath = "path_to_your_html_file.html"; // Specify the path to your HTML file
        var pdfFromHtmlFile = renderer.RenderHtmlFileAsPdf(htmlFilePath);
        pdfFromHtmlFile.SaveAs("HTMLFileToPDF.pdf");

        // 3. Convert URL to PDF
        var url = "http://ironpdf.com"; // Specify the URL
        var pdfFromUrl = renderer.RenderUrlAsPdf(url);
        pdfFromUrl.SaveAs("URLToPDF.pdf");
    }
}
Imports IronPdf

Friend Class Program
	Shared Sub Main(ByVal args() As String)
		Dim renderer = New ChromePdfRenderer()

		' 1. Convert HTML String to PDF
		Dim htmlContent = "<h1>Hello, IronPDF!</h1><p>This is a PDF from an HTML string.</p>"
		Dim pdfFromHtmlString = renderer.RenderHtmlAsPdf(htmlContent)
		pdfFromHtmlString.SaveAs("HTMLStringToPDF.pdf")

		' 2. Convert HTML File to PDF
		Dim htmlFilePath = "path_to_your_html_file.html" ' Specify the path to your HTML file
		Dim pdfFromHtmlFile = renderer.RenderHtmlFileAsPdf(htmlFilePath)
		pdfFromHtmlFile.SaveAs("HTMLFileToPDF.pdf")

		' 3. Convert URL to PDF
		Dim url = "http://ironpdf.com" ' Specify the URL
		Dim pdfFromUrl = renderer.RenderUrlAsPdf(url)
		pdfFromUrl.SaveAs("URLToPDF.pdf")
	End Sub
End Class
$vbLabelText   $csharpLabel

설치

NuGet을 통해 IronPDF 설치NuGet 패키지 관리자 정보 또는 Visual Studio 설치 가이드 패키지 관리자 콘솔을 사용합니다.

패키지 관리자 콘솔에 명령어를 입력하십시오:

Install-Package IronPdf

Visual Studio 사용

![Swashbuckle ASP .NET Core (개발자를 위한 작동 방식): 그림 3 - Visual Studio에서 프로젝트를 엽니다. 도구 메뉴로 이동하여 "NuGet 패키지 관리자"를 선택한 후 "솔루션용 NuGet 패키지 관리"를 선택합니다. NuGet 패키지 관리자 인터페이스의 탐색 탭에서 "ironpdf"라는 패키지를 검색합니다. 그런 다음 최신 버전의 IronPDF를 선택하고 설치합니다.(/static-assets/pdf/blog/swashbuckle-asp-net-core/swashbuckle-asp-net-core-3.webp)

이제 웹사이트 내용을 PDF 파일로 다운로드하는 기능을 애플리케이션에 추가해 보겠습니다.

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

namespace RestFullMinimalApi.Controllers
{
    [ApiController]
    [Route("[controller]")]
    public class WeatherForecastController : ControllerBase
    {
        private static readonly string[] Summaries = new[]
        {
            "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
        };

        private readonly ILogger<WeatherForecastController> _logger;

        public WeatherForecastController(ILogger<WeatherForecastController> logger)
        {
            _logger = logger;
        }

        /// <summary>
        /// Retrieves WeatherForecast
        /// </summary>
        /// <remarks>Awesomeness!</remarks>
        /// <response code="200">Retrieved</response>
        /// <response code="404">Not found</response>
        /// <response code="500">Oops! Can't lookup your request right now</response>
        [HttpGet(Name = "GetWeatherForecast")]
        public IEnumerable<WeatherForecast> Get()
        {
            return Enumerable.Range(1, 5).Select(index => new WeatherForecast
            {
                Date = DateTime.Now.AddDays(index),
                TemperatureC = Random.Shared.Next(-20, 55),
                Summary = Summaries[Random.Shared.Next(Summaries.Length)]
            })
            .ToArray();
        }

        /// <summary>
        /// Retrieves WeatherForecast as Pdf
        /// </summary>
        /// <remarks>Awesomeness!</remarks>
        /// <response code="200">Retrieved</response>
        /// <response code="404">Not found</response>
        /// <response code="500">Oops! Can't lookup your request right now</response>
        [HttpGet("download", Name = "DownloadWeatherForecast")]
        public IActionResult GetWeatherPdf()
        {
            var results = Enumerable.Range(1, 5).Select(index => new WeatherForecast
            {
                Date = DateTime.Now.AddDays(index),
                TemperatureC = Random.Shared.Next(-20, 55),
                Summary = Summaries[Random.Shared.Next(Summaries.Length)]
            }).ToArray();

            var html = GetHtml(results);
            var renderer = new ChromePdfRenderer();
            var pdf = renderer.RenderHtmlAsPdf(html);
            var fileName = "WeatherReport.pdf";
            pdf.SaveAs(fileName);

            var stream = new FileStream(fileName, FileMode.Open);
            // Return the PDF file for download
            return new FileStreamResult(stream, "application/octet-stream") { FileDownloadName = fileName };
        }

        private static string GetHtml(WeatherForecast[] weatherForecasts)
        {
            string header = @"
<html>
<head><title>WeatherForecast</title></head>
<body>
<h1>WeatherForecast</h1>
";

            var footer = @"
</body>
</html>";

            var htmlContent = header;
            foreach (var weather in weatherForecasts)
            {
                htmlContent += $@"
    <h2>{weather.Date}</h2>
    <p>Summary: {weather.Summary}</p>
    <p>Temperature in Celsius: {weather.TemperatureC}</p>
    <p>Temperature in Fahrenheit: {weather.TemperatureF}</p>
";
            }
            htmlContent += footer;
            return htmlContent;
        }
    }

    public class WeatherForecast
    {
        public DateTime Date { get; set; }
        public int TemperatureC { get; set; }
        public string Summary { get; set; }

        public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
    }
}
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using IronPdf;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;

namespace RestFullMinimalApi.Controllers
{
    [ApiController]
    [Route("[controller]")]
    public class WeatherForecastController : ControllerBase
    {
        private static readonly string[] Summaries = new[]
        {
            "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
        };

        private readonly ILogger<WeatherForecastController> _logger;

        public WeatherForecastController(ILogger<WeatherForecastController> logger)
        {
            _logger = logger;
        }

        /// <summary>
        /// Retrieves WeatherForecast
        /// </summary>
        /// <remarks>Awesomeness!</remarks>
        /// <response code="200">Retrieved</response>
        /// <response code="404">Not found</response>
        /// <response code="500">Oops! Can't lookup your request right now</response>
        [HttpGet(Name = "GetWeatherForecast")]
        public IEnumerable<WeatherForecast> Get()
        {
            return Enumerable.Range(1, 5).Select(index => new WeatherForecast
            {
                Date = DateTime.Now.AddDays(index),
                TemperatureC = Random.Shared.Next(-20, 55),
                Summary = Summaries[Random.Shared.Next(Summaries.Length)]
            })
            .ToArray();
        }

        /// <summary>
        /// Retrieves WeatherForecast as Pdf
        /// </summary>
        /// <remarks>Awesomeness!</remarks>
        /// <response code="200">Retrieved</response>
        /// <response code="404">Not found</response>
        /// <response code="500">Oops! Can't lookup your request right now</response>
        [HttpGet("download", Name = "DownloadWeatherForecast")]
        public IActionResult GetWeatherPdf()
        {
            var results = Enumerable.Range(1, 5).Select(index => new WeatherForecast
            {
                Date = DateTime.Now.AddDays(index),
                TemperatureC = Random.Shared.Next(-20, 55),
                Summary = Summaries[Random.Shared.Next(Summaries.Length)]
            }).ToArray();

            var html = GetHtml(results);
            var renderer = new ChromePdfRenderer();
            var pdf = renderer.RenderHtmlAsPdf(html);
            var fileName = "WeatherReport.pdf";
            pdf.SaveAs(fileName);

            var stream = new FileStream(fileName, FileMode.Open);
            // Return the PDF file for download
            return new FileStreamResult(stream, "application/octet-stream") { FileDownloadName = fileName };
        }

        private static string GetHtml(WeatherForecast[] weatherForecasts)
        {
            string header = @"
<html>
<head><title>WeatherForecast</title></head>
<body>
<h1>WeatherForecast</h1>
";

            var footer = @"
</body>
</html>";

            var htmlContent = header;
            foreach (var weather in weatherForecasts)
            {
                htmlContent += $@"
    <h2>{weather.Date}</h2>
    <p>Summary: {weather.Summary}</p>
    <p>Temperature in Celsius: {weather.TemperatureC}</p>
    <p>Temperature in Fahrenheit: {weather.TemperatureF}</p>
";
            }
            htmlContent += footer;
            return htmlContent;
        }
    }

    public class WeatherForecast
    {
        public DateTime Date { get; set; }
        public int TemperatureC { get; set; }
        public string Summary { get; set; }

        public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
    }
}
Imports Microsoft.AspNetCore.Mvc
Imports Microsoft.Extensions.Logging
Imports IronPdf
Imports System
Imports System.Collections.Generic
Imports System.IO
Imports System.Linq

Namespace RestFullMinimalApi.Controllers
	<ApiController>
	<Route("[controller]")>
	Public Class WeatherForecastController
		Inherits ControllerBase

		Private Shared ReadOnly Summaries() As String = { "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching" }

		Private ReadOnly _logger As ILogger(Of WeatherForecastController)

		Public Sub New(ByVal logger As ILogger(Of WeatherForecastController))
			_logger = logger
		End Sub

		''' <summary>
		''' Retrieves WeatherForecast
		''' </summary>
		''' <remarks>Awesomeness!</remarks>
		''' <response code="200">Retrieved</response>
		''' <response code="404">Not found</response>
		''' <response code="500">Oops! Can't lookup your request right now</response>
		<HttpGet(Name := "GetWeatherForecast")>
		Public Function [Get]() As IEnumerable(Of WeatherForecast)
			Return Enumerable.Range(1, 5).Select(Function(index) New WeatherForecast With {
				.Date = DateTime.Now.AddDays(index),
				.TemperatureC = Random.Shared.Next(-20, 55),
				.Summary = Summaries(Random.Shared.Next(Summaries.Length))
			}).ToArray()
		End Function

		''' <summary>
		''' Retrieves WeatherForecast as Pdf
		''' </summary>
		''' <remarks>Awesomeness!</remarks>
		''' <response code="200">Retrieved</response>
		''' <response code="404">Not found</response>
		''' <response code="500">Oops! Can't lookup your request right now</response>
		<HttpGet("download", Name := "DownloadWeatherForecast")>
		Public Function GetWeatherPdf() As IActionResult
			Dim results = Enumerable.Range(1, 5).Select(Function(index) New WeatherForecast With {
				.Date = DateTime.Now.AddDays(index),
				.TemperatureC = Random.Shared.Next(-20, 55),
				.Summary = Summaries(Random.Shared.Next(Summaries.Length))
			}).ToArray()

			Dim html = GetHtml(results)
			Dim renderer = New ChromePdfRenderer()
			Dim pdf = renderer.RenderHtmlAsPdf(html)
			Dim fileName = "WeatherReport.pdf"
			pdf.SaveAs(fileName)

			Dim stream = New FileStream(fileName, FileMode.Open)
			' Return the PDF file for download
			Return New FileStreamResult(stream, "application/octet-stream") With {.FileDownloadName = fileName}
		End Function

		Private Shared Function GetHtml(ByVal weatherForecasts() As WeatherForecast) As String
			Dim header As String = "
<html>
<head><title>WeatherForecast</title></head>
<body>
<h1>WeatherForecast</h1>
"

			Dim footer = "
</body>
</html>"

			Dim htmlContent = header
			For Each weather In weatherForecasts
				htmlContent &= $"
    <h2>{weather.Date}</h2>
    <p>Summary: {weather.Summary}</p>
    <p>Temperature in Celsius: {weather.TemperatureC}</p>
    <p>Temperature in Fahrenheit: {weather.TemperatureF}</p>
"
			Next weather
			htmlContent &= footer
			Return htmlContent
		End Function
	End Class

	Public Class WeatherForecast
		Public Property [Date]() As DateTime
		Public Property TemperatureC() As Integer
		Public Property Summary() As String

		Public ReadOnly Property TemperatureF() As Integer
			Get
				Return 32 + CInt(Math.Truncate(TemperatureC / 0.5556))
			End Get
		End Property
	End Class
End Namespace
$vbLabelText   $csharpLabel

여기서는 날씨 데이터를 사용하여 HTML 문자열을 생성하고, 그 문자열을 사용하여 PDF 문서를 만듭니다.

HTML 콘텐츠

Swashbuckle ASP .NET Core(개발자를 위한 작동 방법): 그림 4 - 날씨 예보에 대한 HTML 콘텐츠

PDF 보고서는 이렇게 보입니다:

Swashbuckle ASP .NET Core(개발자를 위한 작동 방법): 그림 5 - HTML을 PDF로 변환한 출력 파일: WeatherReport.pdf

전체 코드는 GitHub에서 찾을 수 있습니다 - Swashbuckle 데모 소스 코드.
문서에는 체험판 라이선스에 대한 작은 워터마크가 있으며, 유효한 라이선스로 제거할 수 있습니다.

라이센스 (무료 체험 가능)

위의 코드가 작동하려면 라이선스 키가 필요합니다. 이 키를 appsettings.json 파일에 배치하십시오.

{
    "IronPdf": {
        "LicenseKey": "your license key"
    }
}

체험판 라이선스는 IronPDF 체험 등록을 완료한 개발자들에게 제공됩니다. 체험판 라이선스를 받기 위해 신용카드는 필요하지 않습니다. 이메일 주소를 등록하여 무료 체험판을 받으세요.

결론

Swashbuckle와 IronPDF를 이해하면 ASP.NET Core 애플리케이션에 API 문서화와 PDF 생성 기능을 효과적으로 통합할 수 있습니다. IronPDF는 또한 시작하기에 대한 포괄적인 문서와 다양한 PDF 생성 코드 예제를 제공합니다.

또한, 코딩 기술을 향상시키고 현대 애플리케이션 요건을 충족시키는 데 도움이 되는 Iron Software의 관련 소프트웨어 제품을 탐색할 수 있습니다.

자주 묻는 질문

ASP.NET Core에서 Swashbuckle을 사용하여 RESTful 웹 API를 문서화하려면 어떻게 해야 합니까?

Swashbuckle은 코드의 XML 주석에서 Swagger 문서를 생성하여 RESTful 웹 API를 문서화하는 데 사용할 수 있습니다. 프로젝트의 `Startup.cs` 파일에서 Swashbuckle.AspNetCore 패키지를 설치하고 구성해야 합니다.

새로운 ASP.NET Core 웹 API 프로젝트에 Swashbuckle을 설정하는 단계는 무엇입니까?

Swashbuckle을 설정하려면 Swashbuckle.AspNetCore NuGet 패키지를 설치하는 것부터 시작하십시오. 그 다음, `Startup.cs` 파일의 `ConfigureServices` 메서드에서 `services.AddSwaggerGen()`을 추가하고 `Configure` 메서드에서 `app.UseSwagger()`와 `app.UseSwaggerUI()`를 추가하여 Swagger 미들웨어를 구성하십시오.

.NET Core 애플리케이션에서 HTML 콘텐츠를 PDF로 변환하려면 어떻게 해야 합니까?

IronPDF를 사용하여 .NET Core 애플리케이션에서 HTML 콘텐츠를 PDF로 변환할 수 있습니다. 이 라이브러리는 HTML 문자열, 파일 및 URL을 PDF 문서로 변환하는 `RenderHtmlAsPdf` 및 `RenderUrlAsPdf` 같은 메서드를 제공합니다.

API 개발에서 Swashbuckle을 사용하는 장점은 무엇입니까?

Swashbuckle은 Swagger 호환 문서를 자동으로 생성하여 API 문서를 간소화하며, 명확하고 일관된 API 문서 표준 유지에 도움을 줍니다. 또한 Swagger UI를 통해 API를 탐색하고 테스트하기 위한 사용자 친화적인 인터페이스를 제공합니다.

ASP.NET Core 프로젝트에 PDF 생성 기능을 통합하려면 어떻게 해야 합니까?

ASP.NET Core 프로젝트에 PDF 생성 통합은 IronPDF를 사용하여 달성할 수 있습니다. NuGet를 통해 IronPDF 라이브러리를 설치하고 다양한 콘텐츠 유형에서 PDF를 생성하기 위해 그 메서드를 사용하십시오. 프로젝트에 필수적인 `using` 지시문과 any 라이센스 키 포함이 필요합니다.

Swashbuckle에서 Swagger 문서를 커스터마이징하기 위한 구성 옵션은 무엇입니까?

Swashbuckle은 Swagger 문서를 커스터마이징할 수 있는 다양한 구성 옵션을 제공합니다. API 버전 설정, XML 주석 활성화, 매개변수 명명 규칙 정의, Swagger UI의 외관 및 동작 커스터마이징 등이 포함됩니다.

ASP.NET Core 프로젝트에서 Swashbuckle 사용 시 흔히 발생하는 문제를 해결하려면 어떻게 해야 합니까?

Swashbuckle과 관련된 일반적인 문제는 프로젝트 속성에서 XML 문서화가 활성화되어 있는지 확인하고, 패키지 버전이 정확한지 점검하며, `Startup.cs` 파일에 올바르게 설정되어 있는지, 미들웨어의 순서가 정확한지 검증함으로써 해결할 수 있습니다.

C#에서 PDF를 생성하는 IronPDF의 기능은 무엇입니까?

IronPDF는 HTML, URL, ASP.NET 콘텐츠를 PDF로 변환하고, 헤더 및 푸터 추가, PDF 병합, 기존 PDF 파일 조작과 같은 기능을 제공합니다. C# 프로젝트에서 PDF 작업을 처리하기 위한 종합적인 라이브러리입니다.

IronPDF는 상업적 사용을 위한 라이센싱을 어떻게 지원합니까?

IronPDF는 상업용 라이선스 키를 통해 라이선싱을 지원합니다. 무료 체험판으로 IronPDF를 시도하고 프로젝트 구성 파일인 `appsettings.json`의 `IronPDF` 섹션에 라이선스 키를 포함할 수 있습니다.

제이콥 멜러, 팀 아이언 최고기술책임자
최고기술책임자

제이콥 멜러는 Iron Software의 최고 기술 책임자(CTO)이자 C# PDF 기술을 개척한 선구적인 엔지니어입니다. Iron Software의 핵심 코드베이스를 최초로 개발한 그는 창립 초기부터 회사의 제품 아키텍처를 설계해 왔으며, CEO인 캐머런 리밍턴과 함께 회사를 NASA, 테슬라, 그리고 전 세계 정부 기관에 서비스를 제공하는 50명 이상의 직원을 보유한 기업으로 성장시켰습니다.

제이콥은 맨체스터 대학교에서 토목공학 학사 학위(BEng)를 최우등으로 취득했습니다(1998~2001). 1999년 런던에서 첫 소프트웨어 회사를 설립하고 2005년 첫 .NET 컴포넌트를 개발한 후, 마이크로소프트 생태계 전반에 걸쳐 복잡한 문제를 해결하는 데 전문성을 발휘해 왔습니다.

그의 대표 제품인 IronPDF 및 Iron Suite .NET 라이브러리는 전 세계적으로 3천만 건 이상의 NuGet 설치 수를 기록했으며, 그의 핵심 코드는 전 세계 개발자들이 사용하는 다양한 도구에 지속적으로 활용되고 있습니다. 25년의 실무 경험과 41년의 코딩 전문성을 바탕으로, 제이콥은 차세대 기술 리더들을 양성하는 동시에 기업 수준의 C#, Java, Python PDF 기술 혁신을 주도하는 데 주력하고 있습니다.

아이언 서포트 팀

저희는 주 5일, 24시간 온라인으로 운영합니다.
채팅
이메일
전화해