Skip to content

Issues related to swagger documentation #310

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
vanikulkarniAtFIS opened this issue Jun 14, 2018 · 8 comments
Closed

Issues related to swagger documentation #310

vanikulkarniAtFIS opened this issue Jun 14, 2018 · 8 comments
Assignees

Comments

@vanikulkarniAtFIS
Copy link

We are facing some issue. The properties of json are in camel case whereas it should have been the way they are defined in the entity.
By default the name of api controller also appears in camel case
The sample application (SwaggerOdataWebApiSample) create by you also has this issue.
Any pointers how to resolve this?
Entity :
public class Assessment
{
public int Id { get; set; }
public string AssessmentName { get; set; }
public long? AssessmentIdentifier { get; set; }
}

We did following setting for Default PropertyNames Convension still it displays Entity Propertis in Camel Case in API responce.
//httpConfiguration.Formatters.JsonFormatter.SerializerSettings.ContractResolver = new DefaultContractResolver();
API Response structure:
{
Id :123
assessmentName:"Test"
assessmentIdentifier:"12345"
}

Issue No 2:

Package Required : Swashbuckle.OData

We are using Swashbuckle.OData package to display Odata Query option on Swagger document. Following configuration is done.

configuration.EnableSwagger(SwaggerDocsRoute, swagger =>
{
swagger.CustomProvider(defaultProvider => new ODataSwaggerProvider(defaultProvider, swagger,configuration).Configure(odataConfig =>
{
odataConfig.IncludeNavigationProperties();
}));
}).EnableSwaggerUi(SwaggerUiRoute, swagger => swagger.EnableDiscoveryUrlSelector());

