Skip to content

fix: resolve precompiled block views in Production runtime mode (#273)#315

Merged
rickbutterfield merged 3 commits into
v5/devfrom
v5/bugfix/273-precompiled-view-resolution
Jul 8, 2026
Merged

fix: resolve precompiled block views in Production runtime mode (#273)#315
rickbutterfield merged 3 commits into
v5/devfrom
v5/bugfix/273-precompiled-view-resolution

Conversation

@rickbutterfield

@rickbutterfield rickbutterfield commented Jul 6, 2026

Copy link
Copy Markdown
Owner

Summary

Fixes #273. Block previews rendered a "view not found" warning in deployments where Razor runtime compilation is off and the block views are precompiled into the assembly rather than present on disk (e.g. Runtime:Mode = Production with RazorCompileOnBuild=true).

BlockPreviewViewResolver only resolved a view when the .cshtml file existed on disk (File.Exists). In a lean/precompiled publish the source files are absent while the views live in the compiled assembly, so resolution short-circuited to "not found".

Root cause & tension

The File.Exists guard was added deliberately in #84: on a case-sensitive file system the runtime view compiler throws FileNotFoundException (instead of returning Success = false) when asked for a view path that isn't on disk. Simply removing the guard would regress #84. The two issues pull in opposite directions:

Scenario Runtime compilation .cshtml on disk Behaviour
#84 (dev, case-sensitive FS) on no (wrong case) GetView throws → needs a guard
#273 (precompiled Production) off no File.Exists false → but GetView safely finds the compiled view

Fix — belt and braces

TryResolveView keeps the on-disk fast path (exception-free, preserves #84) and adds a guarded GetView fallback when the file isn't on disk, so precompiled views resolve. The fallback catches IOException so the #84 runtime-compiler throw can't crash resolution. Behaviour is unchanged for on-disk deployments.

Tests

Each was watched fail before implementing (including verifying the guard test fails with the catch removed). Full suite: 67 passed, 0 failed. The mock now returns a realistic NotFound so the resolver is testable through GetView — the previous File.Exists-only path was un-mockable and never exercised in tests.

End-to-end verification

Published the test site with views precompiled + .cshtml excluded (0 on disk), ran with runtime compilation off, and confirmed in the backoffice that the Block Grid preview rendered real content (heroBlock output) with no "view not found" warning and no preview errors server-side — i.e. resolution went through the new precompiled fallback path.

Docs

Adds a "Runtime mode and Production deployments" section to docs/configuration.md. It explains that Umbraco only enables Razor runtime compilation in BackofficeDevelopment mode, so Production (and Development) runtime modes require views to be precompiled (RazorCompileOnBuild / RazorCompileOnPublish = true) — without which no Razor view can render, block previews and front-end alike. This is the configuration half of #273 (the default Umbraco template ships with these set to false).

🤖 Generated with Claude Code

rickbutterfield and others added 3 commits July 4, 2026 09:58
BlockPreviewViewResolver only resolved a view when the .cshtml file was
present on disk (File.Exists). In a precompiled deployment - e.g.
Runtime:Mode = Production, where Umbraco does not register Razor runtime
compilation - the source files may be absent while the views are compiled
into the assembly, so resolution failed and previews rendered "view not
found".

Resolution now consults the Razor view engine even when the file is not on
disk, picking up precompiled views. The on-disk fast path is preserved
(belt), and the not-on-disk path is guarded against the runtime compiler
throwing FileNotFoundException on a case-sensitive file-system miss (braces,
regression guard for #84).

Adds unit tests for precompiled-but-not-on-disk resolution, IOException
safety, and PascalCase fall-through. Makes the resolver testable by no
longer gating solely on the un-mockable File.Exists.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…273)

Adds a "Runtime mode and Production deployments" section to the
configuration guide explaining that Umbraco only enables Razor runtime
compilation in BackofficeDevelopment mode, so Production (and Development)
runtime modes require views to be precompiled (RazorCompileOnBuild /
RazorCompileOnPublish). Without this, no Razor view can render - block
previews and the front-end alike.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The File.Exists fast-path issued the same GetView call as the guarded
branch, so it no longer avoided work - it only decided whether the call
was wrapped in try/catch. This left an asymmetry where an on-disk view
that threw IOException (e.g. a locked file) would crash resolution while
the same failure off-disk was swallowed.

Collapse to a single guarded GetView call. On-disk views resolve exactly
as before (GetView succeeds); off-disk precompiled views still resolve
(#273); IOException from the runtime compiler (#84) is still treated as
"not resolvable". IWebHostEnvironment is no longer needed and is removed
along with its now-redundant test mock.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@rickbutterfield
rickbutterfield merged commit 7636a97 into v5/dev Jul 8, 2026
5 checks passed
rickbutterfield added a commit that referenced this pull request Jul 8, 2026
…d-view-resolution

fix: resolve precompiled block views in Production runtime mode (#273)
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

Successfully merging this pull request may close these issues.

1 participant