简体   繁体   中英

ASP.NET Core 2.2 app with Node.js broke after VS update

note: the interesting bit is under [Edit 10/22/2020] below, the intro is just me being puzzled.

I think it was the VS update to 16.8.0 Preview 4.0. I am well aware .NET Core 2.2 was deprecated and is no longer supported. I want to understand what is going on.

We inherited a web application that was supposed to be ASP.NET Core with MVC but as it appears it doesn't do much with that infrastructure and instead leans heavily on Node.js. Here's webpack.config.js :

const path = require('path');

module.exports = {
    entry: {
        main: './ClientApp/index.js'
    },
    devtool: 'inline-source-map',
    stats: { modules: false },
    devServer: {
        hot: false
    },
    watchOptions: {
        ignored: /node_modules/
    },
    output: {
        path: path.join(__dirname, '/wwwroot/js/'),
        filename: 'site.js',
        publicPath: '/'
    }
};

An entry point ./ClientApp/index.js is declared and until recently this seemed indeed what was executed when one started the application in Visual Studio with IIS Express and Chrome.

However, since my update I get Index.cshtml instead. Which is exactly what I would expect from an ASP.NET application with MVC.

One remarkable thing I noticed is that under dependencies I no longer see the any/npm branch that used to be there.

My co-workers who are still on Visual Studio 2019 stable still get the old behavior, with index.js kicking in. It looks like request routing behavior has changed.

Re-installing dotnet SDK 2.2 and Node.js with subsequent "npm install" does not fix it, I still get the default page Index.cshtml .

Question: What exactly made the application execute index.js rather than Index.cshtml ? I do not find any references in the code to index.js apart from the declaration in webpack.config.js . I would expect to find something that starts node.exe with index.js as an argument, or some statement that wraps that.

I tried to get it working by installing NuGet packages Node.js and Microsoft.AspNetCore.NodeServices, which were never there before. But it does not restore the desired behavior.

[Edit]

It appears it does not matter what I enter for the main entry point in webpack.config.js , it only needs to comply with the schema but it is never even looked for at runtime. I found a way to display the console to see some output. I got rid of some warnings and errors but the result is still the same. It may not be routing after all, it may have been the same page all the time, just now dysfunctional and looking very different as a result. I do not know. Here's the console output, I hope it will provide some alert to more knowledgeable folks:

info: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[0]
      User profile is available. Using 'C:\Users\MaatM\AppData\Local\ASP.NET\DataProtection-Keys' as key repository and Windows DPAPI to encrypt keys at rest.
Hosting environment: Development
Content root path: D:\Projects\ProjectName
Now listening on: https://localhost:5001
Now listening on: http://localhost:5000
Application started. Press Ctrl+C to shut down.
info: Microsoft.AspNetCore.NodeServices[0]
      webpack built 33af367a37b276ede2b3 in 2029ms
info: Microsoft.AspNetCore.NodeServices[0]
      i ´¢ówdm´¢ú: Hash: 33af367a37b276ede2b3
      Version: webpack 4.29.5
      Time: 2029ms
      Built at: 2020-10-16 14:22:53
        Asset      Size  Chunks             Chunk Names
      site.js  6.71 MiB    main  [emitted]  main
      Entrypoint main = site.js
info: Microsoft.AspNetCore.NodeServices[0]
      i ´¢ówdm´¢ú: Compiled successfully.
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
      Request starting HTTP/1.1 GET https://localhost:5001/
info: Microsoft.AspNetCore.Routing.EndpointMiddleware[0]
      Executing endpoint 'Page: /Index'
info: Microsoft.AspNetCore.Mvc.RazorPages.Internal.PageActionInvoker[3]
      Route matched with {page = "/Index"}. Executing page /Index
info: Microsoft.AspNetCore.Mvc.RazorPages.Internal.PageActionInvoker[101]
      Executing handler method ProjectName.Pages.IndexModel.OnGet with arguments ((null)) - ModelState is Valid
info: Microsoft.AspNetCore.Mvc.RazorPages.Internal.PageActionInvoker[102]
      Executed handler method OnGet, returned result .
info: Microsoft.AspNetCore.Mvc.RazorPages.Internal.PageActionInvoker[103]
      Executing an implicit handler method - ModelState is Valid