After Odata Versiong ODataSwaggerProvider throws Exception -
Additional information: Value cannot be null.
{"Value cannot be null.\r\nParameter name: routeData"}
at System.Net.Http.HttpRequestMessageExtensions.SetRouteData(HttpRequestMessage request, IHttpRouteData routeData)
at Swashbuckle.OData.Descriptions.SwaggerRouteStrategy.CreateHttpRequestMessage(HttpMethod httpMethod, Operation potentialOperation, SwaggerRoute potentialSwaggerRoute, HttpConfiguration httpConfig) in C:\Users\rbeauchamp\Documents\GitHub\Swashbuckle.OData\Swashbuckle.OData\Descriptions\SwaggerRouteStrategy.cs:line 105
at Swashbuckle.OData.Descriptions.SwaggerRouteStrategy.GetActionDescriptors(HttpMethod httpMethod, Operation potentialOperation, SwaggerRoute potentialSwaggerRoute, HttpConfiguration httpConfig) in C:\Users\rbeauchamp\Documents\GitHub\Swashbuckle.OData\Swashbuckle.OData\Descriptions\SwaggerRouteStrategy.cs:line 67
at Swashbuckle.OData.Descriptions.SwaggerRouteStrategy.GetActionDescriptors(SwaggerRoute potentialSwaggerRoute, HttpConfiguration httpConfig) in C:\Users\rbeauchamp\Documents\GitHub\Swashbuckle.OData\Swashbuckle.OData\Descriptions\SwaggerRouteStrategy.cs:line 52
at Swashbuckle.OData.Descriptions.SwaggerRouteStrategy.<>c__DisplayClass3_0.b__1(SwaggerRoute potentialSwaggerRoute) in C:\Users\rbeauchamp\Documents\GitHub\Swashbuckle.OData\Swashbuckle.OData\Descriptions\SwaggerRouteStrategy.cs:line 41
at System.Linq.Enumerable.d__162.MoveNext() at System.Linq.Enumerable.<SelectManyIterator>d__162.MoveNext()
at System.Linq.Enumerable.d__631.MoveNext() at System.Linq.Enumerable.<SelectManyIterator>d__162.MoveNext()
at System.Collections.Generic.List1..ctor(IEnumerable1 collection)
at System.Linq.Enumerable.ToList[TSource](IEnumerable1 source) at Swashbuckle.OData.CollectionExtentions.ToCollection[T](IEnumerable1 source) in C:\Users\rbeauchamp\Documents\GitHub\Swashbuckle.OData\Swashbuckle.OData\CollectionExtentions.cs:line 77
at Swashbuckle.OData.Descriptions.ODataApiExplorer.GetApiDescriptions() in C:\Users\rbeauchamp\Documents\GitHub\Swashbuckle.OData\Swashbuckle.OData\Descriptions\ODataApiExplorer.cs:line 43
at System.Lazy`1.CreateValue()

Issue No -3
Compile time error is occured for Odata ApiExplorer.
{"Object reference not set to an instance of an object."}
at Microsoft.Web.Http.Description.TypeExtensions.<>c__DisplayClass10_0.b__0(IEdmStructuredType t)
at System.Linq.Enumerable.FirstOrDefault[TSource](IEnumerable1 source, Func2 predicate)
at Microsoft.Web.Http.Description.TypeExtensions.GetStructuredType(Type type, IEdmModel model, IAssembliesResolver assembliesResolver)
at Microsoft.Web.Http.Description.TypeExtensions.SubstituteIfNecessary(Type type, IServiceProvider serviceProvider, IAssembliesResolver assembliesResolver, ModelTypeBuilder modelTypeBuilder)
at Microsoft.Web.Http.Description.ODataApiExplorer.CreateParameterDescriptionFromBinding(HttpParameterBinding parameterBinding, IServiceProvider serviceProvider, IAssembliesResolver assembliesResolver)
at Microsoft.Web.Http.Description.ODataApiExplorer.CreateParameterDescriptions(HttpActionDescriptor actionDescriptor, IHttpRoute route)
at Microsoft.Web.Http.Description.ODataApiExplorer.ExploreRouteActions(IHttpRoute route, HttpControllerDescriptor controllerDescriptor, IHttpActionSelector actionSelector, Collection1 apiDescriptions, ApiVersion apiVersion) at Microsoft.Web.Http.Description.ODataApiExplorer.ExploreRouteControllers(IDictionary2 controllerMappings, IHttpRoute route, ApiVersion apiVersion)
at Microsoft.Web.Http.Description.VersionedApiExplorer.InitializeApiDescriptions()
at System.Lazy1.CreateValue() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Lazy1.get_Value()
at Microsoft.Web.Http.Description.VersionedApiExplorer.get_ApiDescriptions()

@commonsensesoftware
Copy link
Collaborator

Issue 1

OData doesn't use the default JSON MediaTypeFormatter; it uses its own. Camelcase is very common for JSON. I suspect you are using the configuration in the examples I provide, which enable this. Simply remove this configuration. For example:

var modelBuilder = new VersionedODataModelBuilder( configuration )
{
    // configuration shown in example using camelcase
    // ModelBuilderFactory = () => new ODataConventionModelBuilder().EnableLowerCamelCase(),

    // default configuration using source case, which usually Pascalcase
    ModelBuilderFactory = () => new ODataConventionModelBuilder(),

    // remaining configuration ...
};

Issue 2

I really know very little about the Swashbuckle.OData library or project. I don't use it or support it. You should have everything you need with the OData API versioning, OData API Explorer, and vanilla Swashbuckle. If there is something not supported that you need, I'd be interested in hearing about it to determine if a new feature is required. My recommendation would be to remove Swashbuckle.OData all together. It shouldn't be needed.

Issue 3

I'm not sure what this is. Does it repro in the example that you previously provided? If you can provide a copy of the most version of that sample where the scenario repros, I'll take a look. It's possible there's a bug.

@commonsensesoftware
Copy link
Collaborator

Were you able to get things working? Issue 3 turned out to be a real issue reported by another user. The issue only occurs when you host on IIS. You made no mention of that, but I assume you must be because that's the only case where I've see this occur. The latest version of the package - Microsoft.AspNet.OData.Versioning.ApiExplorer (v1.2.2) fixes the issue.

Let me know if you have any other issues or questions.

@commonsensesoftware
Copy link
Collaborator

It seems that much of this issue is a duplicate of #302 and you have resolved your issue. Should that not be the case, feel free to come back. Thanks.

@vanikulkarniAtFIS
Copy link
Author

We are still getting below exception after using the latest package.
If we use DTOs instead on EF entities the issue does not occur

Runtime error occurs even after updating the package Microsoft.AspNet.OData.Versioning.ApiExplorer to v1.2.2
The code throws exception in SwaggerConfig at: apiExplorer.ApiDescriptions

The code works when there are only Dtos in the ODataModelBuilder. However it throws exception when there are entities.

Code Snippet (SwaggerConfig) :
public static void Register(HttpConfiguration configuration)
{
if (!IsRestApiDocsEnabled())
return;

        var apiExplorer = configuration.AddODataApiExplorer(
            options =>
            {
                options.GroupNameFormat = "'v'VVV";
               options.SubstituteApiVersionInUrl = true;
            });

        configuration.EnableSwagger(SwaggerDocsRoute, swagger =>
                {
                    swagger.MultipleApiVersions(
                    (apiDesc, version) =>
                    {
                    },
                info =>
                      {
                          foreach (var group in apiExplorer.ApiDescriptions)
                          {
                              info.Version(group.Name, $"Optimist 8 REST Integration Services {group.ApiVersion}");
                          }
                      });
                    swagger.PrettyPrint();
                    swagger.ResolveConflictingActions(apiDescriptions => apiDescriptions.First());
                    swagger.OperationFilter<AuthOperationFilter>();
                    swagger.OperationFilter(() => new AddHeaderParameter());
                    swagger.UseFullTypeNameInSchemaIds();
                }).EnableSwaggerUi(SwaggerUiRoute, swagger => swagger.EnableDiscoveryUrlSelector());

    }

Exception Detail:
System.NullReferenceException was unhandled by user code
HResult=-2147467261
Message=Object reference not set to an instance of an object.
Source=Microsoft.AspNet.OData.Versioning.ApiExplorer
StackTrace:
at Microsoft.Web.Http.Description.TypeExtensions.<>c__DisplayClass10_0.b__0(IEdmStructuredType t)
at System.Linq.Enumerable.FirstOrDefault[TSource](IEnumerable1 source, Func2 predicate)
at Microsoft.Web.Http.Description.TypeExtensions.GetStructuredType(Type type, IEdmModel model, IAssembliesResolver assembliesResolver)
at Microsoft.Web.Http.Description.TypeExtensions.SubstituteIfNecessary(Type type, IServiceProvider serviceProvider, IAssembliesResolver assembliesResolver, ModelTypeBuilder modelTypeBuilder)
at Microsoft.Web.Http.Description.ODataApiExplorer.CreateParameterDescriptionFromBinding(HttpParameterBinding parameterBinding, IServiceProvider serviceProvider, IAssembliesResolver assembliesResolver)
at Microsoft.Web.Http.Description.ODataApiExplorer.CreateParameterDescriptions(HttpActionDescriptor actionDescriptor, IHttpRoute route)
at Microsoft.Web.Http.Description.ODataApiExplorer.ExploreRouteActions(IHttpRoute route, HttpControllerDescriptor controllerDescriptor, IHttpActionSelector actionSelector, Collection1 apiDescriptions, ApiVersion apiVersion) at Microsoft.Web.Http.Description.ODataApiExplorer.ExploreRouteControllers(IDictionary2 controllerMappings, IHttpRoute route, ApiVersion apiVersion)
at Microsoft.Web.Http.Description.VersionedApiExplorer.InitializeApiDescriptions()
at System.Lazy1.CreateValue() at System.Lazy1.LazyInitValue()
at System.Lazy`1.get_Value()
at Microsoft.Web.Http.Description.VersionedApiExplorer.get_ApiDescriptions()

