π Π‘ΠΎΠ·Π΄Π°Π΅ΠΌ ΠΊΡΠ°ΡΠΈΠ²ΡΡ Π΄ΠΎΠΊΡΠΌΠ΅Π½ΡΠ°ΡΠΈΡ API Ρ ΠΏΠΎΠΌΠΎΡΡΡ Scalar Π² ASP.NET Core
Π£ΡΡΠ°Π»ΠΈ ΠΎΡ ΡΠΊΡΡΠ½ΠΎΠ³ΠΎ Swagger UI? ΠΠΎΠ±ΡΠΎ ΠΏΠΎΠΆΠ°Π»ΠΎΠ²Π°ΡΡ Π² Π½ΠΎΠ²ΡΠΉ ΠΌΠΈΡ API-Π΄ΠΎΠΊΡΠΌΠ΅Π½ΡΠ°ΡΠΈΠΈ Ρ ΡΡΠΊΠΈΠΌ ΠΈ ΡΠΎΠ²ΡΠ΅ΠΌΠ΅Π½Π½ΡΠΌ ΠΈΠ½ΡΠ΅ΡΡΠ΅ΠΉΡΠΎΠΌ Scalar, ΠΊΠΎΡΠΎΡΡΠΉ ΠΈΠ·ΠΌΠ΅Π½ΠΈΡ Π²Π°ΡΠ΅ ΠΏΡΠ΅Π΄ΡΡΠ°Π²Π»Π΅Π½ΠΈΠ΅ ΠΎ ΡΠΎΠΌ, ΠΊΠ°ΠΊ Π΄ΠΎΠ»ΠΆΠ½Π° Π²ΡΠ³Π»ΡΠ΄Π΅ΡΡ Π΄ΠΎΠΊΡΠΌΠ΅Π½ΡΠ°ΡΠΈΡ API!
Scalar β ΡΡΠΎ ΠΈΠ½ΡΡΡΡΠΌΠ΅Π½Ρ, ΠΊΠΎΡΠΎΡΡΠΉ ΠΏΠΎΠΌΠΎΠ³Π°Π΅Ρ ΡΠΎΠ·Π΄Π°Π²Π°ΡΡ ΠΏΡΠΈΠ²Π»Π΅ΠΊΠ°ΡΠ΅Π»ΡΠ½ΡΡ Π΄ΠΎΠΊΡΠΌΠ΅Π½ΡΠ°ΡΠΈΡ Π΄Π»Ρ Π½Π°ΡΠΈΡ API. Π ΠΎΡΠ»ΠΈΡΠΈΠ΅ ΠΎΡ ΡΡΠ°Π½Π΄Π°ΡΡΠ½ΠΎΠΉ Π΄ΠΎΠΊΡΠΌΠ΅Π½ΡΠ°ΡΠΈΠΈ Swagger, ΠΊΠΎΡΠΎΡΠ°Ρ ΠΌΠΎΠΆΠ΅Ρ Π²ΡΠ³Π»ΡΠ΄Π΅ΡΡ Π½Π΅ΠΌΠ½ΠΎΠ³ΠΎ ΡΡΡΠ°ΡΠ΅Π²ΡΠ΅ΠΉ, Scalar ΠΏΡΠ΅Π΄Π»Π°Π³Π°Π΅Ρ ΡΠ²Π΅ΠΆΠΈΠΉ, ΡΠΎΠ²ΡΠ΅ΠΌΠ΅Π½Π½ΡΠΉ ΠΈΠ½ΡΠ΅ΡΡΠ΅ΠΉΡ. ΠΠ»Π°Π³ΠΎΠ΄Π°ΡΡ Π°ΠΊΠΊΡΡΠ°ΡΠ½ΠΎΠΌΡ Π΄ΠΈΠ·Π°ΠΉΠ½Ρ ΡΠ°Π·ΡΠ°Π±ΠΎΡΡΠΈΠΊΠ°ΠΌ ΠΏΡΠΎΡΠ΅ Π½Π°Ρ ΠΎΠ΄ΠΈΡΡ Π½ΡΠΆΠ½ΡΠ΅ API Π΄Π»Ρ ΡΠ΅ΡΡΠΈΡΠΎΠ²Π°Π½ΠΈΡ.
Π ΡΡΠΎΠΉ ΡΡΠ°ΡΡΠ΅ ΠΌΡ ΡΠ°ΡΡΠΌΠΎΡΡΠΈΠΌ, ΠΊΠ°ΠΊ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΡ Scalar Π΄Π»Ρ Π΄ΠΎΠΊΡΠΌΠ΅Π½ΡΠΈΡΠΎΠ²Π°Π½ΠΈΡ API Π² ASP.NET Core Web API, ΡΡΠΎΠ±Ρ Π·Π°ΠΌΠ΅Π½ΠΈΡΡ ΡΡΠ°Π½Π΄Π°ΡΡΠ½ΡΠΉ Swagger UI.
ΠΠ°Π½Π½Π°Ρ ΡΡΠ°ΡΡΡ ΡΠ²Π»ΡΠ΅ΡΡΡ ΠΏΠ΅ΡΠ΅Π²ΠΎΠ΄ΠΎΠΌ Π΄ΡΡΠ³ΠΎΠΉ ΡΡΠ°ΡΡΠΈ. Π‘ ΠΎΡΠΈΠ³ΠΈΠ½Π°Π»ΠΎΠΌ Π²Ρ ΠΌΠΎΠΆΠ΅ΡΠ΅ ΠΎΠ·Π½Π°ΠΊΠΎΠΌΠΈΡΡΡΡ ΠΏΠΎ ΡΡΡΠ»ΠΊΠ΅.
Π£ΡΡΠ°Π½ΠΎΠ²ΠΊΠ° Scalar
ΠΡΠΊΡΠΎΠΉΡΠ΅ NuGet Package Manager, Π½Π°ΠΉΠ΄ΠΈΡΠ΅ ΠΈ ΡΡΡΠ°Π½ΠΎΠ²ΠΈΡΠ΅ ΠΏΠ°ΠΊΠ΅Ρ Scalar.AspNetCore:
ΠΠ°ΡΡΡΠΎΠΉΠΊΠ° Scalar
ΠΡΠΊΡΠΎΠΉΡΠ΅ ΡΠ°ΠΉΠ» Program.cs
ΠΈ Π·Π°ΠΌΠ΅Π½ΠΈΡΠ΅ ΠΊΠΎΠ½ΡΠΈΠ³ΡΡΠ°ΡΠΈΡ Swagger ΠΏΠΎ ΡΠΌΠΎΠ»ΡΠ°Π½ΠΈΡ.
ΠΡΠ»ΠΎ ΡΠ°ΠΊ:
if (app.Environment.IsDevelopment()) { app.UseSwagger(); app.UseSwaggerUI(); }
Π Π΄ΠΎΠ»ΠΆΠ½ΠΎ ΡΡΠ°ΡΡ ΡΠ°ΠΊ:
app.UseSwagger(opt => { opt.RouteTemplate = "openapi/{documentName}.json"; }); app.MapScalarApiReference(opt => { opt.Title = "Scalar Example"; opt.Theme = ScalarTheme.Mars; opt.DefaultHttpClient = new(ScalarTarget.Http, ScalarClient.Http11); });
ΠΡΡΠ΅Π½ΡΠΈΡΠΈΠΊΠ°ΡΠΈΡ Bearer
ΠΡ ΡΠ°ΠΊΠΆΠ΅ ΠΌΠΎΠΆΠ΅ΠΌ Π΄ΠΎΠ±Π°Π²ΠΈΡΡ Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΎΠΊ Π°ΡΡΠ΅Π½ΡΠΈΡΠΈΠΊΠ°ΡΠΈΠΈ Bearer Π² Π΄ΠΎΠΊΡΠΌΠ΅Π½ΡΠ°ΡΠΈΡ Scalar. ΠΡΠΎΡΡΠΎ Π·Π°ΠΌΠ΅Π½ΠΈΡΠ΅ Π² Program.cs
ΠΊΠΎΠ½ΡΠΈΠ³ΡΡΠ°ΡΠΈΡ builder.Services.AddSwaggerGen();
Π½Π° ΡΠ°ΠΊΡΡ:
builder.Services.AddSwaggerGen(opt => { opt.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme { BearerFormat = "JWT", Description = "JWT Authorization header using the Bearer scheme.", Name = "Authorization", In = ParameterLocation.Header, Type = SecuritySchemeType.Http, Scheme = "Bearer" }); opt.AddSecurityRequirement(new OpenApiSecurityRequirement { { new OpenApiSecurityScheme { Reference = new OpenApiReference { Id = "Bearer", Type = ReferenceType.SecurityScheme } }, Array.Empty<string>() } }); });
ΠΠΈΠΆΠ΅ ΠΏΡΠΈΠ²Π΅Π΄ΡΠ½ ΠΏΠΎΠ»Π½ΡΠΉ ΡΠ°ΠΉΠ» Program.cs
Ρ Π½ΡΠΆΠ½ΡΠΌΠΈ ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΡΠΌΠΈ:
using Microsoft.OpenApi.Models; using Scalar.AspNetCore; var builder = WebApplication.CreateBuilder(args); builder.Services.AddControllers(); builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(opt => { opt.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme { BearerFormat = "JWT", Description = "JWT Authorization header using the Bearer scheme.", Name = "Authorization", In = ParameterLocation.Header, Type = SecuritySchemeType.Http, Scheme = "Bearer" }); opt.AddSecurityRequirement(new OpenApiSecurityRequirement { { new OpenApiSecurityScheme { Reference = new OpenApiReference { Id = "Bearer", Type = ReferenceType.SecurityScheme } }, Array.Empty<string>() } }); }); var app = builder.Build(); app.UseSwagger(opt => { opt.RouteTemplate = "openapi/{documentName}.json"; }); app.MapScalarApiReference(opt => { opt.Title = "Scalar Example"; opt.Theme = ScalarTheme.Mars; opt.DefaultHttpClient = new(ScalarTarget.Http, ScalarClient.Http11); }); app.UseHttpsRedirection(); app.UseAuthorization(); app.MapControllers(); app.Run();
ΠΠ°ΡΡΡΠΎΠΉΠΊΠΈ Π·Π°ΠΏΡΡΠΊΠ°
Π§ΡΠΎΠ±Ρ Scalar Π°Π²ΡΠΎΠΌΠ°ΡΠΈΡΠ΅ΡΠΊΠΈ ΠΎΡΠΊΡΡΠ²Π°Π»ΡΡ ΠΏΡΠΈ Π·Π°ΠΏΡΡΠΊΠ΅ ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΡ, Π½ΡΠΆΠ½ΠΎ ΡΠΊΠΎΡΡΠ΅ΠΊΡΠΈΡΠΎΠ²Π°ΡΡ ΡΠ°ΠΉΠ» LaunchSettings.json
, ΠΊΠΎΡΠΎΡΡΠΉ Π½Π°Ρ
ΠΎΠ΄ΠΈΡΡΡ Π² ΠΏΠ°ΠΏΠΊΠ΅ Properties.
ΠΡΠΊΡΠΎΠΉΡΠ΅ LaunchSettings.json
ΠΈ Π·Π°ΠΌΠ΅Π½ΠΈΡΠ΅ "launchUrl": "swagger"
Π½Π° "launchUrl": "scalar/v1
":
{ "$schema": "http://json.schemastore.org/launchsettings.json", "iisSettings": { "windowsAuthentication": false, "anonymousAuthentication": true, "iisExpress": { "applicationUrl": "http://localhost:39471", "sslPort": 44375 } }, "profiles": { "http": { "commandName": "Project", "dotnetRunMessages": true, "launchBrowser": true, "launchUrl": "scalar/v1", "applicationUrl": "http://localhost:5290", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" } }, "https": { "commandName": "Project", "dotnetRunMessages": true, "launchBrowser": true, "launchUrl": "scalar/v1", "applicationUrl": "https://localhost:7242;http://localhost:5290", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" } }, "IIS Express": { "commandName": "IISExpress", "launchBrowser": true, "launchUrl": "scalar/v1", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" } } } }
ΠΠ°ΠΏΡΡΠΊ ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΡ
Π’Π΅ΠΏΠ΅ΡΡ Π·Π°ΠΏΡΡΠΊΠ°Π΅ΠΌ ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅:
ΠΡΠΈΠΌΠ΅Ρ ΡΠ΅ΡΡΠΎΠ²ΠΎΠ³ΠΎ Π·Π°ΠΏΡΠΎΡΠ°:
ΠΠ°ΡΠ° Π΄ΠΎΠΊΡΠΌΠ΅Π½ΡΠ°ΡΠΈΡ Π΄Π»Ρ API ΡΠ΅ΠΏΠ΅ΡΡ Π²ΡΠ³Π»ΡΠ΄ΠΈΡ ΠΏΠΎΡΡΡΡΠ°ΡΡΠ΅!
ΠΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΠ΅ Scalar Π΄Π»Ρ Π΄ΠΎΠΊΡΠΌΠ΅Π½ΡΠΈΡΠΎΠ²Π°Π½ΠΈΡ API Π΄Π°ΡΡ ΠΌΠ½ΠΎΠΆΠ΅ΡΡΠ²ΠΎ ΠΏΡΠ΅ΠΈΠΌΡΡΠ΅ΡΡΠ² ΠΈ ΡΠΏΡΠΎΡΠ°Π΅Ρ ΡΠ°Π±ΠΎΡΡ ΡΠ°Π·ΡΠ°Π±ΠΎΡΡΠΈΠΊΠΎΠ². ΠΠ½ΡΠ΅ΡΡΠ΅ΠΉΡ Π²ΡΠ³Π»ΡΠ΄ΠΈΡ ΠΊΡΠ°ΡΠΈΠ²ΠΎ, Π² Π±ΠΎΠΊΠΎΠ²ΠΎΠΌ ΠΌΠ΅Π½Ρ Π»Π΅Π³ΠΊΠΎ Π½Π°ΠΉΡΠΈ Π½ΡΠΆΠ½ΡΠ΅ ΡΠ°Π·Π΄Π΅Π»Ρ Π±Π΅Π· ΠΏΠΎΡΡΠΎΡΠ½Π½ΠΎΠΉ ΠΏΡΠΎΠΊΡΡΡΠΊΠΈ, Π° ΡΡΠ½ΠΊΡΠΈΡ Test Request
ΠΏΠΎΠ·Π²ΠΎΠ»ΡΠ΅Ρ ΡΡΠ°Π·Ρ ΡΠ΅ΡΡΠΈΡΠΎΠ²Π°ΡΡ ΡΠ½Π΄ΠΏΠΎΠΈΠ½ΡΡ ΠΈΠ· Π΄ΠΎΠΊΡΠΌΠ΅Π½ΡΠ°ΡΠΈΠΈ.
ΠΡΡ ΠΎΠ΄Π½ΡΠΉ ΠΊΠΎΠ΄ ΠΏΡΠΎΠ΅ΠΊΡΠ° ΠΌΠΎΠΆΠ½ΠΎ Π½Π°ΠΉΡΠΈ Π·Π΄Π΅ΡΡ.