1- using ApiVersioning . Examples ;
21using Asp . Versioning ;
3- using Microsoft . Extensions . Options ;
4- using Swashbuckle . AspNetCore . SwaggerGen ;
2+ using Scalar . AspNetCore ;
3+ using System . Reflection ;
54using OrderV1 = ApiVersioning . Examples . Models . V1 . Order ;
65using OrderV2 = ApiVersioning . Examples . Models . V2 . Order ;
76using OrderV3 = ApiVersioning . Examples . Models . V3 . Order ;
87using PersonV1 = ApiVersioning . Examples . Models . V1 . Person ;
98using PersonV2 = ApiVersioning . Examples . Models . V2 . Person ;
109using PersonV3 = ApiVersioning . Examples . Models . V3 . Person ;
1110
11+ [ assembly: AssemblyDescription ( "An example API" ) ]
12+
1213var builder = WebApplication . CreateBuilder ( args ) ;
1314var services = builder . Services ;
1415
15- // Add services to the container.
1616services . AddProblemDetails ( ) ;
1717services . AddEndpointsApiExplorer ( ) ;
1818services . AddApiVersioning (
3939 // can also be used to control the format of the API version in route templates
4040 options . SubstituteApiVersionInUrl = true ;
4141 } )
42+ . AddOpenApi ( ( _ , options ) => options . AddScalarTransformers ( ) )
4243 // this enables binding ApiVersion as a endpoint callback parameter. if you don't use it, then
4344 // you should remove this configuration.
4445 . EnableApiVersionBinding ( ) ;
45- services . AddTransient < IConfigureOptions < SwaggerGenOptions > , ConfigureSwaggerOptions > ( ) ;
46- services . AddSwaggerGen ( options => options . OperationFilter < SwaggerDefaultValues > ( ) ) ;
4746
48- // Configure the HTTP request pipeline.
4947var app = builder . Build ( ) ;
5048var orders = app . NewVersionedApi ( "Orders" ) ;
5149var people = app . NewVersionedApi ( "People" ) ;
5654 . HasApiVersion ( 1.0 ) ;
5755
5856ordersV1 . MapGet ( "/{id:int}" , ( int id ) => new OrderV1 ( ) { Id = id , Customer = "John Doe" } )
57+ . WithSummary ( "Get Order" )
58+ . WithDescription ( "Gets a single order." )
5959 . Produces < OrderV1 > ( )
6060 . Produces ( 404 ) ;
6161
6767 var location = new Uri ( $ "{ scheme } { Uri . SchemeDelimiter } { host } /api/orders/{ order . Id } " ) ;
6868 return Results . Created ( location , order ) ;
6969 } )
70+ . WithSummary ( "Place Order" )
71+ . WithDescription ( "Places a new order." )
7072 . Accepts < OrderV1 > ( "application/json" )
7173 . Produces < OrderV1 > ( 201 )
7274 . Produces ( 400 )
7375 . MapToApiVersion ( 1.0 ) ;
7476
7577ordersV1 . MapPatch ( "/{id:int}" , ( int id , OrderV1 order ) => Results . NoContent ( ) )
78+ . WithSummary ( "Update Order" )
79+ . WithDescription ( "Updates an order." )
7680 . Accepts < OrderV1 > ( "application/json" )
7781 . Produces ( 204 )
7882 . Produces ( 400 )
9094 new ( ) { Id = 2 , Customer = "Bob Smith" } ,
9195 new ( ) { Id = 3 , Customer = "Jane Doe" , EffectiveDate = DateTimeOffset . UtcNow . AddDays ( 7d ) } ,
9296 } )
97+ . WithSummary ( "Get Orders" )
98+ . WithDescription ( "Retrieves all orders." )
9399 . Produces < IEnumerable < OrderV2 > > ( )
94100 . Produces ( 404 ) ;
95101
96102ordersV2 . MapGet ( "/{id:int}" , ( int id ) => new OrderV2 ( ) { Id = id , Customer = "John Doe" } )
103+ . WithSummary ( "Get Order" )
104+ . WithDescription ( "Gets a single order." )
97105 . Produces < OrderV2 > ( )
98106 . Produces ( 404 ) ;
99107
105113 var location = new Uri ( $ "{ scheme } { Uri . SchemeDelimiter } { host } /api/orders/{ order . Id } " ) ;
106114 return Results . Created ( location , order ) ;
107115 } )
116+ . WithSummary ( "Place Order" )
117+ . WithDescription ( "Places a new order." )
108118 . Accepts < OrderV2 > ( "application/json" )
109119 . Produces < OrderV2 > ( 201 )
110120 . Produces ( 400 ) ;
111121
112122
113123ordersV2 . MapPatch ( "/{id:int}" , ( int id , OrderV2 order ) => Results . NoContent ( ) )
124+ . WithSummary ( "Update Order" )
125+ . WithDescription ( "Updates an order." )
114126 . Accepts < OrderV2 > ( "application/json" )
115127 . Produces ( 204 )
116128 . Produces ( 400 )
127139 new ( ) { Id = 2 , Customer = "Bob Smith" } ,
128140 new ( ) { Id = 3 , Customer = "Jane Doe" , EffectiveDate = DateTimeOffset . UtcNow . AddDays ( 7d ) } ,
129141 } )
142+ . WithSummary ( "Get Orders" )
143+ . WithDescription ( "Retrieves all orders." )
130144 . Produces < IEnumerable < OrderV3 > > ( ) ;
131145
132146ordersV3 . MapGet ( "/{id:int}" , ( int id ) => new OrderV3 ( ) { Id = id , Customer = "John Doe" } )
147+ . WithSummary ( "Get Order" )
148+ . WithDescription ( "Gets a single order." )
133149 . Produces < OrderV3 > ( )
134150 . Produces ( 404 ) ;
135151
141157 var location = new Uri ( $ "{ scheme } { Uri . SchemeDelimiter } { host } /api/orders/{ order . Id } " ) ;
142158 return Results . Created ( location , order ) ;
143159 } )
160+ . WithSummary ( "Place Order" )
161+ . WithDescription ( "Places a new order." )
144162 . Accepts < OrderV3 > ( "application/json" )
145163 . Produces < OrderV3 > ( 201 )
146164 . Produces ( 400 ) ;
147165
148166ordersV3 . MapDelete ( "/{id:int}" , ( int id ) => Results . NoContent ( ) )
167+ . WithSummary ( "Cancel Order" )
168+ . WithDescription ( "Cancels an order." )
149169 . Produces ( 204 ) ;
150170
151171// 1.0
160180 FirstName = "John" ,
161181 LastName = "Doe" ,
162182 } )
183+ . WithSummary ( "Get Person" )
184+ . WithDescription ( "Gets a single person." )
163185 . Produces < PersonV1 > ( )
164186 . Produces ( 404 ) ;
165187
192214 Email = "jane.doe@somewhere.com" ,
193215 } ,
194216 } )
217+ . WithSummary ( "Get People" )
218+ . WithDescription ( "Gets all people." )
195219 . Produces < IEnumerable < PersonV2 > > ( ) ;
196220
197221peopleV2 . MapGet ( "/{id:int}" , ( int id ) =>
202226 LastName = "Doe" ,
203227 Email = "john.doe@somewhere.com" ,
204228 } )
229+ . WithSummary ( "Get Person" )
230+ . WithDescription ( "Gets a single person." )
205231 . Produces < PersonV2 > ( )
206232 . Produces ( 404 ) ;
207233
237263 Phone = "555-789-3456" ,
238264 } ,
239265 } )
266+ . WithSummary ( "Get People" )
267+ . WithDescription ( "Gets all people." )
240268 . Produces < IEnumerable < PersonV3 > > ( ) ;
241269
242270peopleV3 . MapGet ( "/{id:int}" , ( int id ) =>
248276 Email = "john.doe@somewhere.com" ,
249277 Phone = "555-987-1234" ,
250278 } )
279+ . WithSummary ( "Get Person" )
280+ . WithDescription ( "Gets a single person." )
251281 . Produces < PersonV3 > ( )
252282 . Produces ( 404 ) ;
253283
259289 var location = new Uri ( $ "{ scheme } { Uri . SchemeDelimiter } { host } /v{ version } /api/people/{ person . Id } " ) ;
260290 return Results . Created ( location , person ) ;
261291 } )
292+ . WithSummary ( "Add Person" )
293+ . WithDescription ( "Adds a new person." )
262294 . Accepts < PersonV3 > ( "application/json" )
263295 . Produces < PersonV3 > ( 201 )
264296 . Produces ( 400 ) ;
265297
266- app . UseSwagger ( ) ;
267298if ( app . Environment . IsDevelopment ( ) )
268299{
269- app . UseSwaggerUI (
300+ app . IncludeVersionedEndpoints ( ) . MapOpenApi ( ) . WithDocumentPerVersion ( ) ;
301+ app . MapScalarApiReference (
270302 options =>
271303 {
272304 var descriptions = app . DescribeApiVersions ( ) ;
273305
274- // build a swagger endpoint for each discovered API version
275- foreach ( var description in descriptions )
306+ for ( var i = 0 ; i < descriptions . Count ; i ++ )
276307 {
277- var url = $ "/swagger/{ description . GroupName } /swagger.json";
278- var name = description . GroupName . ToUpperInvariant ( ) ;
279- options . SwaggerEndpoint ( url , name ) ;
308+ var description = descriptions [ i ] ;
309+ var isDefault = i == descriptions . Count - 1 ;
310+
311+ options . AddDocument ( description . GroupName , description . GroupName , isDefault : isDefault ) ;
280312 }
281313 } ) ;
282314}
315+
283316app . Run ( ) ;
0 commit comments