From f7a6e775545c9f00c42c6e5edd361a399e3666f4 Mon Sep 17 00:00:00 2001
From: Pierre Ferreira
Date: Tue, 7 Mar 2023 19:26:03 +0100
Subject: [PATCH 1/2] =?UTF-8?q?:bookmark:=20D=C3=A9but=20du=20versionning,?=
=?UTF-8?q?=20probl=C3=A8me=20au=20niveau=20de=20swagger,=20voir=20le=20co?=
=?UTF-8?q?de=20du=20prof=20ou=20tenter=20un=20SwaggerOption,=20qui=20rest?=
=?UTF-8?q?e=20compliquer.?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
Sources/API_LoL/API_LoL.csproj | 2 +
.../Controllers/ChampionsController.cs | 4 +-
.../ChampionsControllerVersioned.cs | 106 ++++++++++++++++++
Sources/API_LoL/Program.cs | 41 ++++++-
4 files changed, 149 insertions(+), 4 deletions(-)
create mode 100644 Sources/API_LoL/Controllers/ChampionsControllerVersioned.cs
diff --git a/Sources/API_LoL/API_LoL.csproj b/Sources/API_LoL/API_LoL.csproj
index 5ada54d..a8c4de7 100644
--- a/Sources/API_LoL/API_LoL.csproj
+++ b/Sources/API_LoL/API_LoL.csproj
@@ -9,6 +9,8 @@
+
+
diff --git a/Sources/API_LoL/Controllers/ChampionsController.cs b/Sources/API_LoL/Controllers/ChampionsController.cs
index 9aefc31..acad597 100644
--- a/Sources/API_LoL/Controllers/ChampionsController.cs
+++ b/Sources/API_LoL/Controllers/ChampionsController.cs
@@ -9,7 +9,9 @@ using System.CodeDom.Compiler;
namespace API_LoL.Controllers
{
- [Route("api/[controller]")]
+ //[Route("api/[controller]")]
+ [ApiVersion("1.0")]
+ [Route("api/v{version:apiVersion}/[controller]")]
[ApiController]
public class ChampionsController : ControllerBase
{
diff --git a/Sources/API_LoL/Controllers/ChampionsControllerVersioned.cs b/Sources/API_LoL/Controllers/ChampionsControllerVersioned.cs
new file mode 100644
index 0000000..e8b3a24
--- /dev/null
+++ b/Sources/API_LoL/Controllers/ChampionsControllerVersioned.cs
@@ -0,0 +1,106 @@
+using Microsoft.AspNetCore.Mvc;
+using Model;
+using StubLib;
+using DTO;
+using DTO.Mapper;
+using System.CodeDom.Compiler;
+
+namespace API_LoL.Controllers
+{
+ [ApiVersion("2.0")]
+ [ApiVersion("2.2")]
+ [Route("api/v{version:apiVersion}/versioned")]
+ [ApiController]
+ public class ChampionsControllerVersioned : ControllerBase
+ {
+ public ChampionsControllerVersioned(IDataManager Manager)
+ {
+ this.ChampionsManager = Manager.ChampionsMgr;
+ }
+
+ private IChampionsManager ChampionsManager;
+
+ // GET api//5
+
+ [HttpGet]
+ public async Task Get(String? name = null, String? skill = null, String? characteristic = null, int index = 0, int size = 10)
+ {
+ if (size - index > 10)
+ {
+ return BadRequest();
+ }
+ if (!string.IsNullOrEmpty(name))
+ {
+ var list = await ChampionsManager.GetItemsByName(name, index, size);
+ if (list.Count() != 0)
+ {
+ return Ok(list.Select(champion => champion?.ToDTO()));
+ }
+ else { return NoContent(); }
+ }
+ else if (!string.IsNullOrEmpty(skill))
+ {
+ var list = await ChampionsManager.GetItemsBySkill(skill, index, size);
+ if (list.Count() != 0)
+ {
+ return Ok(list.Select(champion => champion?.ToDTO()));
+ }
+ else { return NoContent(); }
+ }
+ else if (!string.IsNullOrEmpty(characteristic))
+ {
+ var list = await ChampionsManager.GetItems(index, size);
+ if (list.Count() != 0)
+ {
+ return Ok(list.Select(champion => champion?.ToDTO()));
+ }
+ else { return NoContent(); }
+ }
+ else
+ {
+ var list = await ChampionsManager.GetItems(index, size);
+ if (list.Count() != 0)
+ {
+ return Ok(list.Select(champion => champion?.ToDTO()));
+ }
+ else { return NoContent(); }
+ }
+ }
+
+
+ // POST api/
+ [HttpPost]
+ public async Task Post(ChampionDTO champion)
+ {
+ if (champion == null)
+ {
+ return UnprocessableEntity();
+ }
+ else
+ {
+ await ChampionsManager.AddItem(champion.ToChampion());
+ return CreatedAtAction("Post", champion);
+ }
+ }
+
+ // PUT api//5
+ [HttpPut("{id}")]
+ public void Put(int id, [FromBody] string value)
+ {
+ }
+
+ // DELETE api//5
+ [HttpDelete("{id}")]
+ public void Delete(int id)
+ {
+ }
+
+
+ ///---------- Versioning ----------///
+ [HttpGet]
+ public string GetThatOnlySayHello() => "Hello v2.0!";
+
+ [HttpGet, MapToApiVersion("2.2")]
+ public string GetThatOnlySayHelloV2() => "Hello but i'm from v2.2!";
+ }
+}
diff --git a/Sources/API_LoL/Program.cs b/Sources/API_LoL/Program.cs
index d4fb3b8..b8f9f47 100644
--- a/Sources/API_LoL/Program.cs
+++ b/Sources/API_LoL/Program.cs
@@ -1,24 +1,59 @@
+using Microsoft.AspNetCore.Mvc.ApiExplorer;
+using Microsoft.AspNetCore.Mvc.Versioning;
using Model;
using StubLib;
var builder = WebApplication.CreateBuilder(args);
-// Add services to the container.
-builder.Services.AddControllers();
+//Versioning
+
+///NOT WORKING WHEN CHANGING VERSIONS :
+/// voir sur https://blog.christian-schou.dk/how-to-use-api-versioning-in-net-core-web-api/ rubrique "Configure SwaggerOptions"
+/// (mais requiere l'injection de dépendance).
+/// Sinon, code plus simple disponible par le prof
+
+
+
+// Add ApiExplorer to discover versions
+builder.Services.AddVersionedApiExplorer(setup =>
+{
+ setup.GroupNameFormat = "'v'VVV";
+ setup.SubstituteApiVersionInUrl = true;
+});
+
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
+
+builder.Services.AddApiVersioning(o => o.ApiVersionReader = new UrlSegmentApiVersionReader());
+
+// Add services to the container.
+builder.Services.AddControllers();
+
+
+
builder.Services.AddScoped();
var app = builder.Build();
+var apiVersionDescriptionProvider = app.Services.GetRequiredService();
+
+
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
- app.UseSwaggerUI();
+ app.UseSwaggerUI(options =>
+ {
+
+ foreach (var description in apiVersionDescriptionProvider.ApiVersionDescriptions)
+ {
+ options.SwaggerEndpoint($"/swagger/{description.GroupName}/swagger.json",
+ description.GroupName.ToUpperInvariant());
+ }
+ });
}
app.UseHttpsRedirection();
From 0260d4afd0328909204459ba5125aaf1f82f0f25 Mon Sep 17 00:00:00 2001
From: Pierre Ferreira
Date: Mon, 13 Mar 2023 16:23:27 +0100
Subject: [PATCH 2/2] :bookmark: fin du versionning ! 3 versions differentes :
V1, V2, V2.2 !
---
.../ChampionsControllerVersioned.cs | 140 +++++++++---------
Sources/API_LoL/Program.cs | 6 +
Sources/API_LoL/SwaggerOptions.cs | 61 ++++++++
3 files changed, 138 insertions(+), 69 deletions(-)
create mode 100644 Sources/API_LoL/SwaggerOptions.cs
diff --git a/Sources/API_LoL/Controllers/ChampionsControllerVersioned.cs b/Sources/API_LoL/Controllers/ChampionsControllerVersioned.cs
index e8b3a24..87598d9 100644
--- a/Sources/API_LoL/Controllers/ChampionsControllerVersioned.cs
+++ b/Sources/API_LoL/Controllers/ChampionsControllerVersioned.cs
@@ -22,84 +22,86 @@ namespace API_LoL.Controllers
// GET api//5
- [HttpGet]
- public async Task Get(String? name = null, String? skill = null, String? characteristic = null, int index = 0, int size = 10)
- {
- if (size - index > 10)
- {
- return BadRequest();
- }
- if (!string.IsNullOrEmpty(name))
- {
- var list = await ChampionsManager.GetItemsByName(name, index, size);
- if (list.Count() != 0)
- {
- return Ok(list.Select(champion => champion?.ToDTO()));
- }
- else { return NoContent(); }
- }
- else if (!string.IsNullOrEmpty(skill))
- {
- var list = await ChampionsManager.GetItemsBySkill(skill, index, size);
- if (list.Count() != 0)
- {
- return Ok(list.Select(champion => champion?.ToDTO()));
- }
- else { return NoContent(); }
- }
- else if (!string.IsNullOrEmpty(characteristic))
- {
- var list = await ChampionsManager.GetItems(index, size);
- if (list.Count() != 0)
- {
- return Ok(list.Select(champion => champion?.ToDTO()));
- }
- else { return NoContent(); }
- }
- else
- {
- var list = await ChampionsManager.GetItems(index, size);
- if (list.Count() != 0)
- {
- return Ok(list.Select(champion => champion?.ToDTO()));
- }
- else { return NoContent(); }
- }
- }
+ //[HttpGet]
+ //public async Task Get(String? name = null, String? skill = null, String? characteristic = null, int index = 0, int size = 10)
+ //{
+ // if (size - index > 10)
+ // {
+ // return BadRequest();
+ // }
+ // if (!string.IsNullOrEmpty(name))
+ // {
+ // var list = await ChampionsManager.GetItemsByName(name, index, size);
+ // if (list.Count() != 0)
+ // {
+ // return Ok(list.Select(champion => champion?.ToDTO()));
+ // }
+ // else { return NoContent(); }
+ // }
+ // else if (!string.IsNullOrEmpty(skill))
+ // {
+ // var list = await ChampionsManager.GetItemsBySkill(skill, index, size);
+ // if (list.Count() != 0)
+ // {
+ // return Ok(list.Select(champion => champion?.ToDTO()));
+ // }
+ // else { return NoContent(); }
+ // }
+ // else if (!string.IsNullOrEmpty(characteristic))
+ // {
+ // var list = await ChampionsManager.GetItems(index, size);
+ // if (list.Count() != 0)
+ // {
+ // return Ok(list.Select(champion => champion?.ToDTO()));
+ // }
+ // else { return NoContent(); }
+ // }
+ // else
+ // {
+ // var list = await ChampionsManager.GetItems(index, size);
+ // if (list.Count() != 0)
+ // {
+ // return Ok(list.Select(champion => champion?.ToDTO()));
+ // }
+ // else { return NoContent(); }
+ // }
+ //}
- // POST api/
- [HttpPost]
- public async Task Post(ChampionDTO champion)
- {
- if (champion == null)
- {
- return UnprocessableEntity();
- }
- else
- {
- await ChampionsManager.AddItem(champion.ToChampion());
- return CreatedAtAction("Post", champion);
- }
- }
+ //// POST api/
+ //[HttpPost]
+ //public async Task Post(ChampionDTO champion)
+ //{
+ // if (champion == null)
+ // {
+ // return UnprocessableEntity();
+ // }
+ // else
+ // {
+ // await ChampionsManager.AddItem(champion.ToChampion());
+ // return CreatedAtAction("Post", champion);
+ // }
+ //}
- // PUT api//5
- [HttpPut("{id}")]
- public void Put(int id, [FromBody] string value)
- {
- }
+ //// PUT api//5
+ //[HttpPut("{id}")]
+ //public void Put(int id, [FromBody] string value)
+ //{
+ //}
- // DELETE api//5
- [HttpDelete("{id}")]
- public void Delete(int id)
- {
- }
+ //// DELETE api//5
+ //[HttpDelete("{id}")]
+ //public void Delete(int id)
+ //{
+ //}
///---------- Versioning ----------///
- [HttpGet]
+ [HttpGet, MapToApiVersion("2.0")]
public string GetThatOnlySayHello() => "Hello v2.0!";
+
+ //! FIXME : not working, mais avec la version 2.0 ca marche !
[HttpGet, MapToApiVersion("2.2")]
public string GetThatOnlySayHelloV2() => "Hello but i'm from v2.2!";
}
diff --git a/Sources/API_LoL/Program.cs b/Sources/API_LoL/Program.cs
index b8f9f47..c192eac 100644
--- a/Sources/API_LoL/Program.cs
+++ b/Sources/API_LoL/Program.cs
@@ -1,3 +1,4 @@
+using API_LoL;
using Microsoft.AspNetCore.Mvc.ApiExplorer;
using Microsoft.AspNetCore.Mvc.Versioning;
using Model;
@@ -26,6 +27,8 @@ builder.Services.AddVersionedApiExplorer(setup =>
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
+builder.Services.ConfigureOptions();
+
builder.Services.AddApiVersioning(o => o.ApiVersionReader = new UrlSegmentApiVersionReader());
@@ -36,6 +39,9 @@ builder.Services.AddControllers();
builder.Services.AddScoped();
+
+
+
var app = builder.Build();
var apiVersionDescriptionProvider = app.Services.GetRequiredService();
diff --git a/Sources/API_LoL/SwaggerOptions.cs b/Sources/API_LoL/SwaggerOptions.cs
new file mode 100644
index 0000000..46ad759
--- /dev/null
+++ b/Sources/API_LoL/SwaggerOptions.cs
@@ -0,0 +1,61 @@
+using Microsoft.AspNetCore.Mvc.ApiExplorer;
+using Microsoft.Extensions.Options;
+using Microsoft.OpenApi.Models;
+using Swashbuckle.AspNetCore.SwaggerGen;
+
+namespace API_LoL
+{
+ public class ConfigureSwaggerOptions : IConfigureNamedOptions
+ {
+ private readonly IApiVersionDescriptionProvider _provider;
+
+ public ConfigureSwaggerOptions(IApiVersionDescriptionProvider provider)
+ {
+ _provider = provider;
+ }
+
+ ///
+ /// Configure each API discovered for Swagger Documentation
+ ///
+ ///
+ public void Configure(SwaggerGenOptions options)
+ {
+ // add swagger document for every API version discovered
+ foreach (var description in _provider.ApiVersionDescriptions)
+ {
+ options.SwaggerDoc(description.GroupName, CreateVersionInfo(description));
+ }
+ }
+
+ ///
+ /// Configure Swagger Options. Inherited from the Interface
+ ///
+ ///
+ ///
+ public void Configure(string name, SwaggerGenOptions options)
+ {
+ Configure(options);
+ }
+
+ ///
+ /// Create information about the version of the API
+ ///
+ ///
+ /// Information about the API
+ private OpenApiInfo CreateVersionInfo(ApiVersionDescription desc)
+ {
+ var info = new OpenApiInfo()
+ {
+ Title = ".NET Core (.NET 6) Web API",
+ Version = desc.ApiVersion.ToString()
+ };
+
+ if (desc.IsDeprecated)
+ {
+ info.Description += " This API version has been deprecated. Please use one of the new APIs available from the explorer.";
+ }
+
+ return info;
+ }
+ }
+}