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

[aspnetcore]: Preliminary support for ASP.NET 3.0 Core preview 5 #2824

Merged
merged 11 commits into from
Jun 25, 2019

Conversation

A-Joshi
Copy link
Contributor

@A-Joshi A-Joshi commented May 5, 2019

PR checklist

  • Read the contribution guidelines.
  • Ran the shell script under ./bin/ to update Petstore sample so that CIs can verify the change. (For instance, only need to run ./bin/{LANG}-petstore.sh, ./bin/openapi3/{LANG}-petstore.sh if updating the {LANG} (e.g. php, ruby, python, etc) code generator or {LANG} client's mustache templates). Windows batch files can be found in .\bin\windows\. If contributing template-only or documentation-only changes which will change sample output, be sure to build the project first.
  • Filed the PR against the correct branch: master, 3.4.x, 4.0.x. Default: master.
  • Copied the technical committee to review the pull request if your PR is targeting a particular programming language.

Description of the PR

Preliminary support for ASP.NET Core 3.0 (preview 4). See issue #2350

No support for the new style routing or new Json library (still uses Newtonsoft).

@A-Joshi A-Joshi changed the title Feature/version3 [aspnetcore]: Preliminary support for ASP.NET 3.0 preview 4 May 5, 2019
@etherealjoy
Copy link
Contributor

I thought the signature got changed here

public void Configure(IApplicationBuilder app,  IWebHostEnvironment env)

@etherealjoy
Copy link
Contributor

Does it makes sense to use static files when swashbuckle is not used? In pure WebApi scenarios?

@etherealjoy etherealjoy changed the title [aspnetcore]: Preliminary support for ASP.NET 3.0 preview 4 [aspnetcore]: Preliminary support for ASP.NET 3.0 Core preview 4 May 5, 2019
@A-Joshi
Copy link
Contributor Author

A-Joshi commented May 5, 2019

I thought the signature got changed here

public void Configure(IApplicationBuilder app,  IWebHostEnvironment env)

Yes - but the old style is still available with a deprecation warning:
"Startup.cs(67,56): warning CS0618: 'IHostingEnvironment' is obsolete: 'This type is obsolete and will be removed in a future version. The recommended alternative is Microsoft.AspNetCore.Hosting.IWebHostEnvironment.' [/Src/contract-first/contracts/aspnetcore-server-task-async/target/contracts/src/Contracts/Contracts.csproj]"

There are a couple more such warnings that will have to be cleaned up (aside from support for new routing and json libraries) before it is fully ready.

@etherealjoy
Copy link
Contributor

etherealjoy commented May 5, 2019

@ALL
If it breaks current 2.2 version does not it make sense then to use a different version instead for the 3.0?
This would make it easier to maintain and also use the new features that come with the 3.0 version

@A-Joshi
Copy link
Contributor Author

A-Joshi commented May 5, 2019

@ALL
If it breaks current 2.2 version does not it make sense then to use a different version instead for the 3.0?
This would make it easier to maintain and also use the new features that come with the 3.0 version

Does not break 2.2 - did not want to send the PR till the break was fixed.

@jimschubert
Copy link
Member

jimschubert commented May 5, 2019

edit: n/m. I read the issue before looking at the PR.

Copy link
Member

@jimschubert jimschubert left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for this PR. It's looking pretty good. I think the biggest issue is that newtonsoft is still referenced, although it's possible to exclude the library. I had a handful of other logic or user (of the generator) clarifications.

docs/generators/aspnetcore.md Outdated Show resolved Hide resolved
@@ -60,18 +64,22 @@
private boolean useSwashbuckle = true;
protected int serverPort = 8080;
protected String serverHost = "0.0.0.0";
protected CliOption aspnetCoreVersion = new CliOption(ASPNET_CORE_VERSION, "ASP.NET Core version: 2.2 (default), 2.1, 2.0 (deprecated)");
protected CliOption swashbuckleVersion = new CliOption(SWASHBUCKLE_VERSION, "Swashbucke version: 3.0.0 (default), 4.0.0");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should remove default version definition from being embedded in the help text. This will already be displayed via config-help:

	swashbuckleVersion
	    Swashbucke version: 3.0.0 (default), 4.0.0 (Default: 3.0.0)


private void setIsFramework() {
if (aspnetCoreVersion.getOptValue().startsWith("3.")) {
// default, do nothing
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this block is setting a field and has a side effect of assigning a key/value in additionalProperties. Saying "do nothing" could be confusing. Similarly, "3.x" isn't the default defined in this type and could be confusing. Should probably remove comment since the log message below provides runtime and in-code explanation.

private void setUseNewtonsoft() {
if (aspnetCoreVersion.getOptValue().startsWith("2.")) {
LOGGER.warn("ASP.NET core version is " + aspnetCoreVersion.getOptValue() + " so staying on default json library.");
useNewtonsoft = false;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel like there's either a typo here or on the conditional a couple lines above. Is it intentional to disallow JSON.net in aspnetcore 2.x? If so, this may be considered a breaking change and should probably be done separately from this PR to generate discussion.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The change is not a breaking change:

This one is a little tricky - the MVC configuration in 2.x and 3.x use AddJsonOptions but mean different things: the default JSON in 2.x is implicitly Newtonsoft, while in 3.x and later it will be the Microsoft one.

I can change it use something like useDefaultJson or jsonLibrary. I don't like the former since the default in different cases means different things. Maybe explicitly defining the jsonLibrary as Newtonsoft or Microsoft but that makes the mustache file complex - since mustache does not have conditionals based on values.

What are your thoughts there?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My main concern is that for 2.x, when useNewtonSoft is false, this results in the NewtonSoft library not being referenced, but is still used on controllers and models. From a maintainability perspective (both built-in templates and custom user templates), I find that very confusing.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For 2.x NewtonSoft is used by the framework by default itself because it is part of the fw, but MS removed it from the framework starting from 3.x and manual addition of package is needed.
Which in this case the user really has no choice to not use NewtonSoft in 2.x
Since we would need to use NewtonSoft for model compatibility reasons it does not makes sense to allow the user to set this flag because if the fw is > 3.x we will need to add it

}

private void setSwashbuckleVersion() {
setCliOption(swashbuckleVersion);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Long comment, but minor (can be addressed later).

Only the CLI should be setting CLI options. We should read options once (in processOpts), then have nothing to do with CLIOption types. That is, we should load into fields and work from those fields directly. I'm concerned that making this method side-effecting as it is and assuming options parsing within the generator, things can become out of sync.

For example, a user can pass --additional-properties=swashbuckleVersion=3.0.5". Although this isn't defined in the enum of available versions, this is a valid use case that we allow for properties defined in additionalProperties; this is why you often see the guard that we only set the value if it doesn't already exist. CodegenConfiguratoralso allows for JSON deserialization into theCodegenConfigurator` type (to load these values from a config), which sorta bypasses both the cli options and additional properties (see CodegenConfigurator).

In all of these cases, this method will reset the user-provided value to whatever is originally hardcoded as the swashbuckleVersion default within the generator.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The other choice here is to check the version of Swashbuckle is valid for the ASP.NET Core chosen and throw an error if the version is not valid.

In this particular case I think you can use v 4.0.0 with version 2.x and 3.x but you cannot use v3.0.0 with 3.x and later.

What are you thoughts here - error or warn and correct - not sure what the general policy for this is.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think my preference would be to set a default if one doesn't exist, and warn if it's something we don't expect will work. We'll probably want to be clear that anything below 4.0.0 may not work, but trust that the user understands the versioning. For example, someone might have a fork of Swashbuckle which does work, and they could reference and add the file with the reference to .openapi-generator-ignore. In that case, a warn+correct would be unexpected if the value was explicitly provided.

{{#compatibilityVersion}}
.SetCompatibilityVersion(CompatibilityVersion.{{compatibilityVersion}})
{{/compatibilityVersion}}
.AddJsonOptions(opts =>
.{{#useNewtonsoft}}AddNewtonsoftJson{{/useNewtonsoft}}{{^useNewtonsoft}}AddJsonOptions{{/useNewtonsoft}}(opts =>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Variable useNewtonsoft will also need to be evaluated in controller.mustache and model.mustache. Currently, the artifact won't be loaded, but controllers and models are still tightly coupled to json serialize/deserialize using the library.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

see the earlier comment about setting the value of useNewtonsoft.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure I follow.

To put the concern a different way, as a user if I set useNewtonSoft=false, and the controller/model generation still includes NewtonSoft imports, I'd consider that a bug. Maybe the variable name is what's misleading here.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed, since the models are generated with Netwonsoft in mind it is required that in 3.x it is included via the package dependency and for 2.x is there as part of core fw.

…licitly clear. Also fix small messages for the review comments
@A-Joshi
Copy link
Contributor Author

A-Joshi commented May 5, 2019

I am beginning to think that instead of automatically correcting the value if invalid, then just throw an error. It will simplify some of the logic.

The PR does not address supporting the new features of 3.0 - it simply ensure that you can use 3.0 in a backward compatible way.

Thoughts?

@etherealjoy
Copy link
Contributor

The PR does not address supporting the new features of 3.0 - it simply ensure that you can use 3.0 in a backward compatible way.

Here is what I also would like to hear the opinion. Because if we use the new features of 3.0 we will have to use a new template otherwise maintaining backwards compatibility will be too much.
Besides it also make contribution from more people easier to manage due to lesser chance of breaking 2.x

@wing328
Copy link
Member

wing328 commented May 15, 2019

What about merging this PR into master and then ask the community for feedback?

@etherealjoy
Copy link
Contributor

This is not going to work yet. Routing changes are missing.
I think we can stick with JSON.NET instead of Utf8JsonReader/Writer. Utf8JsonReader is still lacking many features.
Additionally I believe ASP.NET Core 3.0 brings so many new things that it makes more sense to have it as a separate generator. e.g use ControllerWithView and Razor at the same time instead of Swashbucke with Mvc in the past.

@etherealjoy
Copy link
Contributor

@wing328 @A-Joshi
I would like to give to give feedback after 3 weeks of using ASP.NET Core 3.0 Preview 5.

  • Utf8JsonReader is not feature complete so we are better off for now using JSON.NET
  • API Controllers and Controller with views use the Utf8JsonReader so incompatibility with net core client models. So we should continue to use ASP.NetCore MVC package
  • We can add Razor to to MVC so not an issue there.
  • We can continue to use the same generator because the diff from here mainly is the Configure.

New changes needed

  • In Configure, endpoint routing has to be activated
  • JSON.NET has to be added a an external dependency in .csproj
  • JSON camel case NamingStartegy has to use instead of deprecated option.
  • docker alpine runtime is available
  • rest is same :)

@A-Joshi
Copy link
Contributor Author

A-Joshi commented Jun 4, 2019 via email

@A-Joshi
Copy link
Contributor Author

A-Joshi commented Jun 5, 2019

Could you give sample of what the changes you needed to do were?

@wing328 @A-Joshi
New changes needed

* In `Configure`, endpoint routing has to be activated

What did you have to change? parameter value to be set?

* `JSON.NET` has to be added a an external dependency in `.csproj`

What was the dependency you needed to add? I think its already there.

* JSON camel case NamingStartegy has to use instead of deprecated option.

Not sure what the change needed was?

* docker alpine runtime is available

Can look at this for the next round.

* rest is same :)

Can we get the PR added in ? It does not break 2.x and it will be easier to work against the master once this is merged in.

@etherealjoy
Copy link
Contributor

I did these

In Configure, endpoint routing has to be activated

In Configure, shown here without swashbuckle

public void Configure(IApplicationBuilder app,  IWebHostEnvironment env)
{
	app.UseHttpsRedirection();
	app.UseRouting();
	app.UseEndpoints(endpoints =>
	{
		endpoints.MapControllers();
	});	
	if (env.IsDevelopment())
	{
		app.UseDeveloperExceptionPage();
	}
	else
	{
		app.UseHsts();
	}
}

JSON.NET has to be added a an external dependency in .csproj

In .csproj file

<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" 
          Version="3.0.0-preview5-19227-01" />

JSON camel case NamingStrategy has to use instead of deprecated option.

using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Serialization;


public void ConfigureServices(IServiceCollection services)
{
	// Add framework services.
	services
		.AddMvc()
		.SetCompatibilityVersion(CompatibilityVersion.Version_3_0)
		.AddNewtonsoftJson(opts =>
			{
				opts.SerializerSettings.ContractResolver = 
						new CamelCasePropertyNamesContractResolver();
				opts.SerializerSettings.Converters.Add(new StringEnumConverter
				{
					NamingStrategy = new CamelCaseNamingStrategy()
				});
			}
		);

}

docker alpine runtime is available

In Dockerfile
FROM mcr.microsoft.com/dotnet/core/aspnet:3.0-alpine AS runtime

@A-Joshi
Copy link
Contributor Author

A-Joshi commented Jun 6, 2019

@etherealjoy:
Added the parts you found above except the docker image - have to give it a little thought whether we should make the whole base docker image name configurable or pass in the parameter like alpine.

Can you test the new push please?

@wing328, @jimschubert - Assuming @etherealjoy is good then I suggest we merge it in - there are no changes for the version 2.1/2.2 while this will add preliminary support for 3.0 preview 5 in compatibility mode.

@etherealjoy
Copy link
Contributor

etherealjoy commented Jun 6, 2019

I will try this out and give feedback.
And thank you for the updates :)

@A-Joshi A-Joshi changed the title [aspnetcore]: Preliminary support for ASP.NET 3.0 Core preview 4 [aspnetcore]: Preliminary support for ASP.NET 3.0 Core preview 5 Jun 6, 2019
@jimschubert
Copy link
Member

Regarding the recommendation of having 3.0 be a separate generator…

Rather than conditionally assigning locations for files between versions (e.g. 2.2/filename.mustache and 3.0/filename.mustache), why not just use the core generation's library feature? These are different versions of the same library, but there's no reason we can't use that option to reference library versions. This allows us to put common code under resources/aspnetcore and any version-specific overrides under their respective library folders. This would be a breaking change for anyone who has extended templates, so such a change would have to be done in release 4.1.0. This is just a thought about managing the concern of maintainability as Microsoft makes breaking changes between versions. I think it would be much easier to manage these as libraries rather than completely separate generators.

@A-Joshi
Copy link
Contributor Author

A-Joshi commented Jun 7, 2019 via email

@etherealjoy
Copy link
Contributor

etherealjoy commented Jun 8, 2019

I tried this and it works using these options.

java -jar modules/openapi-generator-cli/target/openapi-generator-cli.jar generate -i \ 
/home/dev/api/swagger.yaml -o /home/dev/gen --additional-properties  \
aspnetCoreVersion=3.0,useNewtonsoft=true,useDefaultRoutng=false,useSwashbuckle=false \ 
-g aspnetcore

However SwashBuckle on .Net Core 3.0 needs version 5.0.
domaindrivendev/Swashbuckle.AspNetCore#1088
So Swashbuckle needs an update for .Net Core 3.0
#2646

@A-Joshi
Copy link
Contributor Author

A-Joshi commented Jun 9, 2019

You can change the swashbuckle version using the parameter "swashbuckleVersion=4.0.0" I have added 5.0.0 as a possible value but have not tested with that.

@A-Joshi
Copy link
Contributor Author

A-Joshi commented Jun 18, 2019

@etherealjoy are you OK with it now?
@jimschubert @wing328 can we merge this one?

@etherealjoy
Copy link
Contributor

Ok from my side.

@etherealjoy
Copy link
Contributor

Update to swashbuckle 5 is needed to use it with 3.0 but we can do this later.

@wing328
Copy link
Member

wing328 commented Jun 25, 2019

Let's merge this and gather feedback from the community.

@wing328 wing328 merged commit 94c583b into OpenAPITools:master Jun 25, 2019
@wing328 wing328 added this to the 4.0.3 milestone Jun 25, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants