aspnet / Razor

[Archived] Parser and code generator for CSHTML files used in view pages for MVC web apps. Project moved to https://github.com/aspnet/AspNetCore
Apache License 2.0
883 stars 225 forks source link

Improve support for precompilation of razor views in class libraries (embedded ui) #1809

Closed mkArtakMSFT closed 6 years ago

mkArtakMSFT commented 6 years ago

From @evil-shrike on October 17, 2017 15:31

As continue of https://github.com/aspnet/MvcPrecompilation/issues/187

The problem: I need a class library with embedded UI. Currently it's hard implement such setup when a class library in a solution contains pre-compilable razor views. Lloading views from embedded resource is another option and it works fine.

At the end of the mentioned discussion (#187) there was posted a link to blog post about how to implement embedded UI - https://dzone.com/articles/self-contained-ui-running-one-aspnet-core-mvc-site It seems to work well. But looks hacky, too much cleaver things should be done in csproj. Another problem it's not documented in official docs.

So this issue is an suggestion to have more simplified approach for "embedded UI", i.e. keeping razor views in class libraries and automatically compile and deploy them.

Some nuances which should be elaborated:

Currently (aspnetcore2.0) we have to do the following (thanks to @dasMulli for describing it in this comment - https://github.com/aspnet/MVCPrecompilation/issues/71#issuecomment-282494937)

1.

        <MvcRazorCompileOnPublish>true</MvcRazorCompileOnPublish>
  1. <Target Name="SetMvcRazorOutputPath">
        <PropertyGroup>
            <MvcRazorOutputPath>$(OutputPath)</MvcRazorOutputPath>
        </PropertyGroup>
    </Target>
    <Target Name="_MvcRazorPrecompileOnBuild" DependsOnTargets="SetMvcRazorOutputPath;MvcRazorPrecompile" AfterTargets="Build" Condition=" '$(IsCrossTargetingBuild)' != 'true' " />
    <Target Name="IncludePrecompiledViewsInPublishOutput" DependsOnTargets="_MvcRazorPrecompileOnBuild" BeforeTargets="PrepareForPublish" Condition=" '$(IsCrossTargetingBuild)' != 'true' ">
        <ItemGroup>
            <_PrecompiledViewsOutput Include="$(MvcRazorOutputPath)$(MSBuildProjectName).PrecompiledViews.dll" />
            <_PrecompiledViewsOutput Include="$(MvcRazorOutputPath)$(MSBuildProjectName).PrecompiledViews.pdb" />
            <ContentWithTargetPath Include="@(_PrecompiledViewsOutput->'%(FullPath)')" RelativePath="%(_PrecompiledViewsOutput.Identity)" TargetPath="%(_PrecompiledViewsOutput.Filename)%(_PrecompiledViewsOutput.Extension)" CopyToPublishDirectory="PreserveNewest" />
        </ItemGroup>
    </Target>

Off the top of my head I'd suggest to introduce MvcRazorCompile=true.

Copied from original issue: aspnet/MvcPrecompilation#214

mkArtakMSFT commented 6 years ago

From @CGollhardt on October 24, 2017 1:41

I would propose, we have a PrecompileRazorViewsAndMerge property group element, which automaticly precompiles the Views on every Compilation and merge them with the output class library.

Not sure, how hard this would be to implement, but this would be very easy to use and document.

mkArtakMSFT commented 6 years ago

From @nfplee on November 1, 2017 9:59

I agree the class library shouldn't need to be "runnable". A simple class library like Orchard Core modules looks a lot cleaner.

I also think there should be a way to specify a view prefix e.g. "~/Areas/Blog". This way we can just have a Views directory within the root of the library.

mkArtakMSFT commented 6 years ago

From @IEvangelist on December 5, 2017 2:48

I agree with this and would like to further propose that the precompiled views be part of the build step. Currently they are only available from either the Visual Studio (MSBuild) publish command or the dotnet publish command. This is kind of a fundamental misuse of the publish command.

If I take a step back and imagine that I have zero experience or knowledge with how these commands would work I might describe them as follows:

It is my belief that by making the publish step responsible for compilation -- we are making things more complicated for DevOps and less flexible. I'm working on a fortune 500 company / enterprise project right now that has a need to have a web appliciation (that produces an .exe) be packed up and we need its *.PrecompiledViews.dll as well in the NuGet package.

The steps to make this happen in Team City are starting to look like insanity. Something like this right now:

  1. build
  2. publish to local folder
  3. copy *.PrecompiledViews.dll
  4. pack --no-build
  5. publish package to artifactory

I'd much rather go:

  1. build
  2. pack
  3. publish package to artifcatory
mkArtakMSFT commented 6 years ago

From @manigandham on December 5, 2017 3:10

@IEvangelist Agree strongly with this, that should be the default or with an easy flag to enable. Compilation is part of build, whether it's code or views and we've run into plenty of issues where devs check in code that builds but ends up with errors during publish.

alvipeo commented 6 years ago

I wonder is this resolves this issue - https://stackoverflow.com/q/47321379/2896495 ?

rynowak commented 6 years ago

Closing this as we've done all of the big rock work here. Docs currently in progress https://github.com/aspnet/Docs/pull/5790

evil-shrike commented 6 years ago

Hi. I'm trying to migrate my solution from 2.0 (see the first post) to the new 2.1 Razon SDK. But it's not easy. I have moved all views (Views folder) from a project "WebServer" into a project "WebServer.Views". That View-project is Razor sdk lib. It references "WebServer" and package Microsoft.AspNetCore.Mvc, that's all. But when I run build I'm getting two assemblies for View-project:

  WebServer.Views -> ..\Server.NetCore\WebServer.Views\bin\Debug\netcoreapp2.1\WebServer.View.dll
  WebServer.Views -> ..\Server.NetCore\WebServer.Views\bin\Debug\netcoreapp2.1\WebServer.Views.Views.dll

WebServer.View is the name of View-project's assembly:

  <PropertyGroup>
    <TargetFramework>netcoreapp2.1</TargetFramework>
    <AssemblyName>WebServer.View</AssemblyName>
    <RootNamespace>WebServer</RootNamespace>
  </PropertyGroup>

What can be a reason for this?

rynowak commented 6 years ago

Hi, it looks like you are posting on a closed issue/PR/commit!

We're very likely to lose track of your bug/feedback/question unless you:

  1. Open a new issue
  2. Explain very clearly what you need help with
  3. If you think you have found a bug, include detailed repro steps so that we can investigate the problem

Thanks!

evil-shrike commented 6 years ago

here's the bug #2396