@commonsensesoftware
Copy link
Collaborator

Do you have a repro of this behavior that you can attach/upload/link to? There's clearly some other type of edge case that I'm not seeing. In addition, I notice that your predicate in MultipleApiVersions doesn't test or match anything. It should be testing whether the specified API description matches the specified API version.

@LuukN2
Copy link

LuukN2 commented Sep 13, 2018

I get the behaviour of issue 3 when I have a public property on a model that references a public nested class.

If I add this to a model for example:
` public FileConfiguration File { get; set; }

public class FileConfiguration
{

}`

Stacktrace:
[NullReferenceException: Object reference not set to an instance of an object.]
Microsoft.AspNet.OData.<>c__DisplayClass24_0.b__0(IEdmStructuredType t) +74
System.Linq.Enumerable.FirstOrDefault(IEnumerable1 source, Func2 predicate) +182
Microsoft.AspNet.OData.TypeExtensions.GetStructuredType(Type type, IEdmModel model, IEnumerable1 assemblies) +237 Microsoft.AspNet.OData.TypeExtensions.SubstituteIfNecessary(Type type, IServiceProvider serviceProvider, IEnumerable1 assemblies, ModelTypeBuilder modelTypeBuilder) +194
Microsoft.AspNet.OData.TypeExtensions.SubstituteIfNecessary(Type type, IServiceProvider serviceProvider, IAssembliesResolver assembliesResolver, ModelTypeBuilder modelTypeBuilder) +120
Microsoft.Web.Http.Description.ODataApiExplorer.CreateParameterDescriptionFromBinding(HttpParameterBinding parameterBinding, IServiceProvider serviceProvider, IAssembliesResolver assembliesResolver) +217
Microsoft.Web.Http.Description.ODataApiExplorer.CreateParameterDescriptions(HttpActionDescriptor actionDescriptor, IHttpRoute route) +379
Microsoft.Web.Http.Description.ODataApiExplorer.ExploreRouteActions(IHttpRoute route, HttpControllerDescriptor controllerDescriptor, IHttpActionSelector actionSelector, Collection1 apiDescriptions, ApiVersion apiVersion) +325 Microsoft.Web.Http.Description.ODataApiExplorer.ExploreRouteControllers(IDictionary2 controllerMappings, IHttpRoute route, ApiVersion apiVersion) +774
Microsoft.Web.Http.Description.VersionedApiExplorer.InitializeApiDescriptions() +731

@commonsensesoftware
Copy link
Collaborator

@LuukN2 your scenario might actually be a bug. I don't think I've tested nor have any related scenarios for complex models. That being said, it should be supported. I assume this complex type in your model that has variation by version?

The API explorer compares the model type provided against the EDM. As long as the definitions match, there is no substitution. A substitution occurs when they don't match, at which point the API explorer builds a new, dynamic type that looks like what the EDM says it should be for that version, but is a real type that Swagger can work with. This supplants the that need for you to create a model-per-version.

Assuming that this is a bug in your scenario, the workaround will be to create a version-specific model for Swagger. Lame - I know, but that will unblock you until the fix is out.

@commonsensesoftware
Copy link
Collaborator

@vanikulkarniAtFIS This thread seems to have gone dark. Either the issue was solved or another resolution was found.

@LuukN2, I'm tracking the substitution issue as #358. I'm not 100% sure if that's your problem. If you have a complex model, then that is the culprit. Feel free to post any additional information and/or a repro on that issue. Thanks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants