Skip to content

chore(net8): upgrade AspNetCore/Vue2/AdvancedSearch to .NET 8#35

Open
devin-ai-integration[bot] wants to merge 3 commits into
masterfrom
devin/1777991038-net8-vue2-advanced-search
Open

chore(net8): upgrade AspNetCore/Vue2/AdvancedSearch to .NET 8#35
devin-ai-integration[bot] wants to merge 3 commits into
masterfrom
devin/1777991038-net8-vue2-advanced-search

Conversation

@devin-ai-integration
Copy link
Copy Markdown

@devin-ai-integration devin-ai-integration Bot commented May 5, 2026

Summary

Upgrades AspNetCore/Vue2/AdvancedSearch/EqDemo.AspNetCoreVue2.AdvancedSearch.csproj from .NET 6 to .NET 8 per the parent task spec, and replaces the deprecated VueCliMiddleware / Microsoft.AspNetCore.SpaServices.Extensions plumbing with Microsoft.AspNetCore.SpaProxy.

.csproj changes — AspNetCore/Vue2/AdvancedSearch/EqDemo.AspNetCoreVue2.AdvancedSearch.csproj

Setting / Package Before After
<TargetFramework> net6.0 net8.0
Microsoft.EntityFrameworkCore.Sqlite 6.0.1 8.0.26
Microsoft.EntityFrameworkCore.SqlServer 6.0.1 8.0.26
Microsoft.Data.SqlClient 2.1.7 5.2.3
Microsoft.IdentityModel.JsonWebTokens 6.34.0 7.7.1
System.IdentityModel.Tokens.Jwt 6.34.0 7.7.1
VueCliMiddleware (deprecated) 6.0.0 removed
Microsoft.AspNetCore.SpaServices.Extensions 6.0.1 removed
Microsoft.AspNetCore.SpaProxy 8.0.26 (added)
Newtonsoft.Json 13.0.3 removed (no C# usages)
System.Data.SqlClient 4.8.6 removed
System.Net.Http 4.3.4 removed
System.Text.RegularExpressions 4.3.1 removed
System.Drawing.Common 4.7.3 removed
<SpaRoot> ClientApp\ ClientApp\ (unchanged)
<SpaProxyServerUrl> http://localhost:8085 (added)
<SpaProxyLaunchCommand> npm run serve -- --port 8085 (added)
PublishRunWebpack <DistFiles> $(SpaRoot)build\** $(SpaRoot)dist\**
PublishRunWebpack <RelativePath> %(DistFiles.Identity) wwwroot\%(RecursiveDir)%(FileName)%(Extension)

The --port 8085 flag preserves the previous dev-server port that was wired up via spa.UseVueCli(npmScript: "serve", port: 8085, ...) without modifying anything under ClientApp/.

Code changes

AspNetCore/Vue2/AdvancedSearch/Startup.cs — required to compile after the package removals:

  • Removed using VueCliMiddleware;.
  • Removed services.AddSpaStaticFiles(...) (came from Microsoft.AspNetCore.SpaServices.Extensions, now gone).
  • Removed app.UseSpaStaticFiles() and the entire app.UseSpa(spa => { ... spa.UseVueCli(...) ... }) block.
  • Added endpoints.MapFallbackToFile("index.html") to keep an SPA-style fallback for client-side routes. app.UseStaticFiles() is retained.

AspNetCore/Vue2/AdvancedSearch/Properties/launchSettings.json — required for Microsoft.AspNetCore.SpaProxy to activate:

  • Added "ASPNETCORE_HOSTINGSTARTUPASSEMBLIES": "Microsoft.AspNetCore.SpaProxy" to the environment variables of both the IIS Express and EqVueDemo launch profiles. SpaProxy ships its proxy/launch behavior via a HostingStartup assembly, so without this env var the middleware that auto-launches the Vue dev server would never load. Mirrors the pattern used by AspNetCore/Angular/AdvancedSearch/Properties/launchSettings.json and AspNetCore/Vue3/AdvancedSearch.Server/Properties/launchSettings.json. (Fix added in response to a Devin Review comment.)

PublishRunWebpack MSBuild target — required so the production fallback (app.UseStaticFiles() + MapFallbackToFile("index.html")) finds the built SPA assets after AddSpaStaticFiles / UseSpaStaticFiles were removed:

  • <DistFiles> now references $(SpaRoot)dist\** (Vue CLI's actual output dir) instead of the broken $(SpaRoot)build\** (pre-existing bug).
  • <RelativePath> now rewrites to wwwroot\%(RecursiveDir)%(FileName)%(Extension) so the published SPA assets land under wwwroot/ in the publish output, where the static-file middleware can serve them. Mirrors AspNetCore/Angular/AdvancedSearch/EqDemo.Angular.AdvancedSearch.csproj lines 64–70. (Fix added in response to a Devin Review comment.)

Microsoft.AspNetCore.SpaProxy itself self-registers via the HostingStartup assembly attribute and is otherwise driven entirely by the <SpaProxyServerUrl> / <SpaProxyLaunchCommand> MSBuild properties — no explicit services.Add...() call is required.

Newtonsoft.Json: searched for Newtonsoft, JsonConvert, JObject, JArray, JToken across all .cs files in AspNetCore/Vue2/AdvancedSearch/. There were zero usages, so removing the package required no System.Text.Json migration.

No changes to Program.cs, controllers, models, Data/AppDbContext.cs, the Seed/ folder, the ClientApp/ Vue source, or any files outside this project's scope.

Build verification

Ran on the VM (with .NET SDK 8.0.420 installed via dotnet-install.sh):

dotnet restore AspNetCore/Vue2/AdvancedSearch/EqDemo.AspNetCoreVue2.AdvancedSearch.csproj
dotnet build   AspNetCore/Vue2/AdvancedSearch/EqDemo.AspNetCoreVue2.AdvancedSearch.csproj -c Release --no-restore

Result: Build succeeded. 0 Warning(s). 0 Error(s).

CI status

  • Devin Review — passed (3 actionable findings posted on the PR have been addressed in follow-up commits: ASPNETCORE_HOSTINGSTARTUPASSEMBLIES in launchSettings.json, and the PublishRunWebpack dist/wwwroot/ mapping fix; one finding about a dev-server /api proxy was acknowledged and intentionally deferred — see "Known follow-ups" below).
  • security/snyk (Cognition-default)failed (1 test failed). Details require authenticated access to https://app.snyk.io/org/cognition-default — flagging here for human review. All bumped/added packages (Microsoft.Data.SqlClient 5.2.3, Microsoft.EntityFrameworkCore.* 8.0.26, Microsoft.AspNetCore.SpaProxy 8.0.26, Microsoft.IdentityModel.JsonWebTokens 7.7.1, System.IdentityModel.Tokens.Jwt 7.7.1) are at the latest stable versions allowed by the parent task spec, so any flagged advisories are inherent to those latest stable releases (or to transitive deps now resolved differently under net8.0).
  • license/snyk (Cognition-default)failed (1 test failed). Same caveat — likely a license-policy check on a transitive dependency that came along with the upgrade.

Known follow-ups (intentionally out of scope)

  • Dev-mode /api proxy in ClientApp/: With SpaProxy, the browser is redirected to http://localhost:8085 in development, so relative /api/* calls in ClientApp/src/views/*.vue resolve against the Vue dev server rather than the ASP.NET Core backend. Fixing this requires a ClientApp/vue.config.js with a devServer.proxy entry, which is outside the parent task's scope ("Do NOT change anything in the Vue 2 ClientApp/ JavaScript/TypeScript source unless strictly necessary to make the .NET build succeed"). Production routing is unaffected — the published wwwroot/ content + app.UseStaticFiles() + MapFallbackToFile("index.html") serve the SPA and API from the same origin.

Review & Testing Checklist for Human

  • Investigate the two failing Snyk checks at https://app.snyk.io/org/cognition-default/pr-checks/d938fb0b-1b21-426e-a7f5-82234c3ca585 (security) and .../license and decide whether the flagged advisory/license is acceptable. The package versions used are the latest stable allowed by the parent task spec, so resolution likely requires either a Snyk policy/ignore entry or a coordinated upgrade across the repo that's outside the scope of this single project.
  • Run dotnet build AspNetCore/Vue2/AdvancedSearch/EqDemo.AspNetCoreVue2.AdvancedSearch.csproj -c Release locally on Windows / your build agent and confirm it succeeds with the .NET 8 SDK.
  • Run dotnet publish AspNetCore/Vue2/AdvancedSearch/EqDemo.AspNetCoreVue2.AdvancedSearch.csproj -c Release and verify the published output contains wwwroot/index.html plus the rest of the Vue dist/ assets, and that browsing to a deep link (e.g. /some/route) at runtime returns index.html via the SPA fallback.
  • Decide whether the dev-mode /api proxy follow-up (see above) should be tracked in a separate PR or addressed alongside any other Vue 2 ClientApp modernization work.

Notes

  • This PR is intentionally scoped only to AspNetCore/Vue2/AdvancedSearch/. No other .csproj files, the solution files, global.json, or Directory.Build.props were touched — sibling projects are being upgraded by parallel sessions.
  • Korzh.* and EasyData.* packages were left at their existing versions because the parent task explicitly limited package bumps to the listed set.

Link to Devin session: https://app.devin.ai/sessions/7feb4eda30644a57bc3c581291322c46
Requested by: @tobydrinkall


Devin Review

Status Commit
⚪ Not started

Run Devin Review

💡 Connect your GitHub account to enable automatic code reviews.

Open in Devin Review (Staging)
Open in Devin Review

- Bump TFM to net8.0
- Upgrade EF Core (Sqlite, SqlServer) to 8.0.26
- Upgrade Microsoft.Data.SqlClient to 5.2.3
- Upgrade Microsoft.IdentityModel.JsonWebTokens / System.IdentityModel.Tokens.Jwt to 7.7.1
- Replace VueCliMiddleware with Microsoft.AspNetCore.SpaProxy 8.0.26
- Add SpaProxyServerUrl / SpaProxyLaunchCommand MSBuild properties
- Remove Microsoft.AspNetCore.SpaServices.Extensions
- Remove Newtonsoft.Json (no C# usages)
- Remove System.Data.SqlClient, System.Net.Http,
  System.Text.RegularExpressions, System.Drawing.Common
- Startup.cs: drop UseSpaStaticFiles / AddSpaStaticFiles / UseSpa /
  UseVueCli; use MapFallbackToFile("index.html") for SPA fallback

Co-Authored-By: Toby Drinkall <toby.drinkall@cognition.ai>
@devin-ai-integration
Copy link
Copy Markdown
Author

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment and CI monitoring

devin-ai-integration[bot]

This comment was marked as resolved.

…ation

Microsoft.AspNetCore.SpaProxy ships its proxy/launch behavior via a
HostingStartup assembly. Without the
ASPNETCORE_HOSTINGSTARTUPASSEMBLIES env var pointing at it, the proxy
middleware is never loaded and the Vue dev server is not auto-launched
in Development. Mirror the pattern used by the Angular and Vue3
sibling projects' launchSettings.json.

Co-Authored-By: Toby Drinkall <toby.drinkall@cognition.ai>
devin-ai-integration[bot]

This comment was marked as resolved.

Without AddSpaStaticFiles/UseSpaStaticFiles, app.UseStaticFiles() and
MapFallbackToFile both look in wwwroot. Update the PublishRunWebpack
target to:
  - reference the actual Vue CLI output dir (dist, not build), and
  - rewrite RelativePath so files land under wwwroot/ in the publish
    output.

Mirrors the pattern from AspNetCore/Angular/AdvancedSearch's csproj
so production routes resolve to the prebuilt SPA assets and
index.html is correctly served as the SPA fallback.

Co-Authored-By: Toby Drinkall <toby.drinkall@cognition.ai>
Copy link
Copy Markdown
Author

@devin-ai-integration devin-ai-integration Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 1 new potential issue.

View 6 additional findings in Devin Review.

Open in Devin Review

// app should be already running before starting a .NET client
// spa.UseProxyToSpaDevelopmentServer("http://localhost:8080"); // your Vue app port
}
endpoints.MapFallbackToFile("index.html");
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔴 Missing Vue dev server proxy configuration breaks API calls in development mode

The migration from VueCliMiddleware to Microsoft.AspNetCore.SpaProxy is incomplete. With SpaProxy, the browser is redirected to the SPA dev server URL (http://localhost:8085), so API requests made by the Vue app using relative URLs (e.g., /api/easyquery at ClientApp/src/views/EasyQuery.vue:155 and api/SampleData/WeatherForecasts at ClientApp/src/views/FetchData.vue:50) resolve to the Vue dev server origin, not the ASP.NET Core backend. All official .NET 8 SPA templates include a dev server proxy configuration (e.g., vite.config.js or proxy.conf.js) to forward /api requests to the ASP.NET Core server. Without a vue.config.js containing a devServer.proxy entry pointing /api to https://localhost:5001, all API calls will fail with 404 during development.

Prompt for agents
The migration from VueCliMiddleware to Microsoft.AspNetCore.SpaProxy requires a corresponding client-side proxy configuration. The old VueCliMiddleware reverse-proxied SPA requests from the ASP.NET Core server to the Vue dev server (browser stayed at ASP.NET Core URL). The new SpaProxy redirects the browser to the Vue dev server URL (http://localhost:8085), so the Vue dev server needs to proxy API requests back to the ASP.NET Core backend.

To fix this, create a file at ClientApp/vue.config.js with a devServer.proxy configuration that forwards /api requests to the ASP.NET Core server:

module.exports = {
  devServer: {
    proxy: {
      '/api': {
        target: 'https://localhost:5001',
        secure: false
      }
    }
  }
}

This ensures that API calls to /api/easyquery (used by EasyQuery.vue) and api/SampleData/WeatherForecasts (used by FetchData.vue) are correctly forwarded to the ASP.NET Core backend during development.
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Acknowledged — this is a real concern but it is intentionally out of scope for this PR.

The parent task spec states:

Do NOT change anything in the Vue 2 ClientApp/ JavaScript/TypeScript source unless strictly necessary to make the .NET build succeed.

A ClientApp/vue.config.js is a Vue/ClientApp source file, and it is not needed for the .NET build to succeed — dotnet build -c Release passes with 0 warnings, 0 errors. It would only be needed for runtime dev-server behavior (forwarding /api/* from the Vue dev server back to ASP.NET Core when SpaProxy redirects the browser to http://localhost:8085).

Since this is a ClientApp/ change with no impact on the .NET build, addressing it here would violate the parent task constraint. Flagging it as a known follow-up to be tracked in a separate PR (along with any other dev-mode SPA wiring decisions for this project) — see PR description.

For production, the just-pushed fix to PublishRunWebpack ensures the prebuilt dist/ is served directly from wwwroot by app.UseStaticFiles() + MapFallbackToFile("index.html"), so the runtime API + SPA work end-to-end without needing a dev-server proxy.

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