I recently started work with Asp.net Web API and in the present of Methods in Program.cs.
What does AddSwaggerGen() do?
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
In .NET 7 the Startup.cs and Program.cs are composition.
That line of code, adds the Swagger generator to the services collection. SwaggerUI shows the REST APIs in your project in a user-friendly UI, so that you can test them in the browser. For this UI to render, you need the JSON file that expresses the details of the APIs[name, input arguments, types, etc], that JSON is being generated by this Swagger Generator.
Note: Swagger was the name of the project that described the definition of REST APIs, since 2015 it has been known as OpenAPI.
The configuration action passed to the AddSwaggerGen method adds information such as the author, license, and description. You can find more information here.
AddSwaggerGen() method adds a service that generates Swagger documents for your APIs. When this method is called, it adds the service to the dependency injection container so that it can be used later in the application. When the service is used, it will generate a Swagger document that describes the available APIs and their operations. This can be useful for developers who are consuming the APIs, as it provides detailed information about how to use the APIs.
Related
I am reading the Autofac documentation related to its integration with OWIN, and I get confused by the example they put on their website:
public class Startup
{
public void Configuration(IAppBuilder app)
{
var builder = new ContainerBuilder();
// STANDARD WEB API SETUP:
// Get your HttpConfiguration. In OWIN, you'll create one
// rather than using GlobalConfiguration.
var config = new HttpConfiguration();
// Register your Web API controllers.
builder.RegisterApiControllers(Assembly.GetExecutingAssembly());
// Run other optional steps, like registering filters,
// per-controller-type services, etc., then set the dependency resolver
// to be Autofac.
var container = builder.Build();
config.DependencyResolver = new AutofacWebApiDependencyResolver(container);
// OWIN WEB API SETUP:
// Register the Autofac middleware FIRST, then the Autofac Web API middleware,
// and finally the standard Web API middleware.
app.UseAutofacMiddleware(container);
app.UseAutofacWebApi(config);
app.UseWebApi(config);
}
}
Where I am stuck now is on line config.DependencyResolver = new AutofacWebApiDependencyResolver(container); the webapi dependency resolver is set to autofac, and what is the reason that app.UseAutofacWebApi(config); must be called?
The extension method is to "Extends the Autofac lifetime scope added from the OWIN pipeline through to the Web API dependency scope", but the autofac lifetime scope is shared by setting dependency resolver, is this call still necessary?
It would also be very helpful if you can provide me the use cases of UseAutofacWebApi. Thanks!
The short answer is, yes, it's needed.
Usually a way to test this sort of thing is to see if you can get everything you need without it. I mean, if your app works and things are injected right, that's enough, right?
The longer answer involves you needing to understand that Web API is not natively part of OWIN. OWIN is kind of a bolt-on. The way Web API integrates is, very basically, that the Web API pipeline is jammed into the OWIN pipeline as a middleware step. You can do other stuff with OWIN, too, like adding your own middleware and so on. It's a little beyond the scope of the question here to go through all the details of the ASP.NET pipeline, OWIN, how the middleware interacts, etc. A quick Google search for how does web api work with owin brings up a ton of documentation, blog articles, and explanations.
The important aspect there, though, is that there are basically two parts - the OWIN part, with its pipeline, and the Web API part, with its "sub pipeline."
Since the OWIN pipeline starts before the Web API pipeline, in order to make the two work together and have a request lifetime for the whole of the OWIN pipeline, you have to use the Autofac middleware to do that initialization. Then that same scope from the OWIN pipeline needs to make it into Web API. That also means when the Web API request is done, the OWIN pipeline needs to be able to handle the disposal of things rather than letting Web API handle it.
Hence the documentation: "Extends the Autofac lifetime scope added from the OWIN pipeline through to the Web API dependency scope." It's taking the scope created at the start of the OWIN pipeline and making sure it's the same scope that goes into the Web API pipeline.
Some applications not only have Web API but also ASP.NET MVC, all of which is trying to be coordinated through that OWIN pipeline and needing everything to work together. All of the stuff Autofac has in place to get Web API, MVC, and OWIN wired up is there for a reason - to make sure it all plays nicely together.
Generally if something is optional, the docs will explicitly say so. For example in the Autofac Web API documentation it's noted that it's optional to register filter and model binder provider handling. In this case, it's not really optional.
I am currently working on a feature and added the builder code like this in the Autofac
builder.RegisterType<ILTLoPublisher<ScheduleUpdateEvent>>()
.AsImplementedInterfaces()
.InstancePerRequest()
.Keyed<IILTLoPublisher<ScheduleUpdateEvent>>(AuditType.Schedule);
builder.RegisterType<ILTLoPublisher<ScheduleUpdatePart>>()
.AsImplementedInterfaces()
.InstancePerRequest()
.Keyed<IILTLoPublisher<ScheduleUpdatePart>>(AuditType.Part);
builder.RegisterType<ILTLoPublisher<ScheduleUpdateTest>>()
.AsImplementedInterfaces()
.InstancePerRequest()
.Keyed<IILTLoPublisher<ScheduleUpdateTest>>(AuditType.Test);
This code is run as a console app service and the call to this is made from an api service.I want it to be called as below
AutoFacModule autofac = new AutoFacModule();
var builder = new ContainerBuilder();
autofac.LoadBuilder(builder);
Container = builder.Build();
using (var scope = Container.BeginLifetimeScope())
{
var _publisher1 = scope.ResolveKeyed<IILTLoPublisher<ScheduleUpdateEvent>>(AuditType.Schedule);
var _publisher2 = scope.ResolveKeyed<IILTLoPublisher<ScheduleUpdatePart>>(AuditType.Part);
var _publisher2 = scope.ResolveKeyed<IILTLoPublisher<ScheduleUpdateTest>>(AuditType.Test);
}
When i am trying to resolve it using the below code in my implementation class
var _publisher = scope.ResolveKeyed<IILTLoPublisher<ScheduleUpdateEvent>>(AuditType.Schedule);
I am getting the following error
Unable to resolve the type Apiconnector.Integrations.Vilt.Service.Providers.Custom.Publish.ILTLoPublisher`1[LMS.ILT.ScheduleUpdateEvent]' because the lifetime scope it belongs in can't be located
You can't use InstancePerRequest unless the object being resolved is part of a web request (as noted by the comments on the question). More specifically:
The executing application must be a web application.
The executing application needs to have the Autofac web integration in place.
The resolution must be happening in that web application as part of a response to an inbound web request - for example, as part of an MVC controller or ASP.NET Core middleware.
The "per request" semantics have nothing to do with the client making the request - it's about the server handling the request.
You might want to spend some time with the documentation on the topic. There is a section in there about how to implement custom per-request semantics for your app.
If what you are creating is a console app that takes in requests from clients (e.g., a self-hosted web application) then you need to:
Add the existing Autofac web integration for your app type (we do support ASP.NET Web API and ASP.NET Core self hosted scenarios); OR
Implement something custom if you're not using ASP.NET (see that doc I linked).
If what you are creating is a console app that issues requests as a client then you should ignore InstancePerRequest. Instead:
Create a new lifetime scope around each request (like you're doing) and treat that as a unit of work.
Register components as InstancePerLifetimeScope so there will be just one for the duration of that lifetime scope.
That said, without a minimal repro it's hard to see what you're doing beyond that to provide any sort of guidance.
Since you mentioned you're pretty new to all this, it would be very worth your time checking out the Autofac documentation to start understanding concepts like this as well as looking in the Examples repo where there are working examples of many different application types to show you how things work.
When configuring services within MVC app you can set the compatibility version:
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
How can I retrieve this version later in my own code to determine which compatibility version is in use?
There does not appear to be a corresponding GetCompatibilityVersion method anywhere and google/stackoverflow search was not my friend.
Any help appreciated.
The MVC compatibility version is actually stored in an instance of a class called MvcCompatibilityOptions. You can retrieve this object by locating it through the IoC container that is being used by the application – either ASP.NET Core's built-in one or a third party one.
For example, with the default IoC, you can retrieve it like this:
var compatibilityVersion = app.ApplicationServices.GetService<IOptions<MvcCompatibilityOptions>>().Value.CompatibilityVersion;
app is an instance of IApplicationBuilder.
I have Swagger setup for an ASP.NET Core 2 MVC API application. I'm using OpenIddict for OAuth but want to customize how the request and responses appear on the documentation.
Since the method in the controller takes an OpenIdConnectRequest, the generated default output looks like so:
... and it just goes on and on.
This is a far cry from the neat JSON required for a client to consume since the middleware does a bunch of work inbetween the client and the controller method.
How do I change how Swagger represents these? I am already using a hack to massage the responses via a custom, private type for token responses, so any help on how to use that would also be appreciated. I have tried to use the SwaggerGenOptions.MapType<> function as the documentation claims that tells Swagger how to map a type to a custom output. Unfortunately, I've not gotten the Swagger output to reflect anything I've done with .MapType<>.
To be clear, these aren't models I control so I can't decorate the members myself.
Note that this is different from How to show WebApi OAuth token endpoint in Swagger. My controller action is discovered fine. Unfortunately, I'm thinking it may be easier to filter it out and use that as another work around to define it manually but I'd rather not if possible.
I am creating an Azure API app on Visual Studio 2015. when i hit browse and redirected to http://localhost:3012/ if i add swagger to the url nothing happens : http://localhost:3012/swagger
it seems I need to add the /docs/v1 for a full address : http://localhost:3012/swagger/docs/v1 . Shouldn't there be like an automatic URL routing when i add /swagger to load swagger page.
Also, i am only able to view the json schema, if i browser to the UI http://localhost:3012/swagger/ui the page doesn't load.
The API app builds successfully. is there anything missing?
In the configuration of your WebAPI project (SwaggerConfig.cs in the folder App_Start), you have to enable the Swagger UI. It is commented out as default behavior.
Just open the configuration, search for:
/*
})
.EnableSwaggerUi(c =>
{
*/
and disable the comments in the lines above and under it
Pedro, above, has provided a perfect answer for enabling SwaggerUi.
As for your question regarding the URL "swagger/docs/v1"
This is the default URL used by Swashbuckle to return Swagger 2.0 JSON metadata for the API
The SwaggerConfig.cs file is created when you install the Swashbuckle package in a project. You can find it in the folder "App_Start" . It provides a number of ways to configure Swashbuckle. I haven't checked if you can change that default URL or do URL rerouting for it.
Edited:
The default route templates for the Swagger docs and swagger-ui are "swagger/docs/{apiVersion}" and "swagger/ui/{*assetPath}" respectively. You can change these so long as the provided templates include the relevant route parameters - {apiVersion} and {*assetPath}.
For example: the URL to swagger-ui will be myswag/index.
httpConfiguration
.EnableSwagger("docs/{apiVersion}/swagger", c => c.SingleApiVersion("v1", "A title for your API"))
.EnableSwaggerUi("myswag/{*assetPath}");
You can read more about it here in the GitHub repo: https://github.com/domaindrivendev/Swashbuckle
If you are creating API using Template Azure API App in visual studio, you just need to un-comment few lines from SwaggerConfig.cs file to activate Swagger for your API application.
In your solution look for the file 'SwaggerConfig.cs'
'VSSolution' > App_Start > SwaggerConfig.cs
Look for EnableSwaggerUi and remove comments for below line of code
/*
})
.EnableSwaggerUi(c =>
{
*/
That's it, No Other Configuration Required.
Just run the application :
http://localhost:57452/swagger
I had this same problem and was misled a bit by these answers although I saw that they were admittedly entirely correct in the end.
Note the following:
Don't mistake the .EnableSwagger setting for the EnableSwaggerUi
setting in SwaggerConfig.cs.
The former is on by default and comes at the beginning of the
SwaggerConfig.cs file
the latter is commented out by default and buried in a lot of other comments. It cost me quite some time before I noticed that there were actually two settings.
The .EnableSwagger setting causes raw JSON to be emitted on your application url https://yourapp.azurewebsites.net/swagger/docs/v1 - which is not a great help.
While the .EnableSwaggerUi setting is what causes the Swagger UI to appear on your url https://yourapp.azurewebsites.net/swagger