Skip to content
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

.NET 6 support (DateOnly/TimeOnly) #3576

Closed
stephtr opened this issue Aug 1, 2021 · 11 comments
Closed

.NET 6 support (DateOnly/TimeOnly) #3576

stephtr opened this issue Aug 1, 2021 · 11 comments

Comments

@stephtr
Copy link

stephtr commented Aug 1, 2021

Hi,

What is the current plan for .NET 6 (preview) support? Currently NSwag fails when using for example the new DateOnly type.

@GrahamTheCoder
Copy link

GrahamTheCoder commented Aug 3, 2021

Sounds like you're better off than me. Just running with the VS2022 preview installed breaks my previously working nswag process looking for Microsoft.AspNetCore.Authentication, Version=5.0.0.0

Stack Trace System.IO.FileNotFoundException: Could not load file or assembly 'Microsoft.AspNetCore.Authentication, Version=5.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60' or one of its dependencies. The system cannot find the file specified. File name: 'Microsoft.AspNetCore.Authentication, Version=5.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60'
Server stack trace:
   at System.Reflection.RuntimeAssembly.GetExportedTypes(RuntimeAssembly assembly, ObjectHandleOnStack retTypes)
   at System.Reflection.RuntimeAssembly.GetExportedTypes()
   at System.Linq.Enumerable.<SelectManyIterator>d__17`2.MoveNext()
   at System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext()
   at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
   at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
   at NSwag.Commands.Generation.WebApi.WebApiToSwaggerCommand.<GetControllerTypesAsync>d__26.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at NSwag.Commands.Generation.WebApi.WebApiToSwaggerCommand.<RunIsolatedAsync>d__24.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at NSwag.Commands.IsolatedCommandBase`1.IsolatedCommandAssemblyLoader`1.Run(String commandType, String commandData, String[] assemblyPaths, String[] referencePaths)
   at System.Runtime.Remoting.Messaging.StackBuilderSink._PrivateProcessMessage(IntPtr md, Object[] args, Object server, Object[]& outArgs)
   at System.Runtime.Remoting.Messaging.StackBuilderSink.SyncProcessMessage(IMessage msg)

Exception rethrown at [0]:
   at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
   at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
   at NSwag.Commands.IsolatedCommandBase`1.IsolatedCommandAssemblyLoader`1.Run(String commandType, String commandData, String[] assemblyPaths, String[] referencePaths)
   at NSwag.Commands.IsolatedCommandBase`1.<>c__DisplayClass17_0.<RunIsolatedAsync>b__0()
   at System.Threading.Tasks.Task`1.InnerInvoke()
   at System.Threading.Tasks.Task.Execute()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at NSwag.Commands.IsolatedCommandBase`1.<RunIsolatedAsync>d__17.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at NSwag.Commands.IsolatedSwaggerOutputCommandBase`1.<RunAsync>d__13.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at NSwag.Commands.NSwagDocumentBase.<GenerateSwaggerDocumentAsync>d__41.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at NSwag.Commands.NSwagDocument.<ExecuteAsync>d__8.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at NSwag.Commands.Document.ExecuteDocumentCommand.<ExecuteDocumentAsync>d__9.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at NSwag.Commands.Document.ExecuteDocumentCommand.<RunAsync>d__8.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at NConsole.CommandLineProcessor.<ProcessSingleAsync>d__12.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at NConsole.CommandLineProcessor.<ProcessAsync>d__11.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at NConsole.CommandLineProcessor.Process(String[] args, Object input)
   at NSwag.Commands.NSwagCommandProcessor.Process(String[] args)

WRN: Assembly binding logging is turned OFF.
To enable assembly bind failure logging, set the registry value [HKLM\Software\Microsoft\Fusion!EnableLog] (DWORD) to 1.
Note: There is some performance penalty associated with assembly bind failure logging.
To turn this feature off, remove the registry value [HKLM\Software\Microsoft\Fusion!EnableLog].
NSwag command line tool for .NET 4.6.1+ WinX64, toolchain v13.8.2.0 (NJsonSchema v10.2.1.0 (Newtonsoft.Json v11.0.0.0))
Visit http://NSwag.org for more information.
NSwag bin directory: C:\Program Files (x86)\Rico Suter\NSwagStudio\Win

Executing file './GeneratePublicApiOpenApi3Spec.nswag.json' with variables ''...
System.IO.FileNotFoundException: Could not load file or assembly 'Microsoft.AspNetCore.Authentication, Version=5.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60' or one of its dependencies. The system cannot find the file specified.
File name: 'Microsoft.AspNetCore.Authentication, Version=5.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60'

Server stack trace:
   at System.Reflection.RuntimeAssembly.GetExportedTypes(RuntimeAssembly assembly, ObjectHandleOnStack retTypes)
   at System.Reflection.RuntimeAssembly.GetExportedTypes()
   at System.Linq.Enumerable.<SelectManyIterator>d__17`2.MoveNext()
   at System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext()
   at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
   at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
   at NSwag.Commands.Generation.WebApi.WebApiToSwaggerCommand.<GetControllerTypesAsync>d__26.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at NSwag.Commands.Generation.WebApi.WebApiToSwaggerCommand.<RunIsolatedAsync>d__24.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at NSwag.Commands.IsolatedCommandBase`1.IsolatedCommandAssemblyLoader`1.Run(String commandType, String commandData, String[] assemblyPaths, String[] referencePaths)
   at System.Runtime.Remoting.Messaging.StackBuilderSink._PrivateProcessMessage(IntPtr md, Object[] args, Object server, Object[]& outArgs)
   at System.Runtime.Remoting.Messaging.StackBuilderSink.SyncProcessMessage(IMessage msg)

