Skip to content

Commit 6fcc916

Browse files
committed
Add Swagger Support
1 parent 89353de commit 6fcc916

File tree

5 files changed

+142
-21
lines changed

5 files changed

+142
-21
lines changed

src/AlbumViewerNetCore/Controllers/AccountController.cs

+20-1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,14 @@
1818

1919
namespace AlbumViewerAspNetCore
2020
{
21+
/// <summary>
22+
/// Token Authentication class
23+
///
24+
/// This class uses a manually created bearer token via Authenticate
25+
/// that is used to validate each request. If validated the User.Identity
26+
/// is updated as appropriate and can be used in [Authorize] access control
27+
/// or manual token validation by the APIs in this class.
28+
/// </summary>
2129
[Authorize()]
2230
[ServiceFilter(typeof(ApiExceptionFilter))]
2331
public class AccountController : Controller
@@ -44,6 +52,8 @@ public AccountController(AccountRepository actRepo,
4452
/// </summary>
4553
/// <param name="loginUser"></param>
4654
/// <returns></returns>
55+
/// <response code="200">Authenticated</response>
56+
/// <response code="401">Invalid or missing credentials</response>
4757
[AllowAnonymous]
4858
[HttpPost]
4959
[Route("api/authenticate")]
@@ -82,7 +92,11 @@ public async Task<object> Authenticate([FromBody] User loginUser)
8292
};
8393
}
8494

85-
95+
/// <summary>
96+
/// Logs out the current user by immediately expiring the user's
97+
/// active token.
98+
/// </summary>
99+
/// <returns></returns>
86100
[AllowAnonymous]
87101
[HttpGet]
88102
[Route("api/logout")]
@@ -97,6 +111,10 @@ public bool Logout()
97111
return true;
98112
}
99113

114+
/// <summary>
115+
/// Returns true or false depending on whether user is authenticated.
116+
/// </summary>
117+
/// <returns></returns>
100118
[HttpGet]
101119
[Route("api/isAuthenticated")]
102120
public bool IsAuthenthenticated()
@@ -145,6 +163,7 @@ private void RemoveExpiredTokens()
145163
/// <returns></returns>
146164
[AllowAnonymous]
147165
[HttpPost]
166+
[Obsolete("Left here only for reference. Use Token Authentication instead.")]
148167
[Route("api/login")]
149168
public async Task<bool> Login([FromBody] User loginUser)
150169
{

src/AlbumViewerNetCore/Controllers/AlbumViewerApiController.cs

+73-10
Original file line numberDiff line numberDiff line change
@@ -51,19 +51,17 @@ public AlbumViewerApiController(
5151
HostingEnv = env;
5252
}
5353

54-
5554

56-
57-
[HttpGet]
58-
[Route("api/throw")]
59-
public object Throw()
60-
{
61-
throw new InvalidOperationException("This is an unhandled exception");
62-
}
63-
64-
6555
#region albums
6656

57+
/// <summary>
58+
/// A list of albums with detail artist data
59+
/// </summary>
60+
/// <param name="page"></param>
61+
/// <param name="pageSize"></param>
62+
/// <returns></returns>
63+
/// <response code="200">Album List</response>
64+
/// <response code="500">Failed to retrieve albums</response>
6765
[HttpGet]
6866
[Route("api/albums")]
6967
public async Task<IEnumerable<Album>> GetAlbums(int page = -1, int pageSize = 15)
@@ -72,12 +70,23 @@ public async Task<IEnumerable<Album>> GetAlbums(int page = -1, int pageSize = 15
7270
return await AlbumRepo.GetAllAlbums(page, pageSize);
7371
}
7472

73+
/// <summary>
74+
/// Returns an individual album
75+
/// </summary>
76+
/// <param name="id"></param>
77+
/// <returns></returns>
7578
[HttpGet("api/album/{id:int}")]
7679
public async Task<Album> GetAlbum(int id)
7780
{
7881
return await AlbumRepo.Load(id);
7982
}
8083

84+
/// <summary>
85+
/// Update or add a new album
86+
/// </summary>
87+
/// <param name="postedAlbum"></param>
88+
/// <returns></returns>
89+
/// <exception cref="ApiException"></exception>
8190
[HttpPost("api/album")]
8291
public async Task<Album> SaveAlbum([FromBody] Album postedAlbum)
8392
{
@@ -103,6 +112,13 @@ public async Task<Album> SaveAlbum([FromBody] Album postedAlbum)
103112
return album;
104113
}
105114

115+
116+
/// <summary>
117+
/// Delete a specific album by id
118+
/// </summary>
119+
/// <param name="id"></param>
120+
/// <returns></returns>
121+
/// <exception cref="ApiException"></exception>
106122
[HttpDelete("api/album/{id:int}")]
107123
public async Task<bool> DeleteAlbum(int id)
108124
{
@@ -113,6 +129,12 @@ public async Task<bool> DeleteAlbum(int id)
113129
}
114130

115131

132+
/// <summary>
133+
/// Delete an album by its album name
134+
/// </summary>
135+
/// <param name="name"></param>
136+
/// <returns></returns>
137+
/// <exception cref="ApiException"></exception>
116138
[HttpGet]
117139
public async Task<string> DeleteAlbumByName(string name)
118140
{
@@ -139,13 +161,23 @@ await context.Albums
139161

140162
#region artists
141163

164+
/// <summary>
165+
/// Return a list of Artists
166+
/// </summary>
167+
/// <returns></returns>
142168
[HttpGet]
143169
[Route("api/artists")]
144170
public async Task<IEnumerable> GetArtists()
145171
{
146172
return await ArtistRepo.GetAllArtists();
147173
}
148174

175+
/// <summary>
176+
/// Return an individual Artist
177+
/// </summary>
178+
/// <param name="id"></param>
179+
/// <returns></returns>
180+
/// <exception cref="ApiException"></exception>
149181
[HttpGet("api/artist/{id:int}")]
150182
public async Task<object> Artist(int id)
151183
{
@@ -163,6 +195,12 @@ public async Task<object> Artist(int id)
163195
};
164196
}
165197

198+
/// <summary>
199+
/// Update or add a new Artist
200+
/// </summary>
201+
/// <param name="artist"></param>
202+
/// <returns></returns>
203+
/// <exception cref="ApiException"></exception>
166204
[HttpPost("api/artist")]
167205
public async Task<ArtistResponse> SaveArtist([FromBody] Artist artist)
168206
{
@@ -187,6 +225,11 @@ public async Task<ArtistResponse> SaveArtist([FromBody] Artist artist)
187225
};
188226
}
189227

