Why swashbuckle example value does not work? - asp.net-core

Here I added XML doc parameter example="this does not work" for swashbuckle framework.
/// <summary>Gets a user by id.</summary>
/// <param name="id" example="this does not work">The id of user.</param>
/// <returns>got user.</returns>
[HttpGet("Get")]
[ProducesResponseType(typeof(UserDTO), 200)]
[ProducesResponseType(typeof(AppException), StatusCodes.Status500InternalServerError)]
public async Task<IActionResult> Get(string id)
{
return HandleResult(await _userServices.GetUserAsync(id));
}
But example value does not appear in Swagger UI.
Where I should look for the problem?

Unfortunately out of the box Swashbuckle doesn't support the example tag/attribute. You need to write an operation filter and implement your own. Or you can use the Swashbuckle.AspNetCore.Filters nuget package.
You need to add the following code in your program.cs file.
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen(c =>
{
var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
c.IncludeXmlComments(xmlPath, includeControllerXmlComments: true);
});
//For Example tag support
builder.Services.AddSwaggerExamplesFromAssemblies(Assembly.GetEntryAssembly());
And once you run the app you will be able to see examples like this in your swagger documentation.

Related

How to perform async ModelState validation with FluentValidation in Web API using .NET Core

This question is a follow up to this post - How to perform async ModelState validation with FluentValidation in Web API?.
I was wondering if FluentValidation has a way to perform async ModelState validation in .net core web api. I have a FluentValidation Validator class which contains async validation methods such as "MustAsync", which means in my business service class I call the validator manually using "ValidateAsync". I also want to use this same validator class to validate the model coming in from the request. I went through the documents and read that the only way to do this is to manually call the "ValidateAsync()" method since the .net pipeline is synchronous. I would rather not manually have to call this method from within my controller, I would prefer to either register it in the startup (have the framework automatically call the the validator on my model) or decorate my request model with the validator.
Has anyone been able to achieve this?
Thanks!
Based on the linked question, I've adapted the code slightly to be compatible with ASP.NET Core (2.2, in my case). In general, this is using the IAsyncActionFilter interface. You can read about it in the official docs.
public class ModelValidationActionFilter : IAsyncActionFilter
{
private readonly IValidatorFactory _validatorFactory;
public ModelValidationActionFilter(IValidatorFactory validatorFactory) => _validatorFactory = validatorFactory;
public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
{
var allErrors = new Dictionary<string, object>();
// Short-circuit if there's nothing to validate
if (context.ActionArguments.Count == 0)
{
await next();
return;
}
foreach (var (key, value) in context.ActionArguments)
{
// skip null values
if (value == null)
continue;
var validator = _validatorFactory.GetValidator(value.GetType());
// skip objects with no validators
if (validator == null)
continue;
// validate
var result = await validator.ValidateAsync(value);
// if it's valid, continue
if (result.IsValid) continue;
// if there are errors, copy to the response dictonary
var dict = new Dictionary<string, string>();
foreach (var e in result.Errors)
dict[e.PropertyName] = e.ErrorMessage;
allErrors.Add(key, dict);
}
if (allErrors.Any())
{
// Do anything you want here, if the validation failed.
// For example, you can set context.Result to a new BadRequestResult()
// or implement the Post-Request-Get pattern.
}
else
await next();
}
}
If you want to apply this filter globally, you can add the filter to the AddMvc call in your Startup class. For example:
services.AddMvc(options =>
{
options.Filters.Add<ModelValidationActionFilter>();
// uncomment the following line, if you want to disable the regular validation
// options.ModelValidatorProviders.Clear();
});
I had trouble getting the code in #nachtjasmin's answer to work with newer versions of FluentValidation. Specifically, the trouble is that ValidateAsync now takes an IValidationContext instead of the model being validated, and the context can't be created without knowing the type of the model at compile time.
Eventually I stumbled upon this answer, which points out that the exact type is not important and uses object instead.
So, instead of:
var result = await validator.ValidateAsync(value);
You can use:
var context = new ValidationContext<object>(value);
var result = await validator.ValidateAsync(context);
Based on the answer above by #nachtjasmin, you can add this in two ways,
Using AddMvc
services.AddControllersWithViews(options =>
{
options.Filters.Add<FluentValidationActionFilter>();
});
Using AddControllersWithViews
services.AddControllersWithViews(options =>
{
options.Filters.Add<FluentValidationActionFilter>();
});
If your's is just a Web API and you don't have any Razor pages involved, then you can consider using AddControllersWithViews over AddMvc, as the AddMvc uses the AddControllersWithViews internally and add the services.AddRazorPages() on top of that.
You can see this info here for AddMvc and here for AddControllersWithViews

