Git Product home page Git Product logo

Comments (13)

domaindrivendev avatar domaindrivendev commented on August 15, 2024

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.

domaindrivendev avatar domaindrivendev commented on August 15, 2024

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.

mikebridge avatar mikebridge commented on August 15, 2024

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.

domaindrivendev avatar domaindrivendev commented on August 15, 2024

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.

  1. 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.

  1. 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.

mikebridge avatar mikebridge commented on August 15, 2024

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.

mwoodruff avatar mwoodruff commented on August 15, 2024

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.

domaindrivendev avatar domaindrivendev commented on August 15, 2024

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.

domaindrivendev avatar domaindrivendev commented on August 15, 2024

Fixed and released as of version 3.1.1

from swashbuckle.webapi.

VaclavK avatar VaclavK commented on August 15, 2024

I am seeing infinite stack related to JToken again in 4.0

from swashbuckle.webapi.

domaindrivendev avatar domaindrivendev commented on August 15, 2024

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.

VaclavK avatar VaclavK commented on August 15, 2024

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.

domaindrivendev avatar domaindrivendev commented on August 15, 2024

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.

VaclavK avatar VaclavK commented on August 15, 2024

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)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo 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.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.