What is the expected project type and project layout in a visual studio solution for a typical Radzen application

From the Radzen app, an associate has added to an existing solution an Asp.net core 2.2 project, and two web site projects, one each for client and meta.

This doesn't seem very visual studio friendly because web site projects wont actually be compiled, and arent really even recognized as a first class project type, and I think is going to require a bunch of post build event scripts in Asp,Net core 2.2 project to run the steps listed on the Manual "Deploy" page (That is conflating the topics of build and deploy and creating its own confusion).

A solution to this would be to just add the client and meta folders as subfolders of the asp.net core 2.2 project, then we can use existing msbuild tasks or azure dev ops tasks without having to go out of bounds, and would get the benefit of having a single WebDeploy compatible package that can be deployed via the usual means.

Is this or something like it possible? Have we setup the solution and projects in some suboptimal way?

The structure of an Angular Radzen project can be seen in this screenshot:

Radzen doesn't use a Web Site - it uses a web application project and generates the corresponding csproj file.

The client and meta folders depicted in your screenshot are both web site projects. Or so says the icons.

Is there a reason why the client and meta cannot be child folders under the csproj? We are including this app in an existing solution and code branch. As this is really a single logical application that won't be developed for or deployed in the three separate parts, consolidation makes sense.

Web site projects have never really fit into the overall project and build systems, and come with a set of gotchas and complications, so avoiding that project type is kind of important.

Is there a reason why the client and meta cannot be child folders under the csproj?

The client and server directories are produced from the meta directory.

Web site projects have never really fit into the overall project and build systems, and come with a set of gotchas and complications, so avoiding that project type is kind of important.

Those are just two directories. Not sure why Visual Studio treats them as web sites but they are not.

If meta is an originator that only the Radzen app needs or uses, does it need to even be in the VS solution?

Can the client folder be included in the netcore project? Or the appropriate proj file type be created for it?

We are trying to get a less hacky feeling visual studio compile and azdevops build and release experience. Pre and post build actions defined on the netcore project that affect the client folder that is not part of the project or any other, but that is required to be part of the resulting deployable artifact, isn't a great solution

The client folder can't be included in the .net project at the moment. You can probably create a new VS solution that contains only the csproj file. We will probably exclude the meta and client directories from the application.sln file. There doesn't seem to be a good way to add a folder to a solution without VS considering it a "web site".

I'm not sure how adding another solution addresses the problem, but keeping a single solution that produces all release artifacts for a branch is really important, and there are existing projects in this branch that this program would depend on (db, services, etc).

Have you setup a build pipeline in azure dev ops that will produce a deployable artifact for the application? If so, sharing a description of that may clarify things for me. If not, then making that attempt may clarify the problem I'm having for you.

I'm not sure how adding another solution addresses the problem,

You said that having the meta and client directories in the solution causes a problem. Creating a new solution without those directories should solve the problem shouldn't it?

but keeping a single solution that produces all release artifacts for a branch is really important

The client directory is an Angular application based on the Angular CLI. Visual Studio cannot produce a production build of such projects as far as I know. Radzen uses the Angular CLI to do that. Also documented in our manual build procedure.

Have you setup a build pipeline in azure dev ops that will produce a deployable artifact for the application?

No. We haven't setup a build pipeline for azure dev ops and we are not familiar with the specifics. Probably the build instructions that I linked above would help.

The problem is not the presence of the client and meta folders. When included this way, they do not have the same tooling available as just about every other project type has. No pre or post build events, no automatic package manager support, no build or build configuration support (debug, release, etc). This would actually be worse if they were treated as just folders, because a web site project at least has a debug configuration (but only that).

The lack of automatic package manager support (mostly the ability to restore packages) means that a different project in the solution needs to be leveraged to execute the npm install command. I had set this up as a pre-build event for the netcore project.

There is also nothing that will trigger a build for the client code when its setup as web site project. VS is only going to try compiling c# or vb code it finds, and there is none. Also without a pre or post build event for this project, we would have to use a different project in this solution to initiate the ng build, so I setup a post build event on the netcore project to call this project's ng build. This works but means that every time someone compiles the solution they have to sit through npm determining if it
needs to run (and running) and ng cli's building of the project, even if that project didn't change.

The reason that I am asking about moving the client folder is because VS has had an Asp.net core project template that includes an option for Angular for years. Here are screenshots for VS 2017 and VS 2019

This is what the project structure/files looks like in VS 2019, with some nodes expanded.

We want to use Radzen because it would save us time for some things. Requiring us to have an entirely different set of development and build processes just for this one application is not saving time. Please have a look at the project templates above and LMK what can be done to accommodate.

I am afraid moving the client directory to the server is a substantial change in the way Radzen currently works. We cannot do that in the foreseeable future without introducing a lot of breaking changes.

The Visual Studio template you are showing relies on the so called SPA services.
Those project templates rely on npm install too. There is just no other way to build an Angular application. Here is an excerpt from the csproj file of such a project:

 <Target Name="DebugEnsureNodeEnv" BeforeTargets="Build" Condition=" '$(Configuration)' == 'Debug' And !Exists('$(SpaRoot)node_modules') ">
    <Exec Command="node --version" ContinueOnError="true">
      <Output TaskParameter="ExitCode" PropertyName="ErrorCode" />
    </Exec>
    <Exec WorkingDirectory="$(SpaRoot)" Command="npm install" />
    <Error Condition="'$(ErrorCode)' != '0'" Text="Node.js is required to build and run this project. To continue, please install Node.js from https://nodejs.org/, and then restart your command prompt or IDE." />
    <Message Importance="high" Text="Restoring dependencies using 'npm'. This may take several minutes..." />
  </Target>

By the way Radzen uses the SPA services too in development. Maybe it is somehow possible to make a production Angular build from Visual Studio. We haven't found a way to do that though.

I may have found a solution for you. Try adding the following to your csproj:

  <Target Name="PublishRunWebpack" AfterTargets="ComputeFilesToPublish">
    <!-- As part of publishing, ensure the JS resources are freshly built in production mode -->
    <Exec WorkingDirectory="$(SpaRoot)" Command="npm install" />
    <Exec WorkingDirectory="$(SpaRoot)" Command="npm run build -- --prod" />

    <!-- Include the newly-built files in the publish output -->
    <ItemGroup>
      <DistFiles Include="$(SpaRoot)dist\**" />
      <ResolvedFileToPublish Include="@(DistFiles->'%(FullPath)')" Exclude="@(ResolvedFileToPublish)">
        <RelativePath>wwwroot\%(DistFiles.RecursiveDir)%(DistFiles.Filename)%(DistFiles.Extension)</RelativePath>
        <CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
      </ResolvedFileToPublish>
    </ItemGroup>
  </Target>

On 'publish' it should build the client directory in production and copy the client\dist folder to wwwroot. I tested it by running dotnet publish -c Release which should be what a production build would use.

1 Like

Both local development and the build systems use msbuild or VS build and not dotnet as there are other projects in the branch and solution that are shipped at the same time as this application (its a data admin module) and the latter isn't able to compile netfx. The build systems do use the usual "Release" build configuration with optimizations, etc. and do produce the published web app artifact in a webdeploy zip file, its just missing the "client" folder.

This should address that. We will incorporate this code (or similar) and let you know the result. Thanks!

@korchev - we believe this does work. We are having a few followup problems with getting the build to be repeatable, but for this part it seems to be correct now. Thank You