How to dynamically resolve controller with endpoint routing?

Upgrading to asp.net core 2.2 in my hobby project there is a new routing system I want to migrate to. Previously I implemented a custom IRouter to be able to set the controller for the request dynamically. The incoming request path can be anything. I match the request against a database table containing slugs and it looks up the a matching data container class type for the resolved slug. After that I resolve a controller type that can handle the request and set the RouteData values to the current HttpContext and passing it along to the default implementation for IRouter and everything works ok.
Custom implementaion of IRouter:
public async Task RouteAsync(RouteContext context)
{
var requestPath = context.HttpContext.Request.Path.Value;
var page = _pIndex.GetPage(requestPath);
if (page != null)
{
var controllerType = _controllerResolver.GetController(page.PageType);
if (controllerType != null)
{
var oldRouteData = context.RouteData;
var newRouteData = new RouteData(oldRouteData);
newRouteData.Values["pageType"] = page.PageType;
newRouteData.Values["controller"] = controllerType.Name.Replace("Controller", "");
newRouteData.Values["action"] = "Index";
context.RouteData = newRouteData;
await _defaultRouter.RouteAsync(context);
}
}
}
A controller to handle a specific page type.
public class SomePageController : PageController<PageData>
{
public ActionResult Index(PageData currentPage)
{
return View("Index", currentPage);
}
}
However I got stuck when I'm trying to figure out how I can solve it using the new system. I'm not sure where I'm suppose to extend it for this behavior. I don't want to turn off the endpoint routing feature because I see an opportunity to learn something. I would aso appreciate a code sample if possible.
In ASP.NET 3.0 there is an new dynamic controller routing system. You can implement DynamicRouteValueTransformer.
Documentation is on the way, look at the github issue

Remote Validation in Asp.Net Core Razor Pages

