Hi! TL;DR: .NET Clients generated from swagger.json cannot parse models from API because they think that response.Content will contain the Model, but the model is wrapped in a response class, which makes the deserialization fail. How to solve this?
I am making a .NET client for accessing my application's API externally, so I've generated a client with Swagger Codegen (<a class="postlink" href="https://github.com/swagger-api/swagger-codegen">https://github.com/swagger-api/swagger-codegen</a>). But when the client is trying to parse a response, it fails because it thinks that the request.Content is going to be the same as the model defined in the swagger.json, but it isn't. The model is wrapped in a response body, which makes the deserialization fail.
I.e. for TokenAuth/Authenticate client expects response.Content be like { "accessToken": "wtqt2...warar", "encrypted..": ...}, but instead it is {"result": { "accessToken": "wtqt2...warar", "encrypted..": ...}, "targetUrl": "..", ....}.
I'm not sure where the fault lies here, is there something wrong in the swagger.json, Swagger Codegen or is there some kind of configuration in Codegen I'm missing?
PS. I did a quick try in NSwag and the problem seems to be there as well. Weird thing is that it obviously works for DS.
Regards
2 Answer(s)
-
0
This is because ABP wraps response by AjaxResponse class but does it on the runtime. So, swagger invistigation can not know that.
There are some possible solutions of this problem:
You can disable wrapping at all (<a class="postlink" href="https://aspnetboilerplate.com/Pages/Documents/AspNet-Core#result-filter">https://aspnetboilerplate.com/Pages/Doc ... ult-filter</a>). It would be good if we can do it per client (Say that client sends an HTTP Header indicates that it does not want wrapping. I don't know if nswag allows custom headers, but ABP can not do such a dynamic wrapping yet - I created an issue since thought that can be a good feature: <a class="postlink" href="https://github.com/aspnetboilerplate/aspnetboilerplate/issues/2213">https://github.com/aspnetboilerplate/as ... ssues/2213</a>)
You can intercept result and modify it in the client before nswag parse it. But I don't if nswag proxies provide such a customization point. We do it for angular for example by overriding Http service and it works fine. Thus, you can also handle other AjaxResponse properties like error messages.
We can make ABP provides wrapped class model to API explorer (which is used by nswag). But this could be a little hard. And it also breaks our current Angular design. We think AjaxResponse should be handled in a middleware rather than the application itself, so 2. solution would be the best.
-
0
Thank you!
I solved it with method 2. I tried with NSwag first, but since it does not generate a base client I was required to make a partial class with the interception for every controller, which is a bit tedious and takes away a part of the benefits of code generation. Therefore I went for Swagger Codegen instead, where I only need to make a partial of the base ApiClient for the interception. It was also easier to solve the authorization part in Codegen.