.NET · ASP.NET, Razor, Blazor, MAUI

Your .NET code runs on the server. The JavaScript next to it still arrives readable.

Teams building on .NET often assume that because the application is compiled and server-rendered, the client side inherits some of that protection. It does not. The script files under wwwroot are served exactly as written, script embedded in a server template is delivered with the rendered page, and a Blazor WebAssembly build downloads compiled assemblies that decompile back to readable code. Here is what each .NET delivery shape actually exposes, and what to do about it.

The Short Version

Move it server-side, protect the rest

.NET teams have the easiest version of this problem, because the place to move logic already exists.

wwwroot is publicEvery file under it is a static asset that anyone can request and read.
IL is not JavaScriptBlazor WebAssembly assemblies need a .NET obfuscator, not this one.
You already have a serverWhich makes moving authority off the client a routing change rather than a project.
What You Actually Ship

Compilation protects the half of the application that never left

The intuition that a .NET application is “compiled, therefore protected” is half right, and the half that is right is the half nobody was asking about. Controllers, services and data access are compiled into assemblies that stay on your infrastructure, and a visitor never receives them. The browser receives markup, stylesheets and JavaScript. Whatever decisions you implemented in that JavaScript — which fields are valid, how a total is calculated, which features a plan includes, what the next call in a sequence should be — travel to every visitor in full text.

Static assets are served verbatim

Files under wwwroot are handed out by the static file middleware without transformation. There is no build step between your editor and the browser unless you added one, so what you typed is what a visitor reads.

Rendering is not concealment

A view engine assembles HTML on the server and sends the result. Any <script> content inside that view is part of the result. The template stayed home; its output did not.

The developer tools are already open

Every browser ships a debugger, a network log and a full-text search across loaded sources. No special tooling is involved in reading a .NET site’s client code, which is why “nobody would bother” is a weak assumption.

Five Delivery Shapes

The answer changes with how your .NET application reaches the browser

“A .NET web app” covers at least five quite different arrangements, and the exposure profile is not the same across them. Find yours before deciding what to do.

ASP.NET Core MVC and Razor Pages

The common case. Views render server-side, and the interactive behaviour lives in .js files under wwwroot, possibly bundled by a Node toolchain. This is the most straightforward shape to protect: run the protection step over your own built script output, exclude restored libraries, and keep source maps out of the published folder. Inline <script> blocks in a .cshtml view are the awkward part, and moving them into real script files is the right fix for several reasons at once.

Web Forms and other server templates

Long-lived .aspx applications routinely interleave script with server tags in the same file. The Mixed Server Code option exists for this: it locates the script regions inside a file that is not pure JavaScript and protects those while leaving the markup and server tags untouched. Its documented targets are .aspx, .php, .jsp and .html, and it is an Enterprise-tier option.

Blazor Server

The strongest of the five for keeping logic private, because the component code executes on the server and the browser receives rendered diffs over a live connection. Your business rules never become a downloadable file. What the browser does get is the framework script plus whatever interop and enhancement JavaScript you wrote, and that remainder is what a protection step applies to.

Blazor WebAssembly

The shape most often misjudged. The browser downloads your compiled assemblies, and compiled here means intermediate language, which decompiles to readable code with ordinary tooling. A JavaScript protection tool does not transform those assemblies, and we will not claim it does. It covers your interop layer, your JavaScript libraries and your initialisation script; the managed side needs a .NET obfuscator, and anything genuinely sensitive belongs behind an API.

MAUI Hybrid and WebView2 desktop

Web assets packaged inside a desktop application, rendered by an embedded browser. Shipping to a user machine makes the files easier to reach rather than harder, and the embedded browser has the same developer tools. Treat the bundled web content exactly as you would treat a public site, and use the compiled .NET side of the application as the place to put anything that decides something.

A .NET API with a separate front end

If your Razor or Web Forms application is really a JSON API with a React, Angular or Vue client in front of it, the client is an ordinary single-page application and the framework-specific guides apply. The .NET half is already in the right place; the work is entirely on the JavaScript side.