228+
/// <summary>
229+
/// Look up an artist by name (search functionality)
230+
/// </summary>
231+
/// <param name="search"></param>
232+
/// <returns></returns>
190233
[HttpGet("api/artistlookup")]
191234
public async Task<IEnumerable<object>> ArtistLookup(string search = null)
192235
{
@@ -199,6 +242,12 @@ public async Task<IEnumerable<object>> ArtistLookup(string search = null)
199242
}
200243

201244

245+
/// <summary>
246+
/// Delete an individual artist by Id
247+
/// </summary>
248+
/// <param name="id"></param>
249+
/// <returns></returns>
250+
/// <exception cref="ApiException"></exception>
202251
[HttpDelete("api/artist/{id:int}")]
203252
public async Task<bool> DeleteArtist(int id)
204253
{
@@ -210,6 +259,20 @@ public async Task<bool> DeleteArtist(int id)
210259

211260
#endregion
212261

262+
/// <summary>
263+
/// Sample endpoint that explicitly raises an exception to
264+
/// demonstrate default error results.
265+
/// </summary>
266+
/// <returns></returns>
267+
/// <exception cref="InvalidOperationException"></exception>
268+
/// <response code="500">Unhandled exception thrown - error response</response>
269+
[HttpGet]
270+
[Route("api/throw")]
271+
public object Throw()
272+
{
273+
throw new InvalidOperationException("This is an unhandled exception");
274+
}
275+
213276
#region admin
214277
[HttpGet]
215278
[Route("api/reloaddata")]

src/AlbumViewerNetCore/Controllers/ConfigurationController.cs

+12-8
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,10 @@ public ConfigurationController(IOptions<ApplicationConfiguration> configuration,
3535
}
3636

3737

38+
/// <summary>
39+
/// Returns the application configuration settings
40+
/// </summary>
41+
/// <returns></returns>
3842
[HttpGet]
3943
[Route("api/configuration")]
4044
public ApplicationConfiguration GetConfiguration()
@@ -43,6 +47,11 @@ public ApplicationConfiguration GetConfiguration()
4347
}
4448

