Swashbuckle XML Comments with Property Hiding - c#

Is there a way how to make Swashbuckle take the XML Comments for properties which hide those in the base class?
class Base {
/// <summary>
/// This comment shows in swagger UI.
/// </summary>
public int Value { get; set; }
}
class Model: Base {
/// <summary>
/// This comment is not visible in swagger UI.
/// </summary>
public new int Value { get; set; }
}
Is there any workaround, e.g. using a kind of SchemaFilter?
UPDATED
The above simple example works as expected.
Our problem is probably caused by a wrong configuration of the IncludeXmlComments option as our models come from multiple assemblies.
I found a related discussion on GitHub

Related

Swagger - How to add definitions on child objects in c#

In C# (Asp.Net Core) )I have the following documentation over a child object of type NameValue.
I wish to have the documentation I added here over FromWarehouse, but when Swagger renders, it uses the definition for NameValue, not FromWarehouse.
/// <summary>
/// The warehouse this transfer is coming from
/// </summary>
/// <remarks>GLW, WDI, PSO, SMA, SHW</remarks>
public NameValue FromWarehouse { get; set; }
You need to do 3 things:
The summary should be moved from class property to class.
not here
public NameValue FromWarehouse { get; set; }
but to
/// <summary>
/// The warehouse this transfer is coming from
/// </summary>
/// <remarks>GLW, WDI, PSO, SMA, SHW</remarks>
public class NameValue{
....
You need to add document generation, with Include Xml Comments
services.AddSwaggerGen(c =>
{
var xmlFilename = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
c.IncludeXmlComments(Path.Combine(AppContext.BaseDirectory, xmlFilename));
});
Add this to your .csproj file
<PropertyGroup>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
</PropertyGroup>
This is the example I used
/// <summary>
/// The warehouse this transfer is coming from
/// </summary>
/// <remarks>GLW, WDI, PSO, SMA, SHW</remarks>
public class NameValue
{
/// <summary>
/// The Name
/// </summary>
public string Name { get; set; }
/// <summary>
/// The Value
/// </summary>
public string Value { get; set; }
}
Here is the result:
The remarks, I was not able to include the, but as far as I understand, remarks are used to provide payload example, and it is used on top of the resource method.
All this I use with dotnet 6 and Swashbuckle.AspNetCore Version 6.2.3.
I hope it helps.
Reference to Microsoft documentation.

modelState.isValid not checking required decorated attributes

I'm having this issue with ModelState validation, since I'm using a model with an attribute decorated with [Required] attribute but it never gets invalid, even on null.
Here's the controller:
[HttpPost("x/{sampleString}")]
[ProducesResponseType(StatusCodes.Status303SeeOther)]
public IActionResult Post(string sampleString, SponsorContractorFilterModel model)
{
if (!ModelState.IsValid)
return StatusCode(BadRequest("Model sent is not valid").StatusCode.GetValueOrDefault());
//do stuff, add location on header and send back the 303.
return StatusCode(StatusCodes.Status303SeeOther);
}
And the model is pretty simple:
public class SponsorContractorFilterModel
{
/// <summary>
/// Initializes a new instance of the <see cref="SponsorContractorFilterModel"/> class.
/// </summary>
public SponsorContractorFilterModel()
{
}
/// <summary>
/// Sponsor number.
/// </summary>
[Required]
public int? AnImportantNumber { get; set; }
public List<int> SomeIds { get; set; }
//few more attributes not been decorated on purpose.
}
The thing is that when I send with postman a model object without an "AnImportantNumber" or explicitly null in neither of the cases it shows that is invalid. And when I debug it I can see its actually mapped as null.
I would suggest to use [BindRequired] attribute to make sure data were present on the request. There is No source for a model property section in the docs that explains a bit.
Also there is a bit older article [Required] and [BindRequired] in ASP.NET Core MVC written by Filip W. about that subject. It may be good starting point/inspiration too.
Hope it helps

How to show custom request examples in the .net api documentation?

/// <summary>
/// updates information of a job
/// </summary>
/// <param name="job"></param>
/// <returns>Ok or Error</returns>
/// <example>
/// {
/// "info_id": 1,
/// "some_other_id": 2
/// }
/// </example>
[HttpPost]
[Route("api/job/update")]
public IHttpActionResult update(Models.Job job) {
}
//the model
public class Job {
[Required(AllowEmptyStrings = false)]
[Range(1, Int64.MaxValue)]
public Int64 info_id { get; set; }
public Int64? some_other_id{ get; set; }
public DateTime last_log_time { get; set; }
}
Imagine the setup above. I would like to show the example JSON written inside the doc block of update in the documentation. However, there is shown the serialized JSON of an object typed Job with default values instead.
I don't want developers to think they could or should provide last_log_time to function update. This property shall be shown in a response message, but not sent to the api.
How can I customize the examples for the requests formats per function? Ideally I would state it inside the doc block as shown (the API should only take requests in JSON-format), or maybe per annotations on the properties of the Job-class.
How can we hide a property in WebAPI? the answer provodided here does not help because, as stated above, last_log_time shall be given in the response. If I annotate it with [IgnoreDataMember] it will be ignored globally.
You can add [ApiExplorerSettings(IgnoreApi = true)] to your last_log_time property, but it only hides last_log_time in body parameters.
If you want to hide in sample format, you need customize source code of method WriteSampleObjectUsingFormatter at file Areas\HelpPage\SampleGeneration\HelpPageSampleGenerator.cs

Asp.Net Core Swagger / FromForm /// (triple slash) comments not picked up?

I have a controller method that looks like this:
[HttpPost]
[Consumes("application/x-www-form-urlencoded")]
[Produces("application/json")]
public async Task<IActionResult> GenerateTokenAsync([FromForm]TokenParameters tokenParameters)
TokenParameters looks like this:
public class TokenParameters
{
/// <summary>
/// Specifies the grant type. Must be "password".
/// </summary>
[Required]
public GrantType? grant_type
{
get;
set;
}
/// <summary>
/// Specifies the username.
/// </summary>
[Required]
public string username
{
get;
set;
}
/// <summary>
/// Specifies the password.
/// </summary>
[Required]
public string password
{
get;
set;
}
}
Everything works fine, but the Swagger UI is not picking up the /// triple slash comments for the members. My other controllers use FromBody and /// triple slash comments work fine with those. Seems like the model section at the bottom picks up the comments, but I'm talking about the model description in the light green section when I look at the controller.
I've looked in the schema registry, and the descriptions are indeed there.
EDIT: Using Swashbuckle 5.0 Beta.
EDIT #2: It also doesn't seem to pick up the example values from the schema registry for form parameters either.
Any ideas?
Make sure that your project has the Generate xml documentation option checked.
Also, when you configure Swagger, make sure to have it include the xml comments.
// Register the Swagger generator, defining one or more Swagger documents
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v2", new Info { Title = "my API", Version = "v2" });
// Set the comments path for the Swagger JSON and UI.
var basePath = PlatformServices.Default.Application.ApplicationBasePath;
var xmlPath = Path.Combine(basePath, "myapp.xml");
c.IncludeXmlComments(xmlPath);
});
I too had this issue. My issue was that I was not including the correct XML documentation files. I was including only the web application XML documentation while I had my "creation options" object that was being created from the form data defined in another assembly. Once I had this assembly producing XML documentation and including it in the swagger configuration I was able to get descriptions for each form field item.
Here is my controller method handling the POST from the client:
/// <summary>
/// Create a new very complex object.
/// </summary>
/// <param name="creationOptions">Very complex creation options</param>
/// <returns>The very complex object as a data transfer object.</returns>
[HttpPost]
[Consumes("application/x-www-form-urlencoded")]
public async Task<IActionResult> CreateVeryComplexObject([FromForm] VeryComplexObjectCreationOptions creationOptions) { }
When adding the swagger services I included the documentation from both assemblies:
services.AddSwaggerGen(config =>
{
// All my other swagger configuration here...
config.IncludeXmlComments(System.IO.Path.Combine(AppContext.BaseDirectory, "MyService.API.Web.xml"));
config.IncludeXmlComments(System.IO.Path.Combine(AppContext.BaseDirectory, "MyService.API.Contracts.xml"));
});
This is on Swashbuckle 4.0.1.