Exception rethrown at [0]:
   at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
   at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
   at NSwag.Commands.IsolatedCommandBase`1.IsolatedCommandAssemblyLoader`1.Run(String commandType, String commandData, String[] assemblyPaths, String[] referencePaths)
   at NSwag.Commands.IsolatedCommandBase`1.<>c__DisplayClass17_0.<RunIsolatedAsync>b__0()
   at System.Threading.Tasks.Task`1.InnerInvoke()
   at System.Threading.Tasks.Task.Execute()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at NSwag.Commands.IsolatedCommandBase`1.<RunIsolatedAsync>d__17.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at NSwag.Commands.IsolatedSwaggerOutputCommandBase`1.<RunAsync>d__13.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at NSwag.Commands.NSwagDocumentBase.<GenerateSwaggerDocumentAsync>d__41.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at NSwag.Commands.NSwagDocument.<ExecuteAsync>d__8.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at NSwag.Commands.Document.ExecuteDocumentCommand.<ExecuteDocumentAsync>d__9.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at NSwag.Commands.Document.ExecuteDocumentCommand.<RunAsync>d__8.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at NConsole.CommandLineProcessor.<ProcessSingleAsync>d__12.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at NConsole.CommandLineProcessor.<ProcessAsync>d__11.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at NConsole.CommandLineProcessor.Process(String[] args, Object input)
   at NSwag.Commands.NSwagCommandProcessor.Process(String[] args)

I figured basically everyone would hit this, but since you clearly didn't, it's probably worth mentioning here 😄

@RicoSuter
Copy link
Owner

@GrahamTheCoder You should not use WebApiToSwaggerCommand but AspNetCoreToSwaggerCommand because the WebApi one is reflection only and should only be used for legacy (ie asp.net mvc) apps.

@RicoSuter
Copy link
Owner

RicoSuter commented Aug 4, 2021

@stephtr if this is only about missing type support (like DateOnly) we can already add support for this (in NJsonSchema). Currently I'm a bit hesitant to already add new target frameworks for .NET 6 yet (ie for the CLI etc) - however referencing NSwag as nuget package (NSwag.AspNetCore) should work in general...

Right now you could add a custom primitive type mapper for e.g. DateOnly and map it to type "string" and format "date"

RicoSuter added a commit to RicoSuter/NJsonSchema that referenced this issue Aug 5, 2021
@RicoSuter
Copy link
Owner

RicoSuter commented Aug 5, 2021

  • Add support for DateOnly and TimeOnly, will be in NSwag v13.13.1 (NJsonSchema v10.5.1)

@stephtr stephtr changed the title .NET 6 support .NET 6 support (DateOnly/TimeOnly) Aug 6, 2021
@stephtr
Copy link
Author

stephtr commented Aug 6, 2021

Thanks, that's perfect! Since currently I can't think of any other .NET 6 only features, I'll close the issue.

@stephtr stephtr closed this as completed Aug 6, 2021
@Itori
Copy link

Itori commented Dec 9, 2021

Works fine if the DateOnly is in the results, but if used as an action parameters, DateOnly appears as a Complex Type and not a string with date format.

public async Task<ActionResult<AgendaDto>> GetAgendaAgent([FromQuery]DateOnly dateDebut, [FromQuery]DateOnly dateFin, [FromQuery]string cp, CancellationToken cancellationToken = default)

image

Edit: It's normal for nswag, as the dotnet team doesn't fully support it.
See dotnet/runtime#59118 for Workaround

@RicoSuter
Copy link
Owner

RicoSuter commented Dec 9, 2021

@Itori I wonder why that is, the type DateOnly should be resolved the same way and it should end up with a string property... or is it reported as multiple properties/params automatically by API explorer?

@Itori
Copy link

Itori commented Dec 9, 2021

Not sure exactly but it's not simply a problem of exposure, as if I query with a string, I got an exception.
The default serializer expect it to be a complex type.

Find this issue planing support for .Net 7 : dotnet/aspnetcore#34591

@Havunen
Copy link
Contributor

Havunen commented May 20, 2022

This fixes DateOnly model properties serialization, but I'm wondering how fix the parameters too...

            settings.TypeMappers.Add(new PrimitiveTypeMapper(typeof(DateOnly), schema =>
                {
                    schema.Format = "date";
                    schema.Type = JsonObjectType.String;
                }
            ));

@taspeotis
Copy link

@Havunen This worked for me for query parameters:

options.MapType<DateOnly>(() => new OpenApiSchema {Format = "date", Type = "string"});
options.MapType<TimeOnly>(() => new OpenApiSchema {Format = "time", Type = "string"});

options coming from services.AddSwaggerGen(options => ....

@harvzor
Copy link

harvzor commented Jan 23, 2024

@Havunen This worked for me for query parameters:

options.MapType<DateOnly>(() => new OpenApiSchema {Format = "date", Type = "string"});
options.MapType<TimeOnly>(() => new OpenApiSchema {Format = "time", Type = "string"});

options coming from services.AddSwaggerGen(options => ....

Pretty sure this thread is about NSwag, not Swashbuckle, and you're confusing matters by referencing a method from Swashbuckle:

https://github.com/domaindrivendev/Swashbuckle.AspNetCore/blob/8f363f7359cb1cb8fa5de5195ec6d97aefaa16b3/src/Swashbuckle.AspNetCore.SwaggerGen/DependencyInjection/SwaggerGenServiceCollectionExtensions.cs#L14

Meanwhile I'm still struggling to figure out where settings.TypeMappers comes from in NSwag.

Found it:

services.AddOpenApiDocument(configure =>
{
    configure.SchemaSettings.TypeMappers.Add(...);
});

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

No branches or pull requests

7 participants