Mixed Files

Script inside a server template is a genuinely harder problem

A file containing both server tags and JavaScript is not a JavaScript file, and treating it as one produces either a parse failure or corrupted output. The Mixed Server Code option handles the extraction, but the file itself remains more fragile than a standalone script, and understanding why prevents most of the incidents.

A server tag can appear mid-expression

Assigning a variable from a server expression is a normal thing to write and is not valid JavaScript until the server has rendered it. The protector must treat the tag as an opaque token and preserve it exactly, which constrains what it can safely rearrange around it.

Never straddle a statement boundary

A server tag that opens a block on one side and closes it on another leaves the parser without complete statements to work with. Keep each tag inside a single expression, and build conditional markup around whole script blocks rather than through them.

Smoke-test the rendered page

The template is not what runs. Request the page from a real server, view the delivered source, and exercise the behaviour there. A template that looks correct can still render into something that does not run, and only the rendered output tells you.

If your build can emit plain .js files, prefer that path. It is simpler, every other option composes with it more predictably, and it happens to be what a strict content security policy requires as well. Mixed file support exists because large existing applications cannot always be restructured on demand, not because embedding script in templates is the better arrangement.

Where Authority Belongs

The advantage .NET teams have, and usually underuse

Most guidance about moving decisions off the client runs into the objection that there is nowhere to move them to. That objection does not apply here. If you are running ASP.NET at all, you have an authenticated server with a request pipeline, and adding an endpoint is routine work rather than an architectural project. The sorting rule below is worth applying before any protection setting is chosen.

1
Anything that grants permission moves

Licence validation, entitlement and plan checks, role gates and quota enforcement belong in an endpoint that authenticates its caller. A client-side check is a convenience for honest users and nothing more.

2
Anything valuable to a competitor moves

Pricing formulas, scoring models, routing and matching rules, and eligibility logic are worth more to the person reading them than the effort of reading. If the calculation is the product, the calculation should be a request.

3
Secrets never travel

An API key, a signing secret or a connection string in client script is disclosed the moment the page loads, and no transformation changes that. Proxy the call through your own server and keep the credential there.

4
Protect what genuinely has to stay

Interface behaviour, form logic, rendering and the shape of your API surface all have to be in the browser to work. That remainder is a real asset, and it is what the protection step is for.

Build Integration

Fitting the step into a .NET publish

The protection step belongs after your web assets are built and before the publish output is packaged, which in most .NET projects means one command between the front-end build and dotnet publish. It is a release-time step, not part of the inner development loop.

Run it on built output

If a Node toolchain bundles your scripts, protect the bundler output rather than the sources, so the transformation applies once to the final shape. If there is no bundler, point it directly at your own files under wwwroot and let the include and exclude rules do the selecting.

Exclude what you did not write

Restored client libraries, framework runtime files and polyfills gain nothing from being protected and occasionally break when they are. Narrow the input to your own code; it is faster and safer at the same time.

Keep maps out of the publish folder

A source map published next to a protected file reverses the work in a single request. Generate maps, store them privately for symbolicating production traces, and confirm they are absent from what actually ships.

Test the published artifact

Run your end-to-end suite against the protected publish output, not just against a development build. That is the arrangement that catches an interaction between a transform and your code while it is still attached to the change that caused it.

Frequently Asked

ASP.NET, Razor and Blazor protection, answered

Does server-side rendering keep my application logic private?

It keeps whatever stays on the server private, which is the point, but it says nothing about the JavaScript that ships alongside the rendered markup. A Razor page renders HTML on the server and then delivers script files from wwwroot exactly as any other site would. The validation rules, pricing calculations, feature checks and API call sequences written in that script are downloaded in full. Server-side rendering is a strong architecture for keeping logic private precisely because you can move logic into it, not because rendering hides the client code you still ship.

