I am trying to configure swagger for my .Netcore App (1.1) and couldnt generate the docs.
Here is my configuration
public void ConfigureServices(IServiceCollection services) {
services.AddMvcCore().AddVersionedApiExplorer(o => o.GroupNameFormat = "1.0");
services.AddMvc();
services.AddApiVersioning(opt =>
{
opt.ApiVersionReader = new HeaderApiVersionReader("api-version");
opt.DefaultApiVersion = new ApiVersion(1, 0);
opt.ReportApiVersions = true;
opt.AssumeDefaultVersionWhenUnspecified = true;
});
services.AddSwaggerGen(
options =>
{
options.SwaggerDoc("1.0",new Info {Contact = new Contact() {Name="Admin" } });
// add a custom operation filter which sets default values
options.OperationFilter<SwaggerDefaultValues>();
});
}
In the Configure Method
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=User}/{action=Get}/{requestString?}");
});
app.UseSwagger(o=>
{
o.RouteTemplate = "docs/{documentName}/swagger.json";
});
app.UseSwaggerUI(
options =>
{
options.SwaggerEndpoint("/docs/1.0/swagger.json", "1.0");
});
When I run the application,
http://localhost:5000/docs/1.0/swagger.json
I am getting the below methods, None of my API's are discovered.
{"swagger":"2.0","info":{"contact":{"name":"Admin"}},"basePath":"/","paths":{},"definitions":{},"securityDefinitions":{}}
OK, I have reproduced your problem and found that the reason is the value in GroupNameFormat option.
If quickly, instead of const version string you should specify version format. As you want to have version in url as 1.0 you may use:
services.AddMvcCore().AddVersionedApiExplorer( o => o.GroupNameFormat = "VVVV" );
From Version Format section in Documentation:
Format Specifier: VVVV
Description: Major, minor version, and status
Examples: 1-RC -> 1.0-RC, 1.1 -> 1.1, 1 -> 1.0
Regarding AddMvcCore() vs AddMvc():
From the swagger docs at https://github.com/domaindrivendev/Swashbuckle.AspNetCore
Swashbuckle relies heavily on ApiExplorer, the API metadata layer that ships with ASP.NET Core. If you're using the AddMvc helper to bootstrap the MVC stack, then ApiExplorer will be automatically registered and SB will work without issue. However, if you're using AddMvcCore for a more paired-down MVC stack, you'll need to explicitly add the Api Explorer service:
services.AddMvcCore().AddApiExplorer();
If you also want AddVersionedApiExplorer(), chain that after AddApiExplorer()
Related
I have NET5 application and in statup I have configured the application to use Newtonsoft instead of System.Text.Json. For posting CSP report I want to add application/csp-report as a supported media type.
Even though I have configured to use Newtonsoft using AddNewtonsoftJson, the NewtonsoftJsonInputFormatter is still not available as inputformatter. The following code returns null
when try to find in InputFormatters collection.
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews(config =>
{
var jsonInputFormatter = options.InputFormatters
.OfType<NewtonsoftJsonInputFormatter>()
.First();
//jsonInputFormatter is null here
jsonInputFormatter.SupportedMediaTypes.Add("application/csp-report")
})
// Use Newtonsoft’s Json.NET instead of System.Text.Json.
.AddNewtonsoftJson((options)=>
{
options.SerializerSettings.ContractResolver = new DefaultContractResolver();
})
}
based on the post here . The accepted answer in that post did not work for me. However the other suggested work around by #Vincent Rutten did work
services.AddOptions<MvcOptions>()
.PostConfigure<IOptions<JsonOptions>, IOptions<MvcNewtonsoftJsonOptions>, ArrayPool<char>, ObjectPoolProvider, ILoggerFactory>(
(mvcOptions, jsonOpts, newtonJsonOpts, charPool, objectPoolProvider, loggerFactory) =>
{
var formatter = mvcOptions.InputFormatters.OfType<NewtonsoftJsonInputFormatter>().First(i => i.SupportedMediaTypes.Contains("application/json"));
formatter.SupportedMediaTypes.Add(MediaTypeHeaderValue.Parse("application/csp-report"));
mvcOptions.InputFormatters.RemoveType<NewtonsoftJsonInputFormatter>();
mvcOptions.InputFormatters.Add(formatter);
});
I have a AspNetZero .NetCore + Angular project and I need to implement api versioning to the project for backwards compatibility. I followed a few examples online, but they either don't specify all the steps, or are specific to mvc, and this project uses the AppService pattern. If any one has successfully managed to implement api versioning in a AspNetZero project, I would really appreciate your help.
I'm currently at the swagger page showing two version, but for v1, I get an AmbiguousMatchException and for v2 swagger can't find the v2 file, so I assume it's not getting generated.
In my Application project, I changed the current AppService's namespace to .v1, and created a new AppService with namespace v2, that inherits the old one, and overrides 1 method which will be the v2.
The aim is to be able to call both methods once it's done with i.e:
(http://localhost:9901/api/services/app/Equities/Get_Snapshot or http://localhost:9901/api/services/v1/Equities/Get_Snapshot) and
http://localhost:9901/api/services/v2/Equities/Get_Snapshot
Open Startup.cs in YOURCOMPANY.Web.Host project.
In the ConfigureServices method, scroll down and find services.AddSwaggerGen ...
Implement the following code:
services.AddSwaggerGen(options =>
{
options.SwaggerDoc("v1", new OpenApiInfo()
{
Title = "MY API",
Version = "v1",
Description = "Any description for your V1 APIs."
});
options.SwaggerDoc("public", new OpenApiInfo()
{
Title = "CMS API",
Version = "v2",
Description = "Any description for your V2 APIs."
});
options.DocInclusionPredicate((docName, apiDesc) =>
{
switch (docName)
{
case "v1":
return true;
case "v2":
return apiDesc.GroupName == null || apiDesc.GroupName == "v2";
default:
return false;
}
});
options.ParameterFilter<SwaggerEnumParameterFilter>();
options.SchemaFilter<SwaggerEnumSchemaFilter>();
options.OperationFilter<SwaggerOperationIdFilter>();
options.OperationFilter<SwaggerOperationFilter>();
options.CustomDefaultSchemaIdSelector();
}).AddSwaggerGenNewtonsoftSupport();
Next, in the Configure method, scroll down and find app.UseSwaggerUI ...
Open appsettings.json in YOURCOMPANY.Web.Host and add a new endpoint configuration variable in the "App" field:
"SwaggerEndPoint": "/swagger/v1/swagger.json",
"SwaggerV2EndPoint": "/swagger/v2/swagger.json"
Implement the following code:
app.UseSwaggerUI(options =>
{
options.SwaggerEndpoint(_appConfiguration["App:SwaggerEndPoint"], "MY API V1");
options.SwaggerEndpoint(_appConfiguration["App:SwaggerPublicEndPoint"], "MY API V2");
options.IndexStream = () => Assembly.GetExecutingAssembly()
.GetManifestResourceStream("YOURCOMPANY.Web.wwwroot.swagger.ui.index.html");
options.InjectBaseUrl(_appConfiguration["App:ServerRootAddress"]);
});
Now you can implement APIs in V2 group by adding ApiExplorerSettings attribute in your YOURCOMPANY.Application project; let's assume you have a service named (TestAppService),
Then implement your methods (APIs) in the below namespace, and simply open your Swagger UI and test it.
namespace CMS.TestNameSpace
{
[ApiExplorerSettings(GroupName = "v2")]
[Route("api/[controller]/[action]")]
public class TestAppService : (YOUR)AppServiceBase, ITestAppService
{
[HttpGet]
public async Task<TestDto> GetTest(TestDtoInput input)
{
}
}
}
https://github.com/domaindrivendev/Swashbuckle.AspNetCore
By default, Swagger JSON will be exposed at the following route -
"/swagger/{documentName}/swagger.json". If necessary, you can change
this when enabling the Swagger middleware. Custom routes MUST include
the {documentName} parameter.
Why does the template config require this placeholder but the UI config does not?
app.UseSwagger(c =>
{
c.RouteTemplate = "api-docs/{documentName}/swagger.json";
})
NOTE: If you're using the SwaggerUI middleware, you'll also need to update its configuration to reflect the new endpoints:
app.UseSwaggerUI(c =>
{
c.SwaggerEndpoint("/api-docs/v1/swagger.json", "My API V1");
})
What is {documentName} for? Is there a feature to swap it out dynamically or something? Because the UI config in the example has it statically configured. why wouldn't it just be "/api-docs/v1/swagger.json" in the RouteTemplate config too?
documentName
The {documentName} refers to the name you specify in the AddSwaggerGen() method.
The following code uses myapi as the name for a swagger document.
builder.Services.AddSwaggerGen(options =>
options.SwaggerDoc("myapi", new OpenApiInfo { Title = "My API", Version = "v1" })
);
Using UseSwagger as follows
app.UseSwagger(options =>
options.RouteTemplate = "swagger/{documentName}/swagger.json");
leads to a swagger file being created the following location:
/swagger/myapi/swagger.json
Which means your Swagger UI configuration must be
app.UseSwaggerUI(options => {
options.SwaggerEndpoint("/swagger/myapi/swagger.json", "Swagger v1");
});
The Swagger UI can make a UI based on any swagger file, whether it comes from this project or not. That's why it doesn't include the {documentName} placeholder. There isn't a relationship between these, necessarily.
Multiple Swagger UIs
This, for example, is the configuration where I have 1 Swagger Doc, 2 swagger files, and two UI endpoints. I describe the same API, but once using the OpenAPI v3 standard, and once using the old Swagger v2 standard.
builder.Services.AddSwaggerGen(options =>
{
options.SwaggerDoc("myapi", new OpenApiInfo { Title = "My API", Version = "v1" });
});
app.UseSwagger(options =>
{
options.SerializeAsV2 = true;
options.RouteTemplate = "swagger/{documentName}/swaggerV2.json";
});
app.UseSwagger(options =>
{
options.SerializeAsV2 = false;
options.RouteTemplate = "swagger/{documentName}/openapiV3.json";
});
app.UseSwaggerUI(options => {
options.SwaggerEndpoint("/swagger/myapi/openapiV3.json", "OpenApi v3");
options.SwaggerEndpoint("/swagger/myapi/swaggerV2.json", "Swagger v2");
});
When you go to the swagger UI, you will see a dropdown to select one of the two endpoints.
Multiple Swagger Docs
Your app can also have multiple swagger docs. E.g. your 'normal' API + some legacy API stuff.
options.SwaggerDoc("myapi", new OpenApiInfo { Title = "My API", Version = "v1" });
options.SwaggerDoc("myapiLegacy", new OpenApiInfo { Title = "My Legacy API", Version = "v1" });
There are several ways to specify when a method of your project belongs to a certain swagger doc. But the easiest way is to mark it with an attribute:
[HttpPost]
[ApiExplorerSettings(GroupName = "myapiLegacy")]
public void Post([Product product)
So since you can have multiple swagger docs, it makes sense to create a placeholder for it. i.e., {documentName}.
In my swagger UI I now end up with 4 endpoints:
normal api as Swagger V2
normal api as OpenApi V3
legacy api as Swagger V2
legacy api as OpenApi V3
I want to integrate MiniProfiler is a WebApi or View /XX/results-index.
The WebApi is authenticated with Bearer Tokens. I only want Group Users in Active Directory can see the results, but I don't get it.
I have this code in ServicesCollection:
services.AddMiniProfiler(options =>
{
options.RouteBasePath = "/profiler";
options.ResultsAuthorizeAsync = async request => await GetAuthorization(request); }).AddEntityFramework();
private static async Task<bool> GetAuthorization(HttpRequest request)
{
// var user = request.HttpContext.User.Identity.Name; --> Is null
return true;
}
In Configure Method in StartUp:
app.UseSwagger().UseSwaggerUI(options =>
{
options.SwaggerEndpoint($"/swagger/v1/swagger.json", $"{env.ApplicationName} V1");
options.OAuthClientId("TestApiswaggerui");
options.OAuthAppName("TestApi Swagger UI");
options.IndexStream = () => GetType().GetTypeInfo().Assembly.GetManifestResourceStream(
"TestApi.SwaggerMiniProfiler.html");
})
.UseMiniProfiler();
I want to see mini profiler information through some options:
http://localhost:5050/profiler/results-index --> Show the list methods called
http://localhost:5050/swagger/index.html --> Show the MiniProfiler in the same page
Environment:
.NET Core version: 3.1
MiniProfiler version: MiniProfiler.AspNetCore.Mvc v.4.2.1
Operative system: Windows 10
The piece you're probably missing here is that MiniProfiler shows your results. What's "you" is determined by the UserIdProvider option. When recording and viewing profiles, ensure that these are the same "user ID" (defaults to IP address). It looks like this in options:
services.AddMiniProfiler(options =>
{
options.UserIdProvider = request => ConsistentUserId(request);
});
If your swagger has zero server-side processing at all (e.g. it does not include the MiniProfiler <script> tag from .RenderInludes() or the <mini-profiler /> tag helper, then the issue isn't viewing the profiles so much as not even attempting to view. There are some ideas I have around a static tag without profiles to currently view, but I do not know how to get them into Swagger in it's generation phase (just not familiar enough). Note that it's a blatant hack, but you could work around the issue at the moment with a manual script tag. You'll want to follow https://github.com/MiniProfiler/dotnet/issues/326 for this.
I just want to leave the option of having the traces read for that group from the active directory:
services.AddMiniProfiler(options =>
{
// (Optional) Path to use for profiler URLs, default is /mini-profiler-resources
options.RouteBasePath = "/profiler";
options.ColorScheme = StackExchange.Profiling.ColorScheme.Light;
options.PopupRenderPosition = StackExchange.Profiling.RenderPosition.BottomLeft;
options.PopupShowTimeWithChildren = true;
options.PopupShowTrivial = true;
options.ShouldProfile = ShowProfile;
options.SqlFormatter = new StackExchange.Profiling.SqlFormatters.InlineFormatter();
options.ResultsAuthorize = request => request.HttpContext.User.IsInRole("S-INFORMATICA");
})
.AddEntityFramework();
I am trying to use Microsoft.Extensions.DependencyInjection's method AddAuthentification on a ASP .NET Core 2.1 project though it seems it does not exist in the package when trying to resolve it.Instead i have an extension AddAuthentificationCore which does not have the same signature.
According to the documentation it should be present for .NET Core 2.1.
P.S I want to use the AddAuthentification like :
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie(options => {
options.LoginPath = "/login";
options.AccessDeniedPath = "/AccessDenied";
options.Events.OnRedirectToLogin = (context) => {
context.Response.StatusCode = 401;
return Task.CompletedTask;
};
});
That's not part of Microsoft.Extensions.DependencyInjection. It simply uses that namespace so no explicit additional using statement is required to have the extensions show up. It will actually live in one of the Microsoft.AspNetCore.Authentication NuGet packages.