swagger-api / swagger-api/swagger-codegen
[CSharp] ASP.NET Core [FromQuery] parameter doesn't follow the DataMember attributes with classes
Nobody has claimed this yet.
- Dominant language
- Mustache
- Stars
- 17.8k
- Forks
- 6k
- PR merge metrics
- No merged PRs in 30d
Description
Description
I have a simple request class with DataContract and DataMember attributes specified:
[DataContract(Name = "getOrdersRequest")]
public class GetOrdiniRequest
{
[DataMember(Name = "id")]
public int? Id { get; set; }
[DataMember(Name = "plant")]
public string Stabilimento { get; set; }
[DataMember(Name = "warehouse")]
public string Magazzino { get; set; }
[DataMember(Name = "group")]
public string Raggruppamento { get; set; }
[DataMember(Name = "orderType")]
public string TipoOrdine { get; set; }
[DataMember(Name = "orderYear")]
public int? AnnoOrdine { get; set; }
[DataMember(Name = "orderNumber")]
public string NumeOrdine { get; set; }
[DataMember(Name = "paging")]
public PagingParameters Paging { get; set; }
}
In an ASP.NET web api controller I have this type of method with that class as a parameter (pay attention at the FromQuery attribute):
[HttpGet()]
[ProducesResponseType(200)]
public Task<ActionResult<IEnumerable<OrdineTestataDto>>> GetOrdiniAsync([FromQuery] GetOrdiniRequest request) =>
{
...body method...
}
The client code generated from this method doesn't follow the DataMember attributes, so every parameter in the code generated have the name of the original property.
Example: "Stabilimento" should be "plant"
Swagger version
Assembly NSwag.AspNetCore, Version=13.2.3.0
Swagger declaration file content or url
public async System.Threading.Tasks.Task<System.Collections.Generic.IEnumerable<OrdineTestataDto>> GetOrdiniAsync(
int? id = null, string stabilimento = null, string magazzino = null,
string raggruppamento = null, string tipoOrdine = null,
int? annoOrdine = null, string numeOrdine = null,
int? paging_PageNumber = null, int? paging_PageSize = null,
int? paging_Skip = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken))
{
var urlBuilder_ = new System.Text.StringBuilder();
urlBuilder_.Append(BaseUrl != null ? BaseUrl.TrimEnd('/') : "").Append("/api/Orders?");
if (id != null)
{
urlBuilder_.Append(System.Uri.EscapeDataString("Id") + "=").Append(System.Uri.EscapeDataString(ConvertToString(id, System.Globalization.CultureInfo.InvariantCulture))).Append("&");
}
if (stabilimento != null)
{
urlBuilder_.Append(System.Uri.EscapeDataString("Stabilimento") + "=").Append(System.Uri.EscapeDataString(ConvertToString(stabilimento, System.Globalization.CultureInfo.InvariantCulture))).Append("&");
}
if (magazzino != null)
{
urlBuilder_.Append(System.Uri.EscapeDataString("Magazzino") + "=").Append(System.Uri.EscapeDataString(ConvertToString(magazzino, System.Globalization.CultureInfo.InvariantCulture))).Append("&");
}
if (raggruppamento != null)
{
urlBuilder_.Append(System.Uri.EscapeDataString("Raggruppamento") + "=").Append(System.Uri.EscapeDataString(ConvertToString(raggruppamento, System.Globalization.CultureInfo.InvariantCulture))).Append("&");
}
if (tipoOrdine != null)
{
urlBuilder_.Append(System.Uri.EscapeDataString("TipoOrdine") + "=").Append(System.Uri.EscapeDataString(ConvertToString(tipoOrdine, System.Globalization.CultureInfo.InvariantCulture))).Append("&");
}
if (annoOrdine != null)
{
urlBuilder_.Append(System.Uri.EscapeDataString("AnnoOrdine") + "=").Append(System.Uri.EscapeDataString(ConvertToString(annoOrdine, System.Globalization.CultureInfo.InvariantCulture))).Append("&");
}
if (numeOrdine != null)
{
urlBuilder_.Append(System.Uri.EscapeDataString("NumeOrdine") + "=").Append(System.Uri.EscapeDataString(ConvertToString(numeOrdine, System.Globalization.CultureInfo.InvariantCulture))).Append("&");
}
if (paging_PageNumber != null)
{
urlBuilder_.Append(System.Uri.EscapeDataString("Paging.PageNumber") + "=").Append(System.Uri.EscapeDataString(ConvertToString(paging_PageNumber, System.Globalization.CultureInfo.InvariantCulture))).Append("&");
}
if (paging_PageSize != null)
{
urlBuilder_.Append(System.Uri.EscapeDataString("Paging.PageSize") + "=").Append(System.Uri.EscapeDataString(ConvertToString(paging_PageSize, System.Globalization.CultureInfo.InvariantCulture))).Append("&");
}
if (paging_Skip != null)
{
urlBuilder_.Append(System.Uri.EscapeDataString("Paging.Skip") + "=").Append(System.Uri.EscapeDataString(ConvertToString(paging_Skip, System.Globalization.CultureInfo.InvariantCulture))).Append("&");
}
urlBuilder_.Length--;
var client_ = _httpClient;
try
{
using (var request_ = await CreateHttpRequestMessageAsync(cancellationToken).ConfigureAwait(false))
{
request_.Method = new System.Net.Http.HttpMethod("GET");
request_.Headers.Accept.Add(System.Net.Http.Headers.MediaTypeWithQualityHeaderValue.Parse("application/json"));
PrepareRequest(client_, request_, urlBuilder_);
var url_ = urlBuilder_.ToString();
request_.RequestUri = new System.Uri(url_, System.UriKind.RelativeOrAbsolute);
PrepareRequest(client_, request_, url_);
var response_ = await client_.SendAsync(request_, System.Net.Http.HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false);
try
{
var headers_ = System.Linq.Enumerable.ToDictionary(response_.Headers, h_ => h_.Key, h_ => h_.Value);
if (response_.Content != null && response_.Content.Headers != null)
{
foreach (var item_ in response_.Content.Headers)
headers_[item_.Key] = item_.Value;
}
ProcessResponse(client_, response_);
var status_ = ((int)response_.StatusCode).ToString();
if (status_ == "200")
{
var objectResponse_ = await ReadObjectResponseAsync<System.Collections.Generic.IEnumerable<OrdineTestataDto>>(response_, headers_).ConfigureAwait(false);
return objectResponse_.Object;
}
else
if (status_ != "200" && status_ != "204")
{
var responseData_ = response_.Content == null ? null : await response_.Content.ReadAsStringAsync().ConfigureAwait(false);
throw new WebApiException("The HTTP status code of the response was not expected (" + (int)response_.StatusCode + ").", (int)response_.StatusCode, responseData_, headers_, null);
}
return default(System.Collections.Generic.IEnumerable<OrdineTestataDto>);
}
finally
{
if (response_ != null)
response_.Dispose();
}
}
}
finally
{
}
}
Suggest a fix/enhancement
Every parameters should follow the data member attribute
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the ASP.NET Core [FromQuery] parameter handling and the generated C# client shown in the report. Check how DataMember names are represented for query parameters, including nested Paging fields. Done means the generated request uses names such as "plant" instead of "Stabilimento" while preserving the other query parameters.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- csharp
- Domain
- api
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100