Can JavaScript Obfuscator protect a Blazor WebAssembly application?

It protects the JavaScript in that application, which is a real but partial surface. A Blazor WebAssembly build downloads compiled .NET assemblies to the browser, and those assemblies are intermediate language rather than JavaScript. A JavaScript protection tool does not transform them, and we will not pretend otherwise. What it does cover is the interop layer you wrote, any JavaScript libraries you ship, and initialisation or glue script in wwwroot. For the managed assemblies themselves you need a .NET obfuscator, and for anything genuinely sensitive the durable answer is to move it behind a server endpoint.

Is Blazor Server safer than Blazor WebAssembly for proprietary logic?

For keeping logic off the client, yes, and by a wide margin. In the server hosting model your component code executes on the server and the browser receives rendered updates over a persistent connection, so the logic never becomes a downloadable artifact at all. What the browser does receive is the framework script and whatever interop or enhancement JavaScript you added, which is the part worth protecting. The trade is operational rather than architectural: a live connection per user, latency on interactions, and reconnection behaviour to design for.

How do I protect script that is embedded inside an .aspx or .cshtml page?

The two cases differ. For classic Web Forms and similar server-template pages, the Mixed Server Code option is designed for exactly this: it locates script regions inside files that are not pure JavaScript and protects them while leaving the surrounding markup and server tags byte-identical. Its documented targets are .aspx, .php, .jsp and .html pages, and it is an Enterprise-tier option. Razor .cshtml files are not in that list, so for modern ASP.NET Core the supported route is to move script out of the view into .js files under wwwroot and protect those, which is also what a strict content security policy will push you toward anyway.

What goes wrong when a server tag sits inside a JavaScript expression?

It stops being valid JavaScript until the server has rendered it, which is the central difficulty with mixed files. A line such as a variable assigned from a server expression is a template instruction, not a program, so the protector has to treat the tag as an opaque token and preserve it exactly. Two rules follow directly. Never let a server tag straddle a statement boundary, because the parser needs complete statements on either side. And always smoke-test the rendered page rather than the template, because the template is not what runs in a browser.

Which files in wwwroot should the protection step actually process?

Your own built output, and not much else. Point it at the site scripts you wrote or bundled, and exclude vendor directories, package-manager-restored libraries, framework runtime files and polyfills. Protecting a third-party library gains you nothing, costs build time, and occasionally breaks a package that checks its own internals. Source maps should be kept out of the published artifact entirely, since a map next to a protected file undoes the work in one request.

Does a MAUI Hybrid or WebView2 desktop application change the answer?

Only in the sense that the files sit on the user machine instead of a web server, which makes casual inspection easier rather than harder. The web assets are packaged with the application and can be read out of it, and the embedded browser ships the same developer tools as the standalone one. Treat that bundled web content the same way you would treat a public site: protect what you ship, and keep the operations that matter behind either your server or the compiled .NET side of the application, where a customer with a file browser cannot reach them.

Where should authority live in a .NET application?

On the server, and .NET teams have an unusually easy time of this because a server is already part of the architecture. Licence validation, entitlement checks, pricing and discount rules, quota enforcement and anything that decides what a user is allowed to do belong in an endpoint that authenticates its caller. The client then asks and renders the answer. Protecting the front end raises the effort required to lift the interface logic that remains and to tamper with the shipped bundle undetected, which is worth having on top of that arrangement rather than instead of it.

Start Now

Open your own published site and read its scripts

Deploy to a staging environment, open the browser developer tools, and search the loaded sources for the name of a pricing rule, a feature flag or a licence check. Whatever comes back is what a visitor can read today. That search takes two minutes and settles the question of whether any of this applies to your application.

Related Guides

Protecting other JavaScript targets

Sites with no build step · Node.js source · Self-hosted and on-premises apps · Angular · Electron · Mixed Server Code and the lock options · Client-side licence checks · Obfuscating htmx and Alpine apps · Compiled-to-JavaScript output · Low-code platforms