I’m developing a web application using Razor Pages and Code First.
I know that in ASP.NET MVC, you can use Remote above a property referring to an action in a controller that validates the data without the whole page being posted back. But it doesn’t seem to work in Razor Pages as there’s no Controller and Action in ASP.NET Core Razor Pages.
So, How can I get remote validation done in Razor Pages?
For anyone like me who finds this later and loses their mind trying to pass a property from their model onto the validation method, make the method signature look like so
public IActionResult IsCharacterNameAvailable([Bind(Prefix = "Character.Name")] string name)
Character is the model and Name is the property. Without adding the [Bind(Prefix = "")] before the parameter I was always receiving a null value. Hope this helps!
I added the following in my model class:
[Remote(action: "IsNationalIdValid",controller:"Validations")]
I created 'Controllers' folder in my Razor Pages project and added a controller(ValidationsController) with the following method:
public IActionResult IsNationalIdValid(string nationalId){}
However,when I tried to go to the page where this validation was supposed to work,I got the following exception:
No URL for remote validation could be found in asp.net core
Thanks to a reply to the same thread in Asp.Net forum,I figured out the answer:
All I needed to do was to add the following code in Startup.cs file of my Razor Pages project in order to configure the route.
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
Hope this answer will help someone else as well.
In the base class that RemoteAttribute derives from there's a protected GetUrl() method than can be overriden. Therefore I created my own MyRemoteAttribute class
public class MyRemoteAttribute : RemoteAttribute
{
/// <summary>
/// Initialise an instance of the <see cref="MyRemoteAttribute"/>
/// </summary>
/// <param name="handler">The name of the Razor Page Handler</param>
/// <param name="page">The Razor Page name</param>
public MyRemoteAttribute(string handler = null, string page = null)
{
Handler = handler;
Page = page;
}
/// <summary>
/// Gets/sets the url to use for remote validation
/// </summary>
public string Url { get; set; }
public string Page { get; private set; }
public string Handler { get; private set; }
protected override string GetUrl(ClientModelValidationContext context)
{
// Use an URL is specified
if (!string.IsNullOrEmpty(Url)) return Url;
if (context == null)
{
throw new ArgumentNullException(nameof(context));
}
if (string.IsNullOrEmpty(Handler))
{
throw new InvalidOperationException("No Handler specified");
}
var services = context.ActionContext.HttpContext.RequestServices;
var factory = services.GetRequiredService<Microsoft.AspNetCore.Mvc.Routing.IUrlHelperFactory>();
var urlHelper = factory.GetUrlHelper(context.ActionContext);
var page = Page?? context.ActionContext.RouteData.Values["page"] as string;
Url = urlHelper.Page(page, Handler);
if (Url == null)
{
throw new InvalidOperationException();
}
return Url;
}
}
In my app which is using areas, creates a url /BusinessPartners/Clients/Create?handler=CheckUnique
To use decorate your model property with [MyRemote(Url="/Something/Somecheck")] to use the specified URL, or [MyRemote("CheckUnique")] to specify the Razor Page Handler. The handler should be named OnGet<handlername> and needs to return a JsonResult with true for passing validation, false or null if validation fails.
The handler in the Razor Page is:
public IActionResult OnGetCheckUnique(string shortName)
{
var found = db.Queryable<BusinessPartner>().Any(a => a.ShortName == shortName);
return new JsonResult(!found);
}
This is the same as you would do for the RemoteAttribute with the exception on the slightly modified naming convention.
I like my validation to be close to the point where it is used so therefore I've put it in the same page. I also have use a single [BindProperty] for a model class just to keep things neat and manageable.
Looks like there is a feature request for remote validation in ASP.NET Core Razor Pages but it is not priority:
https://github.com/aspnet/Mvc/issues/8245
The PageRemoteValidation attribute was introduced in ASP.NET Core 3.0 and is designed specifically to work with a Razor Pages handler method.
So, if you are working with ASP.NET Core 2.x, or your validation endpoint is an MVC controller, you must use the RemoteValidation attribute. If you are working with ASP.NET Core 3.x or newer, AND your validation service is a Razor Pages handler method, you must use the PageRemoteValidation attribute.
Here is an example describing this in details:

How to show XML comments of class properties in Swagger (MVC 6 Web API JsonResult)