EF mapping: unwanted column with a 1 at the end of the name

I've got a class CurrentPage which has a Page property, and it's an enum (of type int):
namespace App.Model.Application
{
using System.Runtime.Serialization;
/// <summary>
/// Represents user the current page of a user in the application
/// </summary>
[DataContract]
public class CurrentPage
{
/// <summary>
/// Gets or sets the unique identifier for this current page.
/// </summary>
[DataMember]
public int Id { get; set; }
/// <summary>
/// Gets or sets the description
/// </summary>
[DataMember]
public string Description { get; set; }
/// <summary>
/// Gets or sets the identifier of the current page to which the user has navigated.
/// </summary>
[DataMember]
public Page Page { get; set; }
/// <summary>
/// Gets or sets the current page as an integer; this is to support Entity Framework limitations regarding enumerations.
/// </summary>
public int PageId
{
get
{
return (int)this.Page;
}
set
{
this.Page = (Page)value;
}
}
}
}
It's mapped like this:
this.Property(cp => cp.Page).IsRequired();
If I try to run Add-Migration in VisualStudio, I end up getting this in my migration code
RenameColumn(table: "dbo.CurrentPage", name: "Page1", newName: "Page");
I don't understand where this 'Page1' name is coming from. There's no Page1 column in the database.
Any ideas? Could it be creating the Page1 column because it somehow thinks the Page column that's already there isn't suitable for being mapped to that property?
Not 100% sure what the cause of this was, but I deleted the PageId property and removed all existing migrations I had. Then I restarted Visual Studio (fwiw). The ran an update-database -script, and finally added a new migration (Add-Migration MyNewMigration) and it all started working again. Not a very satisfying answer I know, but it is working now. I also got a fresh copy of the database, untouched by my model changes before doing all that.

Categories