Comments (13)
Oh oh - that doesn't sound good. It can't have been fun trying to figure out that issue :(
When I first built Swashbuckle, I was only able to test against the API's and contracts I'm currently involved with. It's been awesome to have it out there in the wild and see how it holds up against all the different ways people are using WebApi. But, it's definitely highlighted some interesting bugs.
I'm guessing the issue is occurring for any type that contains a member of the same type? For example
public class Person
{
from swashbuckle.webapi.
Above continued ...
public class Person
{
public IEnumerable Friends { get; set;
}
This is something I thought I'd accounted for but clearly didn't get quite right.
I'll try get to it next week or alternatively please feel free to submit a pull request?
Thanks for bringing this to my attention
Richie
from swashbuckle.webapi.
I had a look at the code there but I'm not sure what to do about it. It says "I see your JToken is enumerable. It can hold more JTokens". Then it parses the child object which is another JToken---hence the infinite loop.
My original problem was that I was not able to figure out how to bind to the incoming json object to a strongly typed object using FromBody (see: http://blog.travisgosselin.com/web-api-signatures-with-multiple-complex-parameters/) when I wrote the WebApi call. I finally gave up and declared it a JObject and parsed the incoming data structure (which is arbitrarily deep) internally.
Apart from detecting the error condition where there's a cycle of nested types, is there a way to override the api-descriptor generator so that I can provide my own description of what the posted body should be?
from swashbuckle.webapi.
Just took a look at this and you're correct - it's not going to be the easiest thing to solve. I'd have to really rethink the recursive algorithm. But it seems like a common scenario that definitely should be supported. I definitely intend on taking a deeper dive when I get some free time.
For your scenario, It's probably a little pointless for Swashbuckle to generate a model spec for JObjects as the resulting description would be very "meta" and have no context of the actual operation. In fact, I think I'll special case this (as is currently done for HttpResponseMessage) to be treated as undetermined. The net effect would be no model description in the UI
For your scenario, there are a couple of options you may want to investigate.
- Swashbuckle provides a couple of hooks that may help (see the readme for a full description)
You can override the dynamic ModelSpec generation for specific types by setting a pre-canned version at config time (app start) ...
SwahbuckleSpecConfig.Customize(c =>
{
c.MapType(new ModelSpec { //populate this however you see fit })
}
You could use this to get past the infinite loop problem, but you still won't be able to differentiate between the JObject description for different operations.
- Another option, involves injecting a custom filter (IOperationSpecFilter) that can be used to update the specs generated per operation. Something like the following
SwahbuckleSpecConfig.Customize(c =>
{
c.MapType(new ModelSpec()) // Empty by default and then populate using below filter
c.PostFilter()
}
The the filter implementation would look something like the following ...
public class ApplyCustomDescriptions : IOperationSpecFilter
{
public void Apply(ApiDescription apiDescription, OperationSpec operationSpec, ModelSpecMap modelSpecMap)
{
ModelSpec modelSpec;
switch (operationSpec.Nickname)
{
case "Orders_Reorder":
modelSpec = modelSpecMap.FindOrCreateFor(typeof(ReorderRequest));
operationSpec.Parameters.Last().Type = modelSpec.Id;
break;
case "Orders_SomeOtherOp":
modelSpec = modelSpecMap.FindOrCreateFor(typeof(SomeOtherOpRequest));
operationSpec.Parameters.Last().Type = modelSpec.Id;
break;
}
}
}
// You'll have to create a dummy DTO to describe each custom message
internal class ReorderRequest
{
public int OrderId { get; set; }
public string Notes { get; set; }
}
internal class SomeOtherOpRequest
{
public int Foo { get; set; }
public string Bar { get; set; }
}
It's a little involved but should work - at some point I'd like to update the extensibility to make this kind of thing a little easier.
Cheers
from swashbuckle.webapi.
Ah, #1 seems to get me past the problem:
SwaggerSpecConfig.Customize(
c => c.MapType<JToken>(new ModelSpec())
);
I'll have a look next week to see if I can get #2 to produce something useful for this situation.
Thanks!!
-Mike
from swashbuckle.webapi.
The MapType method looks like the way to go for me as well, I was doing something with a custom parameter binding for file uploads and ran into the stack overflow as well. Cause was similar to this (FileInfo was on another type):
public class FailController : ApiController
{
public HttpResponseMessage PostFail(FileInfo file) {
throw new NotImplementedException();
}
}
from swashbuckle.webapi.
Hey
So, I think I have the infinite loop problem fixed. I've implemented progress tracking within the recursive calls to detect self-references and act accordingly
It's currently in a branch called "fix_infinite_loop_issue"
I'd be very grateful if you could pull this down and ensure your original issue doesn't repro
Thanks
from swashbuckle.webapi.
Fixed and released as of version 3.1.1
from swashbuckle.webapi.
I am seeing infinite stack related to JToken again in 4.0
from swashbuckle.webapi.
Hey @VaclavK
Can you elaborate a little more on this so I can get a repro? If you can provide me with your action signature (or a sample one that causes the issue) it would be very helpful.
Also, it's unlikely that I'll get a fix pushed in the next week as I'm currently doing a lot of Ruby work and am without a .Net development environment. I should be up and running again this weekend though and will get to this as soon possible.
from swashbuckle.webapi.
This is my method signature (which I think is pretty valuable as to enforce JSON constraint while not enforcing full strong type validation - e.g. http://www.hanselman.com/blog/TinyHappyFeatures2ASPNETWebAPIInVisualStudio2012.aspx)
public HttpResponseMessage Post([FromBody] JToken data)
JToken is public abstract class JToken : IJEnumerable, IEnumerable, ... and this is where the infinite loop resides
I "fixed" it for now using the same strategy as the thread above uses
c.MapType(() => { ....
from swashbuckle.webapi.
I've just pushed a pre-release version (4.1.0-rc1) including a fix for this issue.
If you get a spare moment, I'd really appreciate you taking the time to test it out and confirm your issue has been resolved.
Install-Package Swashbuckle -Pre
Let me know how it goes
Thanks
Richie
from swashbuckle.webapi.
Yes it is working - showing as string, which is technically correct of course but slightly obscures that the controller is actually using JObject in its signature (it would highlight the input needs to be JSON as opposed to any string)
Vaclav
Date: Thu, 28 Aug 2014 08:04:31 -0700
From: [email protected]
To: [email protected]
CC: [email protected]
Subject: Re: [Swashbuckle] Infinite loop in JObject (#9)
I've just pushed a pre-release version (4.1.0-rc1) including a fix for this issue.
If you get a spare moment, I'd really appreciate you taking the time to test it out and confirm your issue has been resolved.
Install-Package Swashbuckle -Pre
Let me know how it goes
Thanks
Richie
—
Reply to this email directly or view it on GitHub.
from swashbuckle.webapi.
Related Issues (20)
- Custom model binder not working with swagger HOT 1
- Custom DocumentFilter not being applied HOT 1
- Client Code Generating Endpoints
- I cross domain request, do not want the browser to have pre check, options
- Change Controller Name HOT 1
- Model name is re-added to the Parameter if using AddVersionedApiExplorer
- swagger asp.net core failed to load api definition
- 876
- Swagger UI not loading with error Microsoft.AspNet.WebApi net::ERR_INCOMPLETE_CHUNKED_ENCODING 200 (OK) HOT 1
- Converting Swagger 2.0 to OpenAPI 3.0
- How can I not write an httppost in each method by default?
- How can I not specify httppost in each method?
- Swagger Query Parameter name prefix
- `UseOneOfForPolymorphism` puts `discriminator` in useless place in swagger-file
- Swashbuckle Example Data Type not showing correct markup HOT 1
- "Validation failed" error due to square brackets in $ref - swagger 2.0 json generated by swashbuckle web api - While importing in API Management HOT 1
- Restricting swagger ui endpoints and preventing developers from signing in twice
- UX Swagger API List, methods or operations should be grouped by verb for each controller
- Kubernetes | Dotnet Core | Swagger.json 404 not found error
- Update Nugets for Swashbuckle.Core
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from swashbuckle.webapi.