RicoSuter / NSwag

The Swagger/OpenAPI toolchain for .NET, ASP.NET Core and TypeScript.
http://NSwag.org
MIT License
6.7k stars 1.24k forks source link

Building project does not copy files to bin/debug/Win #2988

Open kendallb opened 4 years ago

kendallb commented 4 years ago

Looks like the files in this directory get put there by the installer project, but they are required when the studio program is being run in debug mode. Took me a long time to finally work out that my changes to the code were not working because the studio program calls the command line tool to actually run the client generation, and the command line tool was not being copied to the bin/debug/Win directory.

So I simply moved over to debugging the command line tool, but tried again to figure this out with a full clean. Seems like the only way I could get it copy there was to nuke the Win directory and then build the installer project (which I have moved to leaving unloaded since it takes so long).

Anyway this threw me for a loop, so I would suggest that the code should do either:

1) Remove the reliance on the command line tool to perform the action and simply build the generation logic right into the NSwagStudio front end tool? This would help also with lots of popup windows being left behind from the all console runs when you are testing a spec :)

2) Have the studio program run the version of the tool in the ......\NSwag.Console\bin\Debug\net461 directory so that it will be running the version you just applied the changes to.

jeremyVignelles commented 4 years ago

I didn't understand what you mean, which files are missings?

Could you please send a minimal repro project so that we can see what you mean? The NSwag configuration is complex, and I don't know which settings you chose.

kendallb commented 4 years ago

Well as I explained in the original post, the problem is when you run NSwagStudio, to generate the client it calls the console NSwag.Console program to actually generate the clients. This lives in the bin/Win sub-directory. So when you first build the app in debug mode, it will happily build and generate everything and it works. The problem is if you change anything related to the generation of the client code, which ends up in NSwag.Console, doing a build in debug mode will not copy updated binaries into the bin/Win directory. So if you run NSwagStudio, it will be running old code, not the code you just changed. This took me a long time to figure out why my changes were having no effect.

As it turns out as as I pointed out above, the project that actually copies the files over to the bin/Win directory is the Wix installer project. So if you have that unloaded, nothing ever gets copied. To reproduce it, simply do the following:

  1. Unload the Wix installer project in Visual Studio
  2. Go to the src\NSwagStudio\bin\Release\Win directory and nuke all the files in there
  3. Do a full rebuild
  4. Run NSwagStudio and try to generate a client. It will crash, as the console code is missing.

So as I suggested I think we should really remove the reliance on calling the console app completely from NSwagStudio and simply link to the DLL's and run it within NSwagStudio directly. If you look at the implementation of NSwag.Console it's very simply. Just sets up the command to run and runs it.

I would be happy to implement this and create a PR if people agree it's a worthwhile change.

jeremyVignelles commented 4 years ago

You didn't specify if you're running in the assembly mode or in the csproj mode. Both work differently. The fact that the build process doesn't copy the files is more a MSBuild issue than a NSwag one, isn't it?

Are you using a .net framework project or a .net core one ? SDK-style or legacy csproj ? A minimal repro project would help understanding your issue.

As for the command line invocation, I think that this is by design : Your NswagStudio is running with a given framework version, which might be different from your app framework version. When it loads the assemblies, the version must match, and that's why there are several command line applications under NSwagStudio.

kendallb commented 4 years ago

Not sure what you mean about assembly mode vs csproj mode? I am building in Visual Studio 2019 (which uses their internal msbuild tooling), but I also build with Rider most of the time which uses Resharper build. Just load the solution in VS2019, and build it in debug mode. My assumption is it's running it as a regular .net app since it's a WPF application, not .net core.

My point is it makes debugging much more complicated. Sure, I get that the console app can be built in multiple different target configurations so the studio tool can call any of them regardless of how it is built, but my point is if you are using the studio app and not specifically the command line, having the studio program call the console code to generate the client, or simply running it in place inside the main program makes no real difference to the user. The only difference would be a small increase in code size, but not much since it would just be loading the assemblies that are likely already in the bin directory anyway?

If nobody wants to change it, that's fine. But my point is it really confused me a while to finally work out that the GUI app was calling the console command line and hence made debugging a lot harder. Makes the barrier to entry for anyone else to come along and work on the project a lot higher.

jeremyVignelles commented 4 years ago

If NSwagStudio builds the project, you should be able to generate a client without any issue. If it doesn't copy the required files, then there must be something wrong in some configuration or a bug in NSwag. It's just unclear for me what you're trying to do and what didn't work.

RicoSuter commented 4 years ago

It would be really great if we could improve that somehow.. its really hard to work with that. Does anyone have time for this? Ideally it should not depend on the installer project.

jeremyVignelles commented 4 years ago

OK, after a good night sleep, I finally understood what this is all about:

Your issue is : I cannot open the NSwag solution, build the NSwagStudio project and run it, because NSwagStudio requires some files that are not copied by MSBuild.

I might have a look at this but this should be doable to trigger a NSwag.Console build task, and copy the output files BeforeBuild, but this requires tweaking the csproj file. I've done that before at work for a project that has some plugins so I have some sample code.

kendallb commented 4 years ago

I think the correct solution to fixing this is to remove the dependency on calling the console app from the GUI app, and just have the code linked in. More than happy to do that if it's desired as it won't be much work. The installer can still copy the files there as it may be needed for the final installer to include everything but I can't see any reason to not link the code directly to make debugging easier.

jeremyVignelles commented 4 years ago

I don't think you can do that due to the framework mismatch and the way assemblies are loaded, but @RicoSuter will likely give us the right answer.

kendallb commented 4 years ago

Yeah it's buried in there pretty good. The UI app is always a .net 4.6.1 app at the moment, so there should be no binding issues. The main problem is it's all built around running the console apps. Once I worked out what the issue was I started debugging the actual console app rather than the UI app, but that's quite tedious when you are making both UI changes and then changes to the code generation code.

So without removing all the command line stuff based on MyToolkit, the next best step is to at least fix the build process so it does copy the resulting binaries over when the console app gets rebuilt. It would still be confusing if you put a breakpoint in the code generation and then wonder why it never gets tripped (which is what I ran into).

kendallb commented 4 years ago

Oh, it's a one line code change!

https://github.com/RicoSuter/NSwag/blob/master/src/NSwagStudio/ViewModels/DocumentViewModel.cs#L56

Right there it calls ExecuteCommandLineAsync(), which internally has this:

                if (Runtime == Runtime.Debug)
                {
                    return await ExecuteAsync();
                }

which just runs it async in process when this is set to debug mode (not sure exactly when or how this is set, but someone clearly ran across this before). The only change when I made it run in process is that it was generating against a different version of Json.net (probably just need to update dependencies in the studio project).

So the question is should it be changed to generate in process all the time, or perhaps just when someone is building in debug mode?

kendallb commented 4 years ago

Pull request here:

https://github.com/RicoSuter/NSwag/pull/3000

RicoSuter commented 3 years ago

I totally agree that the current build is not optimal and hard to work with. NSwag.Core.sln is clean, the rest (nswag.sln) needs to be reworked and simplified but that is a huge task (also considering we should not break anyone)