4549

50+
51+
/// <summary>
52+
/// Provides information about the running application
53+
/// </summary>
54+
/// <returns></returns>
4655
[HttpGet("api/applicationstats")]
4756
public object GetApplicationStats()
4857
{
@@ -58,13 +67,12 @@ public object GetApplicationStats()
5867
string useSqLite = RawConfiguration["Data:useSqLite"];
5968

6069
// in 3.0 this might work - 2.2: SERIOUSLY????
61-
string runtime = System.Runtime.InteropServices.RuntimeInformation.FrameworkDescription;
70+
//string runtime = System.Runtime.InteropServices.RuntimeInformation.FrameworkDescription;
6271

6372
var stats = new
6473
{
6574
OsPlatform = System.Runtime.InteropServices.RuntimeInformation.OSDescription,
66-
AspDotnetVersion = vname + " (" +
67-
System.Runtime.InteropServices.RuntimeInformation.ProcessArchitecture.ToString().ToLower() + ")",
75+
AspDotnetVersion = System.Runtime.InteropServices.RuntimeInformation.FrameworkDescription,
6876
DataMode = useSqLite == "true" ? "SqLite" : "Sql Server"
6977
};
7078

@@ -73,11 +81,7 @@ public object GetApplicationStats()
7381

7482

7583
/// <summary>
76-
/// Allow Lets Encrypt Reneawal requests through the pipeline by
77-
/// default these are twarthed because they are treated as extensionless
78-
/// action route urls (which have no match and fail).
79-
///
80-
/// Explicitly map a route to the URL and then serve the physical file
84+
/// Explicit endpoint to handle LetsEncryt certificate requests
8185
/// </summary>
8286
/// <param name="id"></param>
8387
/// <returns></returns>

src/AlbumViewerNetCore/Program.cs

+34-1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
using Microsoft.Extensions.DependencyInjection;
1616
using Microsoft.Extensions.Hosting;
1717
using Microsoft.IdentityModel.Tokens;
18+
using Microsoft.OpenApi.Models;
1819

1920

2021
var builder = WebApplication.CreateBuilder(args);
@@ -109,6 +110,31 @@
109110
opt.SerializerSettings.Formatting = Newtonsoft.Json.Formatting.Indented;
110111
});
111112

113+
114+
builder.Services.AddSwaggerGen(options =>
115+
{
116+
options.SwaggerDoc("v1", new OpenApiInfo
117+
{
118+
Version = "v1",
119+
Title = "License Manager API",
120+
Description = "West Wind Album Viewer",
121+
//TermsOfService = new Uri("https://example.com/terms"),
122+
//Contact = new OpenApiContact
123+
//{
124+
// Name = "Example Contact",
125+
// Url = new Uri("https://example.com/contact")
126+
//},
127+
//License = new OpenApiLicense
128+
//{
129+
// Name = "Example License",
130+
// Url = new Uri("https://example.com/license")
131+
//}
132+
});
133+
134+
var filePath = Path.Combine(System.AppContext.BaseDirectory, "AlbumViewerNetCore.xml");
135+
options.IncludeXmlComments(filePath);
136+
});
137+
112138
//
113139
// *** BUILD THE APP
114140
//
@@ -189,6 +215,14 @@ await context.Response.WriteAsync(
189215
app.MapControllers();
190216
});
191217

218+
219+
// for this app make it public
220+
if (true) // (app.Environment.IsDevelopment())
221+
{
222+
app.UseSwagger();
223+
app.UseSwaggerUI();
224+
}
225+
192226
// catch-all handler for HTML5 client routes - serve index.html
193227
app.Run(async context =>
194228
{
@@ -221,5 +255,4 @@ AlbumViewer Core
221255

222256

223257

224-
225258
app.Run();

src/AlbumViewerNetCore/appsettings.json

+3-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,9 @@
2525

2626
"Logging": {
2727
"LogLevel": {
28-
"Default": "Error"
28+
"Default": "Warning",
29+
"Microsoft": "Warning",
30+
"Microsoft.Hosting.Lifetime": "Warning"
2931
}
3032
}
3133
}

0 commit comments

Comments
 (0)