info: Microsoft.AspNetCore.Mvc.RazorPages.Internal.PageActionInvoker[104]
      Executed an implicit handler method, returned result Microsoft.AspNetCore.Mvc.RazorPages.PageResult.
info: Microsoft.AspNetCore.Mvc.RazorPages.Internal.PageActionInvoker[4]
      Executed page /Index in 63.434ms
info: Microsoft.AspNetCore.Routing.EndpointMiddleware[1]
      Executed endpoint 'Page: /Index'
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
      Request finished in 217.9321ms 200 text/html; charset=utf-8
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
      Request starting HTTP/1.1 GET https://localhost:5001/~/css/site.css?123
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
      Request starting HTTP/1.1 GET https://localhost:5001/~/lib/bootstrap/dist/css/bootstrap.css
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
      Request starting HTTP/1.1 GET https://localhost:5001/~/lib/jquery/dist/jquery.js
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
      Request starting HTTP/1.1 GET https://localhost:5001/~/js/site.js
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
      Request starting HTTP/1.1 GET https://localhost:5001/~/lib/bootstrap/dist/js/bootstrap.bundle.js
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
      Request finished in 31.0267ms 404
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
      Request finished in 31.0331ms 404
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
      Request finished in 19.6686ms 404
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
      Request finished in 52.5483ms 404
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
      Request finished in 52.5487ms 404
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
      Request starting HTTP/1.1 GET https://localhost:5001/~/css/site.css?123
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
      Request finished in 5.9602ms 404
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
      Request starting HTTP/1.1 GET https://localhost:5001/~/lib/jquery/dist/jquery.js
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
      Request finished in 4.1753ms 404
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
      Request starting HTTP/1.1 GET https://localhost:5001/~/lib/bootstrap/dist/js/bootstrap.bundle.js
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
      Request finished in 3.914ms 404
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
      Request starting HTTP/1.1 GET https://localhost:5001/~/js/site.js
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
      Request finished in 4.3371ms 404

Some puzzling things: I see some garbled characters under the second Microsoft.AspNetCore.NodeServices[0], then the same thing a bit further down. In between it says Entrypoint main = site.js which I did not declare.

[Edit 10/22/2020]

Well. this is exciting. Thank you M Hornbacher for the comment. The "link tag to site.js" was not in Index.cshtml, I found it in _Layout.cshtml and it looked like this:

<script src="~/js/site.js" asp-append-version="true"></script>

which struck me as odd. I was not familiar with the ~ syntax, I figured I would have written it like this instead:

<script type="text/javascript" src="/js/site.js"></script>

So I changed it, ran it and I got some of the old desired behavior back! I then looked for more occurrences of the ~/ construct, changed them and instantly got (nearly) all of the desired behavior back.

Apparently the interpretation of ~/ broke, which as I understand it is an ASP.NET thing that gets replaced with the root path on the server. Or, more likely, what the app considers root changed. So now I am wondering where does it say what is to be root?

By the way, I am on Visual Studio 2019 16.8.0 Preview 5.0 now if that could matter. The app is still .NET Core 2.2.

I imagine you know this but, ~ typically stands for the home directory. On a linux or mac you type cd ~ and it will take you to the current users directory.

Like you said ~ could be ASP.net specific, I don't usually see it on projects that deploy to linux, it's too relative.

That said there isn't any C#/ASP.net code to see here. If it actually works on the production server but not locally you might have issues getting to work in production because the ~ is now missing.

You might want to research if prod really requires ~ in the path and if so why.

So now I am wondering where does it say what is to be root?

Based on this:

output: {
        path: path.join(__dirname, '/wwwroot/js/'),
        filename: 'site.js',
        publicPath: '/'
    }

and that __dirname Can change based on the file it is run in I believe. Your js file site.js is going to ${__dirname/wwwroot/js/}

In order for this to work

<script type="text/javascript" src="/js/site.js"></script>

Your root directory for the project looks like it is ${__dirname}/wwwroot/

I also notice in your output you have:

Content root path: D:\Projects\ProjectName

That could be the same as __dirname , thats a guess, it's not possible to determine more with the info given.

I would be curious to know if there is a index/server.js file around.

Here are some references that discuss determining the root of a node app:

Determine project root from a running node.js application

https://www.abeautifulsite.net/determining-your-apps-base-directory-in-nodejs

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM