I have the following ASP.NET Core 7 Web API controller in C# that saves an attachment to Azure Blob Storage:
[MapToApiVersion(Constants.ApiVersions.V1)]
[HttpPost]
[ProducesResponseType(typeof(BlobContentInfo), StatusCodes.Status201Created)]
[ProducesResponseType(typeof(IEnumerable<ValidationError>), StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public async Task<ActionResult<BlobContentInfo>> Post(
[FromRoute] int projectId,
[FromRoute] int equipmentId,
[FromForm] string? description,
[FromForm] byte[] file,
[FromForm] string fileName,
[FromForm] string contentType,
[FromForm] AttachmentType? attachmentType = null)
{
return await TryGetAsync<ActionResult<BlobContentInfo>>(async _ =>
{
var user = await GetUser();
// NDE Logs and IWR Logs attachments don't require an associated equipment
// If they don't have an associated equipment, use ProjectAttachmentsController
var equipment = await Mediator.Send(new GetEquipment { EquipmentId = equipmentId, ProjectId = projectId, User = user });
if (equipment == null)
return NotFound();
var stream = new MemoryStream(file);
var headers = new HeaderDictionary()
{
{ "Content-Type", contentType },
{ "Content-Disposition", $"form-data; name={fileName}; filename={fileName}" },
};
var attachment = new AttachmentUpload
{
EquipmentId = equipmentId,
UploadedOn = DateTimeOffset.UtcNow,
AttachmentType = attachmentType,
Description = description,
FormFile = new FormFile(stream, 0, file.Length, fileName, fileName)
{
Headers = headers
}
};
var result = await _validator.ValidateAsync(attachment);
if (!result.IsValid)
return BadRequest(result.ToValidationErrors());
var uploaded = await Mediator.Send(new UploadAttachment
{
ProjectId = projectId,
AttachmentUpload = attachment,
User = user
});
return CreatedAtAction(nameof(Get), new { projectId, equipmentId }, uploaded);
}, (ex, _) => Error<BlobContentInfo>(ex));
}
I'm using NSwag to generate a client from my API. When it generates BlobContentInfo and its ETag, it's an empty class. As a result, when the client tries to deserialize the ETag (string), it fails.
Here are the definitions of BlobContentInfo and its ETag property.
/// <summary>
/// BlobContentInfo
/// </summary>
[System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "13.19.0.0 (NJsonSchema v10.9.0.0 (Newtonsoft.Json v13.0.0.0))")]
public partial class BlobContentInfo
{
/// <summary>
/// The ETag contains a value that you can use to perform operations conditionally. If the request version is 2011-08-18 or newer, the ETag value will be in quotes.
/// </summary>
[Newtonsoft.Json.JsonProperty("eTag", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)]
public ETag ETag { get; set; }
/// <summary>
/// Returns the date and time the container was last modified. Any operation that modifies the blob, including an update of the blob's metadata or properties, changes the last-modified time of the blob.
/// </summary>
[Newtonsoft.Json.JsonProperty("lastModified", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)]
public System.DateTimeOffset LastModified { get; set; }
/// <summary>
/// If the blob has an MD5 hash and this operation is to read the full blob, this response header is returned so that the client can check for message content integrity.
/// </summary>
[Newtonsoft.Json.JsonProperty("contentHash", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)]
public byte[] ContentHash { get; set; }
/// <summary>
/// A DateTime value returned by the service that uniquely identifies the blob. The value of this header indicates the blob version, and may be used in subsequent requests to access this version of the blob.
/// </summary>
[Newtonsoft.Json.JsonProperty("versionId", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)]
public string VersionId { get; set; }
/// <summary>
/// The SHA-256 hash of the encryption key used to encrypt the blob. This header is only returned when the blob was encrypted with a customer-provided key.
/// </summary>
[Newtonsoft.Json.JsonProperty("encryptionKeySha256", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)]
public string EncryptionKeySha256 { get; set; }
/// <summary>
/// Returns the name of the encryption scope used to encrypt the blob contents and application metadata. Note that the absence of this header implies use of the default account encryption scope.
/// </summary>
[Newtonsoft.Json.JsonProperty("encryptionScope", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)]
public string EncryptionScope { get; set; }
/// <summary>
/// The current sequence number for the page blob. This is only returned for page blobs.
/// </summary>
[Newtonsoft.Json.JsonProperty("blobSequenceNumber", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)]
public long BlobSequenceNumber { get; set; }
}
/// <summary>
/// Represents an HTTP ETag.
/// </summary>
[System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "13.19.0.0 (NJsonSchema v10.9.0.0 (Newtonsoft.Json v13.0.0.0))")]
public partial class ETag
{
}
Is there anyway to get NSwag to generate this properly? If not, is there a way to ignore the ETag entirely in the client generation?