I've added XML comments to my class members but Swagger won't show them in the UI. Am I doing something wrong?
UPDATE: It looks like you can't document your model classes in
Swashbuckle (5.5.3) with #ApiModel and #ApiModelProperty annotations and the
xml comments don't work either.
public class DataController : ApiController
{
[Route("api/GetData")]
[SwaggerResponse(HttpStatusCode.OK, Type = typeof(MyData))]
public System.Web.Mvc.JsonResult GetData()
{
MyData myData = new MyData();
return new System.Web.Mvc.JsonResult
{
Data = myData
};
}
}
public class MyData
{
/// <summary>
/// My code
/// </summary>
public string code;
/// <summary>
/// My name
/// </summary>
public string name;
}
Swagger configuration
public class SwaggerConfig
{
public static void Register()
{
var thisAssembly = typeof(SwaggerConfig).Assembly;
GlobalConfiguration.Configuration
.EnableSwagger(c =>
{
// By default, the service root url is inferred from the request used to access the docs.
// However, there may be situations (e.g. proxy and load-balanced environments) where this does not
// resolve correctly. You can workaround this by providing your own code to determine the root URL.
//
//c.RootUrl(req => GetRootUrlFromAppConfig());
// If schemes are not explicitly provided in a Swagger 2.0 document, then the scheme used to access
// the docs is taken as the default. If your API supports multiple schemes and you want to be explicit
// about them, you can use the "Schemes" option as shown below.
//
//c.Schemes(new[] { "http", "https" });
// Use "SingleApiVersion" to describe a single version API. Swagger 2.0 includes an "Info" object to
// hold additional metadata for an API. Version and title are required but you can also provide
// additional fields by chaining methods off SingleApiVersion.
//
c.SingleApiVersion("v1", "WDSJSONServer");
// If your API has multiple versions, use "MultipleApiVersions" instead of "SingleApiVersion".
// In this case, you must provide a lambda that tells Swashbuckle which actions should be
// included in the docs for a given API version. Like "SingleApiVersion", each call to "Version"
// returns an "Info" builder so you can provide additional metadata per API version.
//
//c.MultipleApiVersions(
// (apiDesc, targetApiVersion) => ResolveVersionSupportByRouteConstraint(apiDesc, targetApiVersion),
// (vc) =>
// {
// vc.Version("v2", "Swashbuckle Dummy API V2");
// vc.Version("v1", "Swashbuckle Dummy API V1");
// });
// You can use "BasicAuth", "ApiKey" or "OAuth2" options to describe security schemes for the API.
// See https://github.com/swagger-api/swagger-spec/blob/master/versions/2.0.md for more details.
// NOTE: These only define the schemes and need to be coupled with a corresponding "security" property
// at the document or operation level to indicate which schemes are required for an operation. To do this,
// you'll need to implement a custom IDocumentFilter and/or IOperationFilter to set these properties
// according to your specific authorization implementation
//
//c.BasicAuth("basic")
// .Description("Basic HTTP Authentication");
//
// NOTE: You must also configure 'EnableApiKeySupport' below in the SwaggerUI section
//c.ApiKey("apiKey")
// .Description("API Key Authentication")
// .Name("apiKey")
// .In("header");
//
//c.OAuth2("oauth2")
// .Description("OAuth2 Implicit Grant")
// .Flow("implicit")
// .AuthorizationUrl("http://petstore.swagger.wordnik.com/api/oauth/dialog")
// //.TokenUrl("https://tempuri.org/token")
// .Scopes(scopes =>
// {
// scopes.Add("read", "Read access to protected resources");
// scopes.Add("write", "Write access to protected resources");
// });
// Set this flag to omit descriptions for any actions decorated with the Obsolete attribute
//c.IgnoreObsoleteActions();
// Each operation be assigned one or more tags which are then used by consumers for various reasons.
// For example, the swagger-ui groups operations according to the first tag of each operation.
// By default, this will be controller name but you can use the "GroupActionsBy" option to
// override with any value.
//
//c.GroupActionsBy(apiDesc => apiDesc.HttpMethod.ToString());
// You can also specify a custom sort order for groups (as defined by "GroupActionsBy") to dictate
// the order in which operations are listed. For example, if the default grouping is in place
// (controller name) and you specify a descending alphabetic sort order, then actions from a
// ProductsController will be listed before those from a CustomersController. This is typically
// used to customize the order of groupings in the swagger-ui.
//
//c.OrderActionGroupsBy(new DescendingAlphabeticComparer());
// If you annotate Controllers and API Types with
// Xml comments (http://msdn.microsoft.com/en-us/library/b2s063f7(v=vs.110).aspx), you can incorporate
// those comments into the generated docs and UI. You can enable this by providing the path to one or
// more Xml comment files.
//
c.IncludeXmlComments(GetXmlCommentsPath());
// Swashbuckle makes a best attempt at generating Swagger compliant JSON schemas for the various types
// exposed in your API. However, there may be occasions when more control of the output is needed.
// This is supported through the "MapType" and "SchemaFilter" options:
//
// Use the "MapType" option to override the Schema generation for a specific type.
// It should be noted that the resulting Schema will be placed "inline" for any applicable Operations.
// While Swagger 2.0 supports inline definitions for "all" Schema types, the swagger-ui tool does not.
// It expects "complex" Schemas to be defined separately and referenced. For this reason, you should only
// use the "MapType" option when the resulting Schema is a primitive or array type. If you need to alter a
// complex Schema, use a Schema filter.
//
//c.MapType<ProductType>(() => new Schema { type = "integer", format = "int32" });
// If you want to post-modify "complex" Schemas once they've been generated, across the board or for a
// specific type, you can wire up one or more Schema filters.
//
//c.SchemaFilter<ApplySchemaVendorExtensions>();
// In a Swagger 2.0 document, complex types are typically declared globally and referenced by unique
// Schema Id. By default, Swashbuckle does NOT use the full type name in Schema Ids. In most cases, this
// works well because it prevents the "implementation detail" of type namespaces from leaking into your
// Swagger docs and UI. However, if you have multiple types in your API with the same class name, you'll
// need to opt out of this behavior to avoid Schema Id conflicts.
//
//c.UseFullTypeNameInSchemaIds();
// Alternatively, you can provide your own custom strategy for inferring SchemaId's for
// describing "complex" types in your API.
//
//c.SchemaId(t => t.FullName.Contains('`') ? t.FullName.Substring(0, t.FullName.IndexOf('`')) : t.FullName);
// Set this flag to omit schema property descriptions for any type properties decorated with the
// Obsolete attribute
//c.IgnoreObsoleteProperties();
// In accordance with the built in JsonSerializer, Swashbuckle will, by default, describe enums as integers.
// You can change the serializer behavior by configuring the StringToEnumConverter globally or for a given
// enum type. Swashbuckle will honor this change out-of-the-box. However, if you use a different
// approach to serialize enums as strings, you can also force Swashbuckle to describe them as strings.
//
//c.DescribeAllEnumsAsStrings();
// Similar to Schema filters, Swashbuckle also supports Operation and Document filters:
//
// Post-modify Operation descriptions once they've been generated by wiring up one or more
// Operation filters.
//
//c.OperationFilter<AddDefaultResponse>();
//
// If you've defined an OAuth2 flow as described above, you could use a custom filter
// to inspect some attribute on each action and infer which (if any) OAuth2 scopes are required
// to execute the operation
//
//c.OperationFilter<AssignOAuth2SecurityRequirements>();
// Post-modify the entire Swagger document by wiring up one or more Document filters.
// This gives full control to modify the final SwaggerDocument. You should have a good understanding of
// the Swagger 2.0 spec. - https://github.com/swagger-api/swagger-spec/blob/master/versions/2.0.md
// before using this option.
//
//c.DocumentFilter<ApplyDocumentVendorExtensions>();
// In contrast to WebApi, Swagger 2.0 does not include the query string component when mapping a URL
// to an action. As a result, Swashbuckle will raise an exception if it encounters multiple actions
// with the same path (sans query string) and HTTP method. You can workaround this by providing a
// custom strategy to pick a winner or merge the descriptions for the purposes of the Swagger docs
//
//c.ResolveConflictingActions(apiDescriptions => apiDescriptions.First());
// Wrap the default SwaggerGenerator with additional behavior (e.g. caching) or provide an
// alternative implementation for ISwaggerProvider with the CustomProvider option.
//
//c.CustomProvider((defaultProvider) => new CachingSwaggerProvider(defaultProvider));
})
.EnableSwaggerUi(c =>
{
// Use the "InjectStylesheet" option to enrich the UI with one or more additional CSS stylesheets.
// The file must be included in your project as an "Embedded Resource", and then the resource's
// "Logical Name" is passed to the method as shown below.
//
//c.InjectStylesheet(containingAssembly, "Swashbuckle.Dummy.SwaggerExtensions.testStyles1.css");
// Use the "InjectJavaScript" option to invoke one or more custom JavaScripts after the swagger-ui
// has loaded. The file must be included in your project as an "Embedded Resource", and then the resource's
// "Logical Name" is passed to the method as shown above.
//
//c.InjectJavaScript(thisAssembly, "Swashbuckle.Dummy.SwaggerExtensions.testScript1.js");
// The swagger-ui renders boolean data types as a dropdown. By default, it provides "true" and "false"
// strings as the possible choices. You can use this option to change these to something else,
// for example 0 and 1.
//
//c.BooleanValues(new[] { "0", "1" });
// By default, swagger-ui will validate specs against swagger.io's online validator and display the result
// in a badge at the bottom of the page. Use these options to set a different validator URL or to disable the
// feature entirely.
//c.SetValidatorUrl("http://localhost/validator");
//c.DisableValidator();
// Use this option to control how the Operation listing is displayed.
// It can be set to "None" (default), "List" (shows operations for each resource),
// or "Full" (fully expanded: shows operations and their details).
//
//c.DocExpansion(DocExpansion.List);
// Specify which HTTP operations will have the 'Try it out!' option. An empty paramter list disables
// it for all operations.
//
//c.SupportedSubmitMethods("GET", "HEAD");
// Use the CustomAsset option to provide your own version of assets used in the swagger-ui.
// It's typically used to instruct Swashbuckle to return your version instead of the default
// when a request is made for "index.html". As with all custom content, the file must be included
// in your project as an "Embedded Resource", and then the resource's "Logical Name" is passed to
// the method as shown below.
//
//c.CustomAsset("index", containingAssembly, "YourWebApiProject.SwaggerExtensions.index.html");
// If your API has multiple versions and you've applied the MultipleApiVersions setting
// as described above, you can also enable a select box in the swagger-ui, that displays
// a discovery URL for each version. This provides a convenient way for users to browse documentation
// for different API versions.
//
//c.EnableDiscoveryUrlSelector();
// If your API supports the OAuth2 Implicit flow, and you've described it correctly, according to
// the Swagger 2.0 specification, you can enable UI support as shown below.
//
//c.EnableOAuth2Support(
// clientId: "test-client-id",
// clientSecret: null,
// realm: "test-realm",
// appName: "Swagger UI"
// //additionalQueryStringParams: new Dictionary<string, string>() { { "foo", "bar" } }
//);
// If your API supports ApiKey, you can override the default values.
// "apiKeyIn" can either be "query" or "header"
//
//c.EnableApiKeySupport("apiKey", "header");
});
}
protected static string GetXmlCommentsPath()
{
return System.String.Format(#"{0}\bin\WebApiSwagger.XML", System.AppDomain.CurrentDomain.BaseDirectory);
}
}
I've created the XML comments file but comments are not seen in the Model section of Swagger UI.
In my case, it was because my models are in a different project than the service.
I added another IncludeXmlComments call in Startup.cs and it works:
c.IncludeXmlComments(xmlPath2); // add Other proj xml comments file, this is needed because it's in a different project.
Just adding the comments isn't enough.
You need to build an XML documentation file and you need to tell swagger where to find it in your configuration.
Go to your project build properties and check XML Documentation File
Then in your swagger config, add the following
c.IncludeXmlComments(string.Format(#"{0}\bin\MyApi.XML",
System.AppDomain.CurrentDomain.BaseDirectory))
Also works if you convert your fields to properties.
public class MyData
{
/// <summary>
/// My code
/// </summary>
public string code { get; set; }
}
The problem seems to be that Swagger does not document fields, only properties. And if you check the generated XML you will see that the variable will have a F or P prefix. https://msdn.microsoft.com/en-us/library/fsbx0t7x(v=vs.110).aspx
I was struggling with that too. What helped me was setting it as a property.
/// <summary>
/// Radius of the circle
/// </summary>
[DataMember]
public double radius;
/// <summary>
/// Colour of the circle
/// </summary>
[DataMember]
public double farba { get; set; }
/// <summary>
/// Some random variable
/// </summary>
[DataMember]
double random { get; set; }
Result
Circle {
radius (number, optional),
farba (number, optional): Colour of the circle ,
random (number, optional)
}
As you can see only public property has description.
Hope it will help.
As other answers state, you need to add documentation files for any projects that house the objects you want comments for. Here is my solution for safely adding more projects.
In the project file, add this line to the opening <PropertyGroup>:
<GenerateDocumentationFile>true</GenerateDocumentationFile>
Then in your swagger config section of the code:
var xmlFiles = new[]
{
//the current assembly (the web api)
$"{Assembly.GetExecutingAssembly().GetName().Name}.xml",
//another assembly housing MyEntityView. Add more lines like this to add more assemblies
$"{Assembly.GetAssembly(typeof(MyEntityView))?.GetName().Name}.xml"
};
foreach(var xmlFile in xmlFiles)
{
var xmlCommentFile = xmlFile;
var xmlCommentsFullPath = Path.Combine(AppContext.BaseDirectory, xmlCommentFile);
if (File.Exists(xmlCommentsFullPath))
{
options.IncludeXmlComments(xmlCommentsFullPath);
}
}

WebApi controller summary is not showing on Swagger documentation

When I enable this documentation feature through Swagger I'm able to see all kind of information about my documentation but there is no details about my Controller name detail/description.
How to show controller documentation content like below example?
/// <summary>
/// Represents the alert api controller class.
/// <summary>
public class XYZController : ApiController
{
}
On enabling swagger I'm not able to see this content any where Represents the XYZ api controller class. here
However I able to see my all method description.
1.) Right click the project and Edit projname.csproj
Add the following
<PropertyGroup>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
</PropertyGroup>
2.) Add the following to AddSwaggerGen in ConfigureServices
// Set the comments path for the Swagger JSON and UI.
var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
c.IncludeXmlComments(xmlPath);
For more details goto:
https://learn.microsoft.com/en-us/aspnet/core/tutorials/getting-started-with-swashbuckle?view=aspnetcore-5.0&tabs=visual-studio
you need to add IncludeXmlComments extension in AddSwaggerGen as below:
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1.0", new Info
{
Title = "My APIs",
Version = "v1.0",
Description = "REST APIs "
});
**// Set the comments path for the Swagger JSON and UI.**
var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
c.IncludeXmlComments(xmlPath);
});
For more details refer here
This is possible, See #Liversage answer on this page https://github.com/domaindrivendev/Swashbuckle/issues/572
services.AddSwaggerGen(c =>
{
var xmlPath = ...;
c.IncludeXmlComments(xmlPath, includeControllerXmlComments: true);
});
Is there following code in the SwaggerConfig class?
GlobalConfiguration.Configuration
.EnableSwagger(c =>
{
c.IncludeXmlComments(string.Format(#"{0}\bin\YourAssemlyName.XML", System.AppDomain.CurrentDomain.BaseDirectory));
As some guys above have reply already, I guess the question was about this:
var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
s.IncludeXmlComments(xmlPath, includeControllerXmlComments: true);
set includeControllerXmlComments: true will allow to take summary of controllers.
I think this is related to the following issue :
https://github.com/domaindrivendev/Swashbuckle/issues/572
It is currently not possible to display the controller summary, according to the maintainer:
The reason this has been low on the priority list is because it's not something I've run into issues with. You can absolutely describe what every action in your API does using XML comments on your actions.
in my case, I only needed to mark to use the XML document
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<DocumentationFile>C:...\CertReports.Host.xml</DocumentationFile>
now, in .net core is easy
config.UseControllerSummaryAsTagDescription = true;