Open mikoskinen opened 2 years ago
Yea this looks like a bug with default responses, think another condition needs to check for HasResult
here instead of just using UnwrappedResultDefaultValue
:
https://github.com/RicoSuter/NSwag/blob/67cc25b63a92df49d185dfa15486ba9e60c0db39/src/NSwag.CodeGeneration.CSharp/Templates/Client.Class.liquid#L337-L342
Having said that, it's only falling back to that as you haven't specified any response types looking at your API spec, whereas they are specified on other patch endpoints.
"responses" : {
"default" : {
"description" : "default response",
"content" : {
"application/json" : { }
}
}
}
With responses in this way, is also returning the same return default(void);.
"responses": {
"200": {
"description": "OK",
"content": {
"application/json": {},
"text/json": {},
"application/xml": {},
"text/xml": {}
}
},
The Open Api spec comes from an external provider (a3laboral-services-api ) so I can not fix it in the external API. So, Is there a workaround while this issue get fixed?
Thank you in advance
@PedroJesusRomeroOrtega what does the API actually return for the request? You could manually edit the spec after downloading it to make it match for now, and possibly contact the provider to get it fixed.
+1 on this issue.
"responses": {
"200": {
"description": "Ok",
"content": {
"application/vnd.mycompany.v1+json": { }
}
},
results in
var status_ = (int)response_.StatusCode;
if (status_ == 200)
{
return default(void);
}
@RicoSuter would you accept a PR for this issue?
any new on this? https://community.openproject.org/api/v3/spec.yml seems to have something similar, though I don't know if it's a problem of nswag or openproject.
Can anyone tell me if this is the same or similar cause as yours? At least I'm getting default(void) for returncode 200, though swagger seems to return something referenced by "$ref": "#/components/examples/Views"
. So I should definitely get a result here, as far as I see in your examples you don't expect any result.
"/api/v3/views": {
"get": {
"parameters": [
{
"description": "JSON specifying filter conditions.\nCurrently supported filters are:\n\n+ project: filters views by the project their associated query is assigned to. If the project filter is passed with the `!*` (not any) operator, global views are returned.\n\n+ id: filters views based on their id\n\n+ type: filters views based on their type",
"example": "[{ \"project_id\": { \"operator\": \"!*\", \"values\": null }\" }]",
"in": "query",
"name": "filters",
"required": false,
"schema": {
"type": "string"
}
}
],
"responses": {
"200": {
"content": {
"application/hal+json": {
"examples": {
"Queries": {
"$ref": "#/components/examples/Views"
}
}
}
},
"description": "OK",
"headers": {}
}
},
"tags": [
"Views"
],
"description": "Returns a collection of Views. The collection can be filtered via query parameters similar to how work packages are filtered.",
"operationId": "List_views",
"summary": "List views"
}
}
/// <param name="cancellationToken">A cancellation token that can be used by other objects or threads to receive notice of cancellation.</param>
/// <summary>
/// List views
/// </summary>
/// <remarks>
/// Returns a collection of Views. The collection can be filtered via query parameters similar to how work packages are filtered.
/// </remarks>
/// <param name="filters">JSON specifying filter conditions.
/// <br/>Currently supported filters are:
/// <br/>
/// <br/>+ project: filters views by the project their associated query is assigned to. If the project filter is passed with the `!*` (not any) operator, global views are returned.
/// <br/>
/// <br/>+ id: filters views based on their id
/// <br/>
/// <br/>+ type: filters views based on their type</param>
/// <returns>OK</returns>
/// <exception cref="ApiException">A server side error occurred.</exception>
public virtual async System.Threading.Tasks.Task ViewsAsync(string filters, System.Threading.CancellationToken cancellationToken)
{
var urlBuilder_ = new System.Text.StringBuilder();
urlBuilder_.Append(BaseUrl != null ? BaseUrl.TrimEnd('/') : "").Append("/api/v3/views?");
if (filters != null)
{
urlBuilder_.Append(System.Uri.EscapeDataString("filters") + "=").Append(System.Uri.EscapeDataString(ConvertToString(filters, System.Globalization.CultureInfo.InvariantCulture))).Append("&");
}
urlBuilder_.Length--;
var client_ = _httpClient;
var disposeClient_ = false;
try
{
using (var request_ = new System.Net.Http.HttpRequestMessage())
{
request_.Method = new System.Net.Http.HttpMethod("GET");
request_.Headers.Accept.Add(System.Net.Http.Headers.MediaTypeWithQualityHeaderValue.Parse("application/hal+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);
var disposeResponse_ = true;
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;
if (status_ == 200)
{
return default(void);
}
else
{
var responseData_ = response_.Content == null ? null : await response_.Content.ReadAsStringAsync().ConfigureAwait(false);
throw new ApiException("The HTTP status code of the response was not expected (" + status_ + ").", status_, responseData_, headers_, null);
}
}
finally
{
if (disposeResponse_)
response_.Dispose();
}
}
}
finally
{
if (disposeClient_)
client_.Dispose();
}
}
I ended up with modifying resulting generated code - code.Replace("return default(void);", "return;");
. Roughly but it works.
As said for me this wouldn't work, since I'm expecting a result here. Maybe this is a bug on its own.
For now I'm working around this with a custom liquid template that manually detects when the default return is default(void)
but this solution is less than ideal
The C# generator generated client method with the following signature:
public async System.Threading.Tasks.Task AttachmentsPatchAsync(int attachmentId, AttachmentRename body, System.Threading.CancellationToken cancellationToken)
Problem is that the method tries to return default(void) which doesn't compile:
Instead of this I suppose plain return would work.
This is with OperationGenerationMode = OperationGenerationMode.MultipleClientsFromPathSegments.
The Open API spec is: https://dev.procountor.com/static/swagger.latest.json