Git Product home page Git Product logo

aspnetcore-vueclimiddleware's Introduction

VueCliMiddleware - Supporting Vue Cli and Quasar Cli

This is a stand-alone module to add Vue Cli and Quasar Cli support to AspNet Core.

See the examples here: https://github.com/EEParker/aspnetcore-vueclimiddleware/tree/master/samples

ASP.NET 3.X Endpoint Routing

First, be sure to switch Vue Cli or Quasar Cli to output distribution files to wwwroot directly (not dist).

  • Quasar CLI: regex: "Compiled successfully"
  • Vue CLI: regex: "Compiled successfully" or "running at" or "Starting development server" depending on version

the reason for Starting development server ,the npm-script running checkpoint: Although the dev server may eventually tell us the URL it's listening on, it doesn't do so until it's finished compiling, and even then only if there were no compiler warnings. So instead of waiting for that, consider it ready as soon as it starts listening for requests.see the codes

Configuration Options

When using the MapToVueCliProxy or UseVueCli you can customize the behavior based on your npm script runner or compiler.

Parameter Type Description Default
npmScript string The name of the script in your package.json file that launches the vue-cli, quasar cli or other web server.
spaOptions SpaOptions Set the folder of the app to be proxied.
port int Specify the vue cli server port number. This is also used by the force-kill option to discover processes utilizing the port. 8080
https bool Set proxy to use https false
runner enum { Npm, Yarn } Specify the runner, Npm and Yarn are valid options. Yarn support is experimental. Npm
regex string IMPORTANT Text to search in npm log that indicates web server is running. This MUST BE SET for vue-cli, quasar and quasar v2. (e.g. running at, READY, APP Url) running at
forceKill bool Attempt to kill the npm process when stopping debugging. false
wsl bool Set to true if you are using WSL on windows. For other operating systems it will be ignored. This changes the executed process name to wsl instead of cmd. false

See Migrating Asp.Net 2.2 to 3.0 Endpoint Routing

    public class Startup {

        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            // NOTE: PRODUCTION Ensure this is the same path that is specified in your webpack output
            services.AddSpaStaticFiles(opt => opt.RootPath = "ClientApp/dist");
            services.AddControllers();
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
	    // optional base path for IIS virtual app/directory
	    app.UsePathBase("/optionalpath");
            
	    // PRODUCTION uses webpack static files
            app.UseSpaStaticFiles();

            // Routing
            app.UseRouting();
            app.UserAuthorization();
            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();

                endpoints.MapToVueCliProxy(
                    "{*path}",
                    new SpaOptions { SourcePath = "ClientApp" },
                    npmScript: (System.Diagnostics.Debugger.IsAttached) ? "serve" : null,
                    regex: "Compiled successfully",
                    forceKill: true,
		    wsl: false // Set to true if you are using WSL on windows. For other operating systems it will be ignored
                    );
            });
        }
    }

ASP.NET 2.2 Usage Example

    using VueCliMiddleware;

    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        public virtual void ConfigureServices(IServiceCollection services)
        {
           services.AddMvc(); // etc
           
           // Need to register ISpaStaticFileProvider for UseSpaStaticFiles middleware to work
           services.AddSpaStaticFiles(configuration => { configuration.RootPath = "ClientApp/dist"; });
        }

        public virtual void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
           // your config opts...
		   // optional basepath
		   // app.UsePathBase("/myapp");

           // add static files from SPA (/dist)
          app.UseSpaStaticFiles();

          app.UseMvc(routes => /* configure*/ );

          app.UseSpa(spa =>
            {
                spa.Options.SourcePath = "ClientApp";
#if DEBUG
                if (env.IsDevelopment())
                {
                    spa.UseVueCli(npmScript: "serve", port: 8080); // optional port
                }
#endif
            });
        }
    }

CSPROJ Configuration

You may also need to add the following tasks to your csproj file. This are similar to what are found in the default ASPNETSPA templates.

  <PropertyGroup>
    <!-- Typescript/Javascript Client Configuration -->
    <SpaRoot>ClientApp\</SpaRoot>
    <DefaultItemExcludes>$(DefaultItemExcludes);$(SpaRoot)node_modules\**</DefaultItemExcludes>
  </PropertyGroup>
  <Target Name="DebugEnsureNodeEnv" BeforeTargets="Build">
    <!-- Build Target:  Ensure Node.js is installed -->
    <Exec Command="node --version" ContinueOnError="true">
      <Output TaskParameter="ExitCode" PropertyName="ErrorCode" />
    </Exec>
    <Error Condition="'$(ErrorCode)' != '0'" Text="Node.js is required to build and run this project. To continue, please install Node.js from https://nodejs.org/, and then restart your command prompt or IDE." />
  </Target>

  <Target Name="DebugEnsureNpm" AfterTargets="DebugEnsureNodeEnv">
    <!-- Build Target:  Ensure Node.js is installed -->
    <Exec Command="npm --version" ContinueOnError="true">
      <Output TaskParameter="ExitCode" PropertyName="ErrorCode" />
    </Exec>
  </Target>

  <Target Name="EnsureNodeModulesInstalled" BeforeTargets="Build" Inputs="package.json" Outputs="packages-lock.json">
    <!-- Build Target: Restore NPM packages using npm -->
    <Message Importance="high" Text="Restoring dependencies using 'npm'. This may take several minutes..." />

    <Exec WorkingDirectory="$(SpaRoot)" Command="npm install" />
  </Target>

  <Target Name="PublishRunWebpack" AfterTargets="ComputeFilesToPublish">
    <!-- Build Target: Run webpack dist build -->
    <Message Importance="high" Text="Running npm build..." />
    <Exec WorkingDirectory="$(SpaRoot)" Command="npm run build" />

    <!-- Include the newly-built files in the publish output -->
    <ItemGroup>
      <DistFiles Include="$(SpaRoot)dist\**" />
      <ResolvedFileToPublish Include="@(DistFiles->'%(FullPath)')" Exclude="@(ResolvedFileToPublish)">
        <RelativePath>%(DistFiles.Identity)</RelativePath>
        <CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
      </ResolvedFileToPublish>
    </ItemGroup>
  </Target>

History

Due to the discussion here, it was decided to not be included in the Microsoft owned package.

aspnetcore-vueclimiddleware's People

Contributors

cecilphillip avatar dependabot[bot] avatar eddami avatar eeparker avatar iamxavier avatar john-cheesman avatar johncampionjr avatar lafriks avatar mikebei avatar nick-orr avatar princemanfred avatar t0shik avatar tobbentm avatar tobymosque avatar ttkoma avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

aspnetcore-vueclimiddleware's Issues

NullReferenceException

image

-------------------------------------------------------------------
You may only use the Microsoft .NET Core Debugger (vsdbg) with
Visual Studio Code, Visual Studio or Visual Studio for Mac software
to help you develop and test your applications.
-------------------------------------------------------------------
info: Microsoft.Hosting.Lifetime[0]
      Now listening on: http://[::]:80
Microsoft.Hosting.Lifetime: Information: Now listening on: http://[::]:80
info: Microsoft.Hosting.Lifetime[0]
      Application started. Press Ctrl+C to shut down.
Microsoft.Hosting.Lifetime: Information: Application started. Press Ctrl+C to shut down.
info: Microsoft.Hosting.Lifetime[0]
      Hosting environment: Development
Microsoft.Hosting.Lifetime: Information: Hosting environment: Development
info: Microsoft.Hosting.Lifetime[0]
      Content root path: /app
Microsoft.Hosting.Lifetime: Information: Content root path: /app
fail: Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware[1]
      An unhandled exception has occurred while executing the request.
System.AggregateException: One or more errors occurred. (One or more errors occurred. (Object reference not set to an instance of an object.))
 ---> System.AggregateException: One or more errors occurred. (Object reference not set to an instance of an object.)
 ---> System.NullReferenceException: Object reference not set to an instance of an object.
   at VueCliMiddleware.PidUtils.GetPortPid(UInt16 port)
   at VueCliMiddleware.PidUtils.KillPort(UInt16 port, Boolean force, Boolean tree)
   at VueCliMiddleware.VueCliMiddleware.StartVueCliServerAsync(String sourcePath, String npmScriptName, ILogger logger, Int32 portNumber, ScriptRunnerType runner, String regex)
   --- End of inner exception stack trace ---
   at System.Threading.Tasks.Task`1.GetResultCore(Boolean waitCompletionNotification)
   at System.Threading.Tasks.Task`1.get_Result()
   at VueCliMiddleware.VueCliMiddleware.<>c.<Attach>b__3_0(Task`1 task)
   at System.Threading.Tasks.ContinuationResultTaskFromResultTask`2.InnerInvoke()
   at System.Threading.Tasks.Task.<>c.<.cctor>b__274_0(Object obj)
   at System.Threading.ExecutionContext.RunFromThreadPoolDispatchLoop(Thread threadPoolThread, ExecutionContext executionContext, ContextCallback callback, Object state)
--- End of stack trace from previous location where exception was thrown ---
   at System.Threading.ExecutionContext.RunFromThreadPoolDispatchLoop(Thread threadPoolThread, ExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Threading.Tasks.Task.ExecuteWithThreadLocal(Task& currentTaskSlot, Thread threadPoolThread)
   --- End of inner exception stack trace ---
   at System.Threading.Tasks.Task`1.GetResultCore(Boolean waitCompletionNotification)
   at System.Threading.Tasks.Task`1.get_Result()
   at VueCliMiddleware.TaskTimeoutExtensions.WithTimeout[T](Task`1 task, TimeSpan timeoutDelay, String message)
   at Microsoft.AspNetCore.SpaServices.Extensions.Proxy.SpaProxy.PerformProxyRequest(HttpContext context, HttpClient httpClient, Task`1 baseUriTask, CancellationToken applicationStoppingToken, Boolean proxy404s)
   at Microsoft.AspNetCore.Builder.SpaProxyingExtensions.<>c__DisplayClass2_0.<<UseProxyToSpaDevelopmentServer>b__0>d.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
   at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)
Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware: Error: An unhandled exception has occurred while executing the request.

System.AggregateException: One or more errors occurred. (One or more errors occurred. (Object reference not set to an instance of an object.))
 ---> System.AggregateException: One or more errors occurred. (Object reference not set to an instance of an object.)
 ---> System.NullReferenceException: Object reference not set to an instance of an object.
   at VueCliMiddleware.PidUtils.GetPortPid(UInt16 port)
   at VueCliMiddleware.PidUtils.KillPort(UInt16 port, Boolean force, Boolean tree)
   at VueCliMiddleware.VueCliMiddleware.StartVueCliServerAsync(String sourcePath, String npmScriptName, ILogger logger, Int32 portNumber, ScriptRunnerType runner, String regex)
   --- End of inner exception stack trace ---
   at System.Threading.Tasks.Task`1.GetResultCore(Boolean waitCompletionNotification)
   at System.Threading.Tasks.Task`1.get_Result()
   at VueCliMiddleware.VueCliMiddleware.<>c.<Attach>b__3_0(Task`1 task)
   at System.Threading.Tasks.ContinuationResultTaskFromResultTask`2.InnerInvoke()
   at System.Threading.Tasks.Task.<>c.<.cctor>b__274_0(Object obj)
   at System.Threading.ExecutionContext.RunFromThreadPoolDispatchLoop(Thread threadPoolThread, ExecutionContext executionContext, ContextCallback callback, Object state)
--- End of stack trace from previous location where exception was thrown ---
   at System.Threading.ExecutionContext.RunFromThreadPoolDispatchLoop(Thread threadPoolThread, ExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Threading.Tasks.Task.ExecuteWithThreadLocal(Task& currentTaskSlot, Thread threadPoolThread)
   --- End of inner exception stack trace ---
   at System.Threading.Tasks.Task`1.GetResultCore(Boolean waitCompletionNotification)
   at System.Threading.Tasks.Task`1.get_Result()
   at VueCliMiddleware.TaskTimeoutExtensions.WithTimeout[T](Task`1 task, TimeSpan timeoutDelay, String message)
   at Microsoft.AspNetCore.SpaServices.Extensions.Proxy.SpaProxy.PerformProxyRequest(HttpContext context, HttpClient httpClient, Task`1 baseUriTask, CancellationToken applicationStoppingToken, Boolean proxy404s)
   at Microsoft.AspNetCore.Builder.SpaProxyingExtensions.<>c__DisplayClass2_0.<<UseProxyToSpaDevelopmentServer>b__0>d.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
   at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)
fail: Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware[1]
      An unhandled exception has occurred while executing the request.
System.AggregateException: One or more errors occurred. (One or more errors occurred. (Object reference not set to an instance of an object.))
 ---> System.AggregateException: One or more errors occurred. (Object reference not set to an instance of an object.)
 ---> System.NullReferenceException: Object reference not set to an instance of an object.
   at VueCliMiddleware.PidUtils.GetPortPid(UInt16 port)
   at VueCliMiddleware.PidUtils.KillPort(UInt16 port, Boolean force, Boolean tree)
   at VueCliMiddleware.VueCliMiddleware.StartVueCliServerAsync(String sourcePath, String npmScriptName, ILogger logger, Int32 portNumber, ScriptRunnerType runner, String regex)
   --- End of inner exception stack trace ---
   at System.Threading.Tasks.Task`1.GetResultCore(Boolean waitCompletionNotification)
   at System.Threading.Tasks.Task`1.get_Result()
   at VueCliMiddleware.VueCliMiddleware.<>c.<Attach>b__3_0(Task`1 task)
   at System.Threading.Tasks.ContinuationResultTaskFromResultTask`2.InnerInvoke()
   at System.Threading.Tasks.Task.<>c.<.cctor>b__274_0(Object obj)
   at System.Threading.ExecutionContext.RunFromThreadPoolDispatchLoop(Thread threadPoolThread, ExecutionContext executionContext, ContextCallback callback, Object state)
--- End of stack trace from previous location where exception was thrown ---
   at System.Threading.ExecutionContext.RunFromThreadPoolDispatchLoop(Thread threadPoolThread, ExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Threading.Tasks.Task.ExecuteWithThreadLocal(Task& currentTaskSlot, Thread threadPoolThread)
   --- End of inner exception stack trace ---
   at System.Threading.Tasks.Task`1.GetResultCore(Boolean waitCompletionNotification)
   at System.Threading.Tasks.Task`1.get_Result()
   at VueCliMiddleware.TaskTimeoutExtensions.WithTimeout[T](Task`1 task, TimeSpan timeoutDelay, String message)
   at Microsoft.AspNetCore.SpaServices.Extensions.Proxy.SpaProxy.PerformProxyRequest(HttpContext context, HttpClient httpClient, Task`1 baseUriTask, CancellationToken applicationStoppingToken, Boolean proxy404s)
   at Microsoft.AspNetCore.Builder.SpaProxyingExtensions.<>c__DisplayClass2_0.<<UseProxyToSpaDevelopmentServer>b__0>d.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
   at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)
Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware: Error: An unhandled exception has occurred while executing the request.

System.AggregateException: One or more errors occurred. (One or more errors occurred. (Object reference not set to an instance of an object.))
 ---> System.AggregateException: One or more errors occurred. (Object reference not set to an instance of an object.)
 ---> System.NullReferenceException: Object reference not set to an instance of an object.
   at VueCliMiddleware.PidUtils.GetPortPid(UInt16 port)
   at VueCliMiddleware.PidUtils.KillPort(UInt16 port, Boolean force, Boolean tree)
   at VueCliMiddleware.VueCliMiddleware.StartVueCliServerAsync(String sourcePath, String npmScriptName, ILogger logger, Int32 portNumber, ScriptRunnerType runner, String regex)
   --- End of inner exception stack trace ---
   at System.Threading.Tasks.Task`1.GetResultCore(Boolean waitCompletionNotification)
   at System.Threading.Tasks.Task`1.get_Result()
   at VueCliMiddleware.VueCliMiddleware.<>c.<Attach>b__3_0(Task`1 task)
   at System.Threading.Tasks.ContinuationResultTaskFromResultTask`2.InnerInvoke()
   at System.Threading.Tasks.Task.<>c.<.cctor>b__274_0(Object obj)
   at System.Threading.ExecutionContext.RunFromThreadPoolDispatchLoop(Thread threadPoolThread, ExecutionContext executionContext, ContextCallback callback, Object state)
--- End of stack trace from previous location where exception was thrown ---
   at System.Threading.ExecutionContext.RunFromThreadPoolDispatchLoop(Thread threadPoolThread, ExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Threading.Tasks.Task.ExecuteWithThreadLocal(Task& currentTaskSlot, Thread threadPoolThread)
   --- End of inner exception stack trace ---
   at System.Threading.Tasks.Task`1.GetResultCore(Boolean waitCompletionNotification)
   at System.Threading.Tasks.Task`1.get_Result()
   at VueCliMiddleware.TaskTimeoutExtensions.WithTimeout[T](Task`1 task, TimeSpan timeoutDelay, String message)
   at Microsoft.AspNetCore.SpaServices.Extensions.Proxy.SpaProxy.PerformProxyRequest(HttpContext context, HttpClient httpClient, Task`1 baseUriTask, CancellationToken applicationStoppingToken, Boolean proxy404s)
   at Microsoft.AspNetCore.Builder.SpaProxyingExtensions.<>c__DisplayClass2_0.<<UseProxyToSpaDevelopmentServer>b__0>d.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
   at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)
fail: Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware[1]
      An unhandled exception has occurred while executing the request.
System.AggregateException: One or more errors occurred. (One or more errors occurred. (Object reference not set to an instance of an object.))
 ---> System.AggregateException: One or more errors occurred. (Object reference not set to an instance of an object.)
 ---> System.NullReferenceException: Object reference not set to an instance of an object.
   at VueCliMiddleware.PidUtils.GetPortPid(UInt16 port)
   at VueCliMiddleware.PidUtils.KillPort(UInt16 port, Boolean force, Boolean tree)
   at VueCliMiddleware.VueCliMiddleware.StartVueCliServerAsync(String sourcePath, String npmScriptName, ILogger logger, Int32 portNumber, ScriptRunnerType runner, String regex)
   --- End of inner exception stack trace ---
   at System.Threading.Tasks.Task`1.GetResultCore(Boolean waitCompletionNotification)
   at System.Threading.Tasks.Task`1.get_Result()
   at VueCliMiddleware.VueCliMiddleware.<>c.<Attach>b__3_0(Task`1 task)
   at System.Threading.Tasks.ContinuationResultTaskFromResultTask`2.InnerInvoke()
   at System.Threading.Tasks.Task.<>c.<.cctor>b__274_0(Object obj)
   at System.Threading.ExecutionContext.RunFromThreadPoolDispatchLoop(Thread threadPoolThread, ExecutionContext executionContext, ContextCallback callback, Object state)
--- End of stack trace from previous location where exception was thrown ---
   at System.Threading.ExecutionContext.RunFromThreadPoolDispatchLoop(Thread threadPoolThread, ExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Threading.Tasks.Task.ExecuteWithThreadLocal(Task& currentTaskSlot, Thread threadPoolThread)
   --- End of inner exception stack trace ---
   at System.Threading.Tasks.Task`1.GetResultCore(Boolean waitCompletionNotification)
   at System.Threading.Tasks.Task`1.get_Result()
   at VueCliMiddleware.TaskTimeoutExtensions.WithTimeout[T](Task`1 task, TimeSpan timeoutDelay, String message)
   at Microsoft.AspNetCore.SpaServices.Extensions.Proxy.SpaProxy.PerformProxyRequest(HttpContext context, HttpClient httpClient, Task`1 baseUriTask, CancellationToken applicationStoppingToken, Boolean proxy404s)
   at Microsoft.AspNetCore.Builder.SpaProxyingExtensions.<>c__DisplayClass2_0.<<UseProxyToSpaDevelopmentServer>b__0>d.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
   at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)
Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware: Error: An unhandled exception has occurred while executing the request.

System.AggregateException: One or more errors occurred. (One or more errors occurred. (Object reference not set to an instance of an object.))
 ---> System.AggregateException: One or more errors occurred. (Object reference not set to an instance of an object.)
 ---> System.NullReferenceException: Object reference not set to an instance of an object.
   at VueCliMiddleware.PidUtils.GetPortPid(UInt16 port)
   at VueCliMiddleware.PidUtils.KillPort(UInt16 port, Boolean force, Boolean tree)
   at VueCliMiddleware.VueCliMiddleware.StartVueCliServerAsync(String sourcePath, String npmScriptName, ILogger logger, Int32 portNumber, ScriptRunnerType runner, String regex)
   --- End of inner exception stack trace ---
   at System.Threading.Tasks.Task`1.GetResultCore(Boolean waitCompletionNotification)
   at System.Threading.Tasks.Task`1.get_Result()
   at VueCliMiddleware.VueCliMiddleware.<>c.<Attach>b__3_0(Task`1 task)
   at System.Threading.Tasks.ContinuationResultTaskFromResultTask`2.InnerInvoke()
   at System.Threading.Tasks.Task.<>c.<.cctor>b__274_0(Object obj)
   at System.Threading.ExecutionContext.RunFromThreadPoolDispatchLoop(Thread threadPoolThread, ExecutionContext executionContext, ContextCallback callback, Object state)
--- End of stack trace from previous location where exception was thrown ---
   at System.Threading.ExecutionContext.RunFromThreadPoolDispatchLoop(Thread threadPoolThread, ExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Threading.Tasks.Task.ExecuteWithThreadLocal(Task& currentTaskSlot, Thread threadPoolThread)
   --- End of inner exception stack trace ---
   at System.Threading.Tasks.Task`1.GetResultCore(Boolean waitCompletionNotification)
   at System.Threading.Tasks.Task`1.get_Result()
   at VueCliMiddleware.TaskTimeoutExtensions.WithTimeout[T](Task`1 task, TimeSpan timeoutDelay, String message)
   at Microsoft.AspNetCore.SpaServices.Extensions.Proxy.SpaProxy.PerformProxyRequest(HttpContext context, HttpClient httpClient, Task`1 baseUriTask, CancellationToken applicationStoppingToken, Boolean proxy404s)
   at Microsoft.AspNetCore.Builder.SpaProxyingExtensions.<>c__DisplayClass2_0.<<UseProxyToSpaDevelopmentServer>b__0>d.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
   at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)

Either recieve "TimeoutException" or a blank page. Even though I can navigate to the port vue serve is running on and it loads the client app

Note: that I can run vue serve and the client app works as expected. Similarly when the asp.net core project is running, I can navigate to localhost:8080 and the client app loads as expected.

When I debug my asp.net application, one of two things occur:

  • The page loads, and is a blank screen. No errors in console, all assets load just fine in network tab. (This happens the majority of the time)
  • Perpetually shows the TimeoutException: The vue-cli server did not start listening for requests within the timeout period of 50 seconds. error. This error will persist indefinitely, despite the vue-cli app running just fine.

The log shows:

VueCliMiddleware:Information:   App running at:
  - Local:   http://localhost:8080 
  - Network: http://myip:8080 

Environment:

  • VS2019
  • Asp.net Core 2.2
  • aspnetcore-vueclimiddleware v

Configuration:

            app.UseSpa(spa =>
            {
                spa.Options.SourcePath = "ClientApp";

                if (env.IsDevelopment())
                {
                    spa.UseVueCli(npmScript: "serve", port: 8080); // optional port
                }
            });

Why is this happening and how can I get this to work?

Update to .NET 5.0

Please update too .NET 5.0 and also refresh the sample project. For now after clone its not starting.

'https' parameter isn't available

As mentioned in the documentation, I am using endpoint routing for development. Also, I installed an SSL certificate using mkcert. Now, I am getting an error Failed to proxy the request to http://localhost:8080/

The reason is: Vue.js app is now running at https://localhost:8080

I have tried to include https: true within endpoints.MapToVueCliProxy( "{*path}", new SpaOptions { SourcePath = "ClientApp" }, npmScript: "serve", regex: "Compiled successfully", forceKill: true); but https parameters doesn't exist in MapToVueCliProxy extension method.

I am using VueCliMiddleware V 3.1.1 via NuGet package.

Please advice further to resolve this issue.

Thanks.

Yarn on Windows

On windows OS, yarn was being replaced by npm, but since arguments wan't replaced too, so run UseVueCli with runner: ScriptRunnerType.Yarn on windows throw a exception.

Websocket warning

I'm not sure where in the tool chain this warning is coming from but I'm getting the following warning in the console when I start up the core app.

sockjs.js?9be2:2998 WebSocket connection to 'ws://localhost:65043/sockjs-node/439/hfyqih4v/websocket' failed: WebSocket is closed before the connection is established.

If that's coming from the Vue CLI or Visual Studio let me know and I'll open an issue there.

How to run from command line?

FIXED
Found the errors, I noticed in startup.cs there was a line
npmScript: (System.Diagnostics.Debugger.IsAttached) ? "serve" : null,
I just had to remove the condition and set it to "serve"

Firstly thank you for your great project outstanding work!

I was trying the VueCliSample in visual studio I can press debug and everything seems to work correctly.

Command Line
From command line I run dotnet watch run and npm run serve but I get the error message: The SPA default page middleware could not return the default page '/index.html' because it was not found, and no other middleware handled the request.

So I'm wondering what the command line should be?

Thanks for your time and effort

How can I run the vue process externally?

Hi,

I have a standard asp.net core 3.1 app with vue.js. It's using this to serve the clientapp with hot reload.
However many of the changes I need to make mean that I need to restart the c# side, which also means I have to wait 30 seconds for the vue.js app to compile.

Is there any way to connect to an already running instance of npm serve? I'd like to be able to run it separately so I don't wait so long each time. If it's possible but not documented or implemented, I'm happy to try to contribute a PR.

Thanks,
Steve

.NET Core 3.1 migration, still need app.UseSpa()

Hi,

I'm having issues with a migration from 2.0 to 3.1 running in "production" mode.
A call to app.UseSpa() is still required, or the client files are not served. Is this expected behaviour?

I have app.UseSpaStaticFiles(); and services.AddSpaStaticFiles(opt => { opt.RootPath = "ClientApp/dist"; }); like the readme says.

Does it have something to do with wwwroot? I don't really understand what is meant by this from the readme:
First, be sure to switch Vue Cli or Quasar Cli to output distribution files to wwwroot directly (not dist).

Both MapToVueCliProxy and the old UseProxyToSpaDevelopmentServer work perfectly in "development" mode.

Not working on 3.0

Using the new setup, on 3.0.0-preview7-1 I get this error:

HttpRequestException: Failed to proxy the request to http://localhost:8080/, because the request to the proxy target failed. Check that the proxy target server is running and accepting requests to http://localhost:8080/.

The last VueCliMiddleware console message is: VueCliMiddleware: Information: Starting server on port 8080...

I can run serve commands just fine and the app runs and loads.

Also noticing that the build output does not appear in the output console in VS anymore?

Version 3.1.2 Hot Reloading is not working. But worked with Version 3.1.1 as Project Reference

Hi,

thank you for your're last NuGet Update 3.1.2 where the options for wsl and https are available now.
But now Hot reoloading is not working.
I tried my sample project with NuGet 3.1.2 and 3.1.1 as Project reference.

And why do you removed the "mkcert" part from Readme.md here in GitHub?

Here is my startup.cs:
endpoints.MapToVueCliProxy( pattern: "en/{*path}", options: new SpaOptions { SourcePath = "ClientApp" }, npmScript: (System.Diagnostics.Debugger.IsAttached) ? "serve" : null, port: 8080, https: true, runner: ScriptRunnerType.Npm, regex: "Compiled successfully", forceKill: true //wsl: false );
And here my vue.config.cs
`const fs = require('fs')

module.exports = {
publicPath: '/en/',
devServer: {
https: {
key: fs.readFileSync('../certs/localhost+3-key.pem'),
cert: fs.readFileSync('../certs/localhost+3.pem'),
}
}
};`

index.html?

Hi,

excellent work with this tool, i'm using this in an old project with net core 2.2, but now i'm having issues implementing it with core 3.1.

i'm creating a new project, it's brand new, the thing is that i don't have a index file at the root, the only index file is at ClientApp/dist/index.html and when i deploy the project to a IIS server, it doesn't work, it says that it couldn't find any index.html.

any suggestion?

Regards.

When run it asks authentication

When I try to start provided VueCliSample it show me auth window in browser though Anonymous Authentication is enabled for this project.

Use with https

Hey, I feel like there is a problem when using https locally.

Here is how I configured the project in startup:

app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseSpaStaticFiles();
app.UseSpa(spa =>
{
    spa.Options.SourcePath = "ClientApp";

    if (env.IsDevelopment())
    {
        spa.UseVueCli(npmScript: "serve", port: 8085);
    }
});

It then keeps trying to Get on https://10.0.1.36:8085/sockjs-node/info, but the https address doesn't exist.
However, if I do a GET on http://10.0.1.36:8085/sockjs-node/info (http, not https), then it responds correctly.

How can i fix this ?

See the errors I get in the screenshot.

screenshot

[Upstream] Specified port is completely ignored

I just upgraded my dev box, reinstalled VS, Node, and vue-cli and can no longer get my client app to run with vueclimiddleware.

It seems like the specified port is no longer used when the application actually launched. I have specified port 8080, but it launches under a random port each time.

HTTPS Support

The main issue is if the dotnet core app is using https and vue isn't the hot reload doesn't work.

It's possible to setup vue-cli to work with https, I've added the option to set https & added instructions to the README.md on how to generate certificates for the dev server. #53

Just note that having a dev environment being https is important to move the bar. it's 2020 like cmon why is security not the default yet.

For .net core 3

.Net core 3 is still in preview mode. So are we going to wait till then?

.NET Core Hosting Problem

Hello,
I am trying to use cli middleware and getting error like :

The "path" argument must be of type string. Received type number.

I will share my project folder structure below to show any hint for a solution

Here you can see the folder structure. src folder is my code base and public folder is hosting folder.

For any reason i have place a dist folder in wwwroot but maybe is unnecessary.

image

In my csproj file i have set the values as you mentioned according to my folder structure

<PropertyGroup>
        <SpaRoot>src\</SpaRoot>
        <DefaultItemExcludes>$(DefaultItemExcludes);node_modules\**</DefaultItemExcludes>
</PropertyGroup>

Any idea or fix suggestion for the solution ?

Production directs to 404.

Production seemingly fails with 404 while localhost works fine.

Swagger path works,
APIs all work.
It's just the SPA failing to work.

This entire project is dockerised and deployed via Kubernetes.

The question is, is there a problem with the DI pipeline I've configured? And if so, what should be removed, added or reorganised?

Here's my program.cs:

using System;
using System.Net;
using System.Security.Cryptography.X509Certificates;
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Hosting;

namespace Nozomi.Web2
{
    public class Program
    {
        public static void Main(string[] args)
        {
            CreateWebHostBuilder(args).Build().Run();
        }

        static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
            WebHost.CreateDefaultBuilder(args)
                .UseKestrel(options =>
                {
                    options.AddServerHeader = false;

                    var environment = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT");
                    var isDevelopment = environment == Environments.Development;
                    if (!System.Diagnostics.Debugger.IsAttached && !isDevelopment)
                    {
                        var hasHttpsPortConfigured = int.TryParse(Environment.GetEnvironmentVariable("HTTPS_PORT")
                            , out var port);
                        if (!hasHttpsPortConfigured)
                        {
                            port = 5001; // Default port

                            Console.WriteLine("HTTPS port not configured! Self configuring to 5001.");
                        }
                        
                        var certPath = Environment.GetEnvironmentVariable("SSLCERT_PATH");
                        if (string.IsNullOrEmpty(certPath)) {
                            certPath = "xxxxx.pfx"; // Deefault

                            Console.WriteLine("SSLCERT_PATH not configured! Self configuring to xxxxx.pfx");
                        }
                        
                        var certPassword = Environment.GetEnvironmentVariable("SSLCERT_PASSWORD");
                        if (string.IsNullOrEmpty(certPassword))
                        {
                            certPassword = "xxxxxx"; // Deefault

                            Console.WriteLine("SSLCERT_PASSWORD not configured! Self configuring to the defaults.");
                        }
                        
                        options.Listen(IPAddress.Any, port, listenOptions =>
                        {
                            var cert = new X509Certificate2(certPath, certPassword);

                            listenOptions.UseHttps(cert);
                        });
                    }
                })
                .UseStartup<Startup>();
    }
}

Here's my Startup:

using System;
using System.IO;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.HttpOverrides;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.SpaServices;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.FileProviders;
using Microsoft.Extensions.Hosting;
using Newtonsoft.Json;
using Nozomi.Preprocessing;
using Nozomi.Preprocessing.Filters;
using Nozomi.Web2.Extensions;
using Swashbuckle.AspNetCore.SwaggerUI;
using VueCliMiddleware;

namespace Nozomi.Web2
{
    public class Startup
    {
        public Startup(IConfiguration configuration, IWebHostEnvironment environment)
        {
            Configuration = configuration;
            Environment = environment;
        }

        public static IConfiguration Configuration { get; set; }

        public static IWebHostEnvironment Environment { get; set; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.Configure<CookiePolicyOptions>(options =>
            {
                // This lambda determines whether user consent for non-essential cookies is needed for a given request.
                options.CheckConsentNeeded = context => false;
                options.MinimumSameSitePolicy = SameSiteMode.None;
            });
            services.Configure<ForwardedHeadersOptions>(options =>
            {
                options.KnownNetworks.Clear();
                options.KnownProxies.Clear();
                
                // https://github.com/IdentityServer/IdentityServer4/issues/1331
                options.ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;
                options.RequireHeaderSymmetry = false;
                options.ForwardLimit = 2;
            });

            services.AddOptions();

            services.AddResponseCompression();

            services.AddDbContextInjections();

            services.AddMemoryCache();

            services.AddHealthChecks();

            // In production, the Vue files will be served from this directory
            services.AddSpaStaticFiles(configuration =>
            {
                configuration.RootPath = "ClientApp/dist";
            });

            services.AddControllers(options =>
                {
                    options.Filters.Add(typeof(HttpGlobalExceptionFilter));
                })
                .AddNewtonsoftJson(options =>
                {
                    options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
                })
                .SetCompatibilityVersion(CompatibilityVersion.Version_3_0);

            // Add AddRazorPages
            // services.AddRazorPages();

            if (Environment.IsProduction())
            {
                services.AddHsts(opt =>
                {
                    opt.Preload = true;
                    opt.IncludeSubDomains = true;
                    opt.MaxAge = TimeSpan.FromDays(60);
                });
            }

            // https://docs.microsoft.com/en-us/aspnet/core/security/enforcing-ssl?view=aspnetcore-3.1&tabs=visual-studio#options
            // Calling AddHttpsRedirection is only necessary to change the values of HttpsPort or RedirectStatusCode.
            services.AddHttpsRedirection(options =>
            {
                // options.RedirectStatusCode = StatusCodes.Status307TemporaryRedirect;
                
                if (!Environment.IsProduction())
                    options.HttpsPort = 5001;
            });

            // UoW-Repository injection
            services.ConfigureRepoLayer();

            // Service layer injections
            services.ConfigureInfra();

            // Swashbuckle Swagger
            services.ConfigureSwagger();

            // Auth
            services.ConfigureNozomiAuth();
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler("/Error");
                // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
                app.UseHsts();
                
                app.UseResponseCompression();
            }
            
            // Always enforce HTTPS for development and production
            app.UseHttpsRedirection();

            // ref: https://github.com/aspnet/Docs/issues/2384
            app.UseForwardedHeaders();

            app.UseAuthentication();

            app.UseStaticFiles();
            app.UseSpaStaticFiles();

            app.UseCookiePolicy();

            // Enable middleware to serve generated Swagger as a JSON endpoint.
            app.UseSwagger();

            // Enable middleware to serve swagger-ui (HTML, JS, CSS, etc.),
            // specifying the Swagger JSON endpoint.
            app.UseSwaggerUI(c =>
            {
                c.DocumentTitle = "Nozomi API";
                // https://stackoverflow.com/questions/39116047/how-to-change-base-url-of-swagger-in-asp-net-core
                c.RoutePrefix = "docs";
                c.SwaggerEndpoint("/swagger/" + 
                                  GlobalApiVariables.CURRENT_API_VERSION + "/swagger.json", "Nozomi API");
                c.IndexStream = () => GetType().Assembly
                    .GetManifestResourceStream("Nozomi.Web2.Resources.Index.html"); // requires file to be added as an embedded resource
                
                c.DocExpansion(DocExpansion.None);
                c.EnableDeepLinking();
                c.EnableFilter();
            });

            app.UseRouting();

            app.UseAuthorization();

            app.UseEndpoints(endpoints =>
            {
                // endpoints.MapControllerRoute(
                //     name: "default",
                //     pattern: "{controller}/{action=Index}/{id?}");
                endpoints.MapControllers();

                // Health check up!!!
                // https://docs.microsoft.com/en-us/aspnet/core/host-and-deploy/health-checks?view=aspnetcore-3.0#basic-health-probe
                // endpoints.MapHealthChecks("/health");
                
                if (env.IsDevelopment())
                    endpoints.MapToVueCliProxy(
                        "{*path}",
                        new SpaOptions { SourcePath = "ClientApp" },
                        System.Diagnostics.Debugger.IsAttached ? "serve" : null,
                        regex: "Compiled successfully",
                        forceKill: true
                    );
                // else
                //     endpoints.MapFallbackToFile("index.html");

                // Add MapRazorPages if the app uses Razor Pages. Since Endpoint Routing includes support for many frameworks, adding Razor Pages is now opt -in.
                // endpoints.MapRazorPages();
            });

            // app.UseSpa(spa =>
            // {
            //     spa.Options.DefaultPage = "/index.html";
            //     spa.Options.SourcePath = "ClientApp";
            // });
        }
    }
}

UseSpaStaticFiles() from embedded resources

Is it possible to configure asp.net core to serve all files needed for SPA from the resources embedded in the assembly? I need to produce a single file application and we can't distribute any other files/directory apart application executable file.

Launch IIS Error .net core 3.1

image

Hello. In order to work on virtual directories, I created my own site in local iis and linked my project there. When I run it in development mode, I get the error in the picture. But it works when I run it in production mode. Of course, the changes I made in the project do not appear on the screen since it is in production mode.

image

Https support

Hey,

I enabled https, even in local yes and I get a lot of the following :

Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at https://192.168.1.18:8085/sockjs-node/info?t=1549978713174. (Reason: CORS request did not succeed)

The thing is that even it wasn't blocked, it wouldn't be correct as it seems like the spa listens on http 8085 only, not https.

Here is a bit of my StartUp.cs:

        app.UseHttpsRedirection();
        app.UseStaticFiles();
        app.UseSpaStaticFiles();
        app.UseSpa(spa =>
        {
            spa.Options.SourcePath = "ClientApp";

            if (env.IsDevelopment())
            {
                spa.UseVueCli(npmScript: "serve", port: 8085);
            }
        });

What should I do?

On mozilla

screenshot

On chrome
screenshot 2

CORS Support

On behalf of @Ethan0007

Hi,

I would like to ask any idea about on how can i enable CORS on this setup?
I already added addCors in my configureservice:
image

and UserCors in Configure:
image
image

But when i put my script in separate server i still got this issue:
image
image

this is my request:
image
image

this my controller:
image
image

Thanks!

[Upstream] Silence webpack progress

With vue-cli 3.11.0 the progress is printed like that:

fail: VueCliMiddleware[0]
      <s> [webpack.Progress] 12% building 24/28 modules 4 active C:\dev\UI\node_modules\cache-loader\dist\cjs.js??ref--12-0!C:\dev\UI\node_modules\babel-loader\lib\index.js!C:\dev\UI\node_modules\eslint-loader\index.js??ref--13-0!C:\dev\UI\src\silent-renew-oidc.js


fail: VueCliMiddleware[0]
      <s> [webpack.Progress] 12% building 24/29 modules 5 active C:\dev\UI\node_modules\webpack-dev-server\node_modules\strip-ansi\index.js


fail: VueCliMiddleware[0]
      <s> [webpack.Progress] 13% building 25/29 modules 4 active C:\dev\UI\node_modules\webpack-dev-server\node_modules\strip-ansi\index.js


fail: VueCliMiddleware[0]
      <s> [webpack.Progress] 13% building 26/29 modules 3 active C:\dev\UI\node_modules\cache-loader\dist\cjs.js??ref--12-0!C:\dev\UI\node_modules\babel-loader\lib\index.js!C:\dev\UI\node_modules\eslint-loader\index.js??ref--13-0!C:\dev\UI\src\silent-renew-oidc.js


fail: VueCliMiddleware[0]
      <s> [webpack.Progress] 13% building 26/30 modules 4 active C:\dev\UI\node_modules\querystring-es3\decode.js

... and so on

Works fine with vue-cli 3.10.0.
VueCliMiddleware 2.2.x

ScriptRunnerType.Yarn not working

I tried to use yarn instead of npm as scriptrunnertype under windows. And found out it is not working ;)
I get message: Usage: npm after dotnet run.

My Configuration:
spa.UseVueCli(npmScript: "serve", port: 8080, regex: "Compiled ", runner: ScriptRunnerType.Yarn);

I think i found the related code where npm is used hard coded even when yarn is configured:
https://github.com/EEParker/aspnetcore-vueclimiddleware/blob/master/src/VueCliMiddleware/Util/ScriptRunner.cs:53
completeArguments = $"/c npm {completeArguments}";

Production environment still doesn't work

I have a production environment for you to look at:
Nozomi

According to your latest documentation and sample, it still wouldn't want to work.

Https uses the default AddHttpsRedirection DI along with Kubernetes' LB + Cloudflare's SSL.

Production now tosses a 404.

Am I missing anything? I can provide you any other information, just let me know! Problem right now is that I have no idea what is the root cause of production's failure right now.

using System;
using System.IO;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.HttpOverrides;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.SpaServices;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.FileProviders;
using Microsoft.Extensions.Hosting;
using Newtonsoft.Json;
using Nozomi.Preprocessing;
using Nozomi.Preprocessing.Filters;
using Nozomi.Web2.Extensions;
using Swashbuckle.AspNetCore.SwaggerUI;
using VueCliMiddleware;

namespace Nozomi.Web2
{
    public class Startup
    {
        public Startup(IConfiguration configuration, IWebHostEnvironment environment)
        {
            Configuration = configuration;
            Environment = environment;
        }

        public static IConfiguration Configuration { get; set; }

        public static IWebHostEnvironment Environment { get; set; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.Configure<CookiePolicyOptions>(options =>
            {
                // This lambda determines whether user consent for non-essential cookies is needed for a given request.
                options.CheckConsentNeeded = context => false;
                options.MinimumSameSitePolicy = SameSiteMode.None;
            });
            services.Configure<ForwardedHeadersOptions>(options =>
            {
                options.KnownNetworks.Clear();
                options.KnownProxies.Clear();
                
                // https://github.com/IdentityServer/IdentityServer4/issues/1331
                options.ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;
                options.RequireHeaderSymmetry = false;
                options.ForwardLimit = 2;
            });

            services.AddOptions();

            services.AddResponseCompression();

            services.AddDbContextInjections();

            services.AddMemoryCache();

            services.AddHealthChecks();

            // In production, the Vue files will be served from this directory
            services.AddSpaStaticFiles(configuration =>
            {
                configuration.RootPath = "ClientApp/dist";
            });

            services.AddControllers(options =>
                {
                    options.Filters.Add(typeof(HttpGlobalExceptionFilter));
                })
                .AddNewtonsoftJson(options =>
                {
                    options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
                })
                .SetCompatibilityVersion(CompatibilityVersion.Version_3_0);

            // Add AddRazorPages
            services.AddRazorPages();

            if (Environment.IsProduction())
            {
                services.AddHsts(opt =>
                {
                    opt.Preload = true;
                    opt.IncludeSubDomains = true;
                    opt.MaxAge = TimeSpan.FromDays(60);
                });
            }

            // https://docs.microsoft.com/en-us/aspnet/core/security/enforcing-ssl?view=aspnetcore-3.1&tabs=visual-studio#options
            // Calling AddHttpsRedirection is only necessary to change the values of HttpsPort or RedirectStatusCode.
            services.AddHttpsRedirection(options =>
            {
                options.RedirectStatusCode = StatusCodes.Status307TemporaryRedirect;
                
                // if (Environment.IsProduction())
                //     options.HttpsPort = 5001;
            });

            // UoW-Repository injection
            services.ConfigureRepoLayer();

            // Service layer injections
            services.ConfigureInfra();

            // Swashbuckle Swagger
            services.ConfigureSwagger();

            // Auth
            services.ConfigureNozomiAuth();
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler("/Error");
                // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
                app.UseHsts();
                
                app.UseResponseCompression();
            }
            
            // Always enforce HTTPS for development and production
            app.UseHttpsRedirection();

            // ref: https://github.com/aspnet/Docs/issues/2384
            app.UseForwardedHeaders();

            app.UseAuthentication();

            app.UseStaticFiles();
            app.UseSpaStaticFiles();

            app.UseCookiePolicy();

            // Enable middleware to serve generated Swagger as a JSON endpoint.
            app.UseSwagger();

            // Enable middleware to serve swagger-ui (HTML, JS, CSS, etc.),
            // specifying the Swagger JSON endpoint.
            app.UseSwaggerUI(c =>
            {
                c.DocumentTitle = "Nozomi API";
                // https://stackoverflow.com/questions/39116047/how-to-change-base-url-of-swagger-in-asp-net-core
                c.RoutePrefix = "docs";
                c.SwaggerEndpoint("/swagger/" + 
                                  GlobalApiVariables.CURRENT_API_VERSION + "/swagger.json", "Nozomi API");
                c.IndexStream = () => GetType().Assembly
                    .GetManifestResourceStream("Nozomi.Web2.Resources.Index.html"); // requires file to be added as an embedded resource
                
                c.DocExpansion(DocExpansion.None);
                c.EnableDeepLinking();
                c.EnableFilter();
            });

            app.UseRouting();

            app.UseAuthorization();

            app.UseEndpoints(endpoints =>
            {
                // endpoints.MapControllerRoute(
                //     name: "default",
                //     pattern: "{controller}/{action=Index}/{id?}");
                endpoints.MapControllers();

                // Health check up!!!
                // https://docs.microsoft.com/en-us/aspnet/core/host-and-deploy/health-checks?view=aspnetcore-3.0#basic-health-probe
                // endpoints.MapHealthChecks("/health");
                
                if (env.IsDevelopment())
                    endpoints.MapToVueCliProxy(
                        "{*path}",
                        new SpaOptions { SourcePath = "ClientApp" },
                        System.Diagnostics.Debugger.IsAttached ? "serve" : null,
                        regex: "Compiled successfully",
                        forceKill: true
                    );
                else
                    endpoints.MapFallbackToFile("index.html");

                // Add MapRazorPages if the app uses Razor Pages. Since Endpoint Routing includes support for many frameworks, adding Razor Pages is now opt -in.
                endpoints.MapRazorPages();
            });

            app.UseSpa(spa =>
            {
                spa.Options.DefaultPage = "/index.html";
                spa.Options.SourcePath = "ClientApp";
            });
        }
    }
}

Route Pattern not working

Hi !

I'm using the version 3.1.1.

I define the MapToVueCliProxy route pattern as follow

endpoints.MapToVueCliProxy( "booking", new SpaOptions { SourcePath = "../Kronos.BookingClient" }, npmScript: System.Diagnostics.Debugger.IsAttached ? "serve" : null, regex: "Compiled successfully", forceKill: true, https: true);

My website continue to serve the vuejs project on root (https://localhost:44389/ instead of https://localhost:44389/booking)

I also tried

endpoints.MapToVueCliProxy( "booking/{*path}", new SpaOptions { SourcePath = "../Kronos.BookingClient" }, npmScript: System.Diagnostics.Debugger.IsAttached ? "serve" : null, regex: "Compiled successfully", forceKill: true, https: true);

I suppose it is not a normal behavior. Am I wrong ?

Why recommend endpoint routing?

This is entirely a question. First, this is what I get with dotnet new angular in ASP.NET Core 3.1:

// other stuff before this
if (!env.IsDevelopment())
{
    app.UseSpaStaticFiles();
}

app.UseRouting();

app.UseEndpoints(endpoints =>
{
    endpoints.MapControllerRoute(
        name: "default",
        pattern: "{controller}/{action=Index}/{id?}");
});

app.UseSpa(spa =>
{
    // To learn more about options for serving an Angular SPA from ASP.NET Core,
    // see https://go.microsoft.com/fwlink/?linkid=864501

    spa.Options.SourcePath = "ClientApp";

    if (env.IsDevelopment())
    {
        spa.UseAngularCliServer(npmScript: "start");
    }
});

The way I see it, using endpoint routing in this middleware doesn’t bring any benefits for common use cases. However, it adds quite some confusion by deviating from established patterns. I understand that it enables advanced use cases like requiring authentication for the SPA.

I think the recommended configuration should still be UseVueCli.

I think forcekill should be true by default

Had an issue where running a different solution using this library served pages from the previous solution (also using this library).

After a bit of confusion and manually killing the node processes realised that forcekill parameter on MapToVueCliProxy resolves this.

Would agree that this should be true by default to prevent my silly mistake. Thoughts?

Node Process Not Being Killed

I'm having an issue with node processes from previously stopped debug sessions not being killed on next launch. I submitted pull request #32 to allow you to optionally specify a force kill option (which fixed my issue) but was told it's good form to open an issue along with it. Is there possibly something I'm missing? Thanks for the great work!

Not able to publish on PCF

I am trying to publish the default project on PCF. After published I could not found index.html and others file.

Even I am not able to publish on IIS as well. Pls, help.

HMR Works But Page Doesn't Reload

I have VueCliMiddleware mostly working in our app with one small exception: it doesn't automatically refresh the page. When I save a Vue file I can see in the output that vue/webpack has recompiled the app but the page doesn't automatically refresh. If I manually refresh the changes appear just fine.

The sample application works and I used the code from it's startup class and project file. Any thoughts on where that disconnect might be or what to look at?

Conflict with swagger

Hello, open the Swagger page and go to the single page of the Vue cli process. I don't know why this is.

it’s not clear how to run the example

could you make an example that you can run and see the result.
I downloaded the project, run it, and nothing happens.
the part with {* path} is not clear, what should I enter there? I write for the place {* path} - "index.html", but this does not work :(
I work with Vue Cli, for asp core 3
help me please

[#ask] Can we use parent folder for ClientApp

I have sample folder strucure for the app

- Dashboard
- - - Backend 
- - - - - - ClientApp
- - - - - - Controllers
------etc

How to achieve folder structure like this
(ClientApp to upper folder align with Backend folder)

- Dashboard
- - - ClientApp 
- - - Backend 
- - - - - - Controllers
------etc

I just try change "ClientApp" to "../Frontend" does not work

SocketException: No connection could be made because the target machine actively refused it.

I've wired up a aspnet core 3.1 app and Vue 2.6 following the samples here. I am able to get updates in the browser when I make changes to my vue components most of the time. But sometimes (seems random) I will lose connection to the web socket. My VS debugger is still attached and I can still hit my API endpoints, but anything through the proxy fails with SocketException: No connection could be made because the target machine actively refused it.

If I restart my debugger it starts to work again, but then will randomly drop off at some point.

my endpoints in the startup file:

 app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();

#if DEBUG
                if (System.Diagnostics.Debugger.IsAttached)
                    endpoints.MapToVueCliProxy("{*path}", new SpaOptions { SourcePath = "ClientApp" }, "serve", regex: "running at");//"Compiled successfully"
                else
#endif
                    // note: output of vue cli should be wwwroot
                    endpoints.MapFallbackToFile("index.html");


            });

Any ideas?

Doesn't seem to do anything?

I'm trying to use this, but when running my project it doesn't seem like vue serve is called at all. It just runs the vanilla asp.net application with an empty window. It completely ignores the port# entered as well, nothing is served up on that port.

If I open the vue ui and serve from there it works as expected.

Error when behind corporate proxy on Windows: Self-referential requests to proxy are forbidden

Problem description:

After upgrading a project from version 3.0.0 to version 3.1.2 of vueclimiddleware, I get the following response when accessing the app via its reverse proxy URL at https://localhost:/ with an HTTP 200 status:

<HTML><TITLE>Forbidden</TITLE><H1>Self-referential requests to proxy are forbidden</H1>Self-referential requests to this proxy server are forbidden</HTML>

Steps to reproduce

I reproduced this problem on Windows 10 2004, .NET Core 3.1

  • Being behind a corporate proxy, I have set the environment variables HTTP_PROXY=http://<proxy>:<port> and NO_PROXY=localhost .
  • Start the sample app in /samples/VueCliSample in this repo.

The browser opens at https://localhost:44323/ and displays the error message from above.

Workaround

The problem is caused by .NET Core 3.1 apparently ignoring the NO_PROXY variable and probably needs to be fixed by the .NET team where a similar issue is tracked for the Angular middleware (dotnet/aspnetcore#14392).

As a workaround, the HTTP_PROXY can be unset in the launchSettings.json file:

"profiles": {
    "IIS Express": {
      "commandName": "IISExpress",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development",
        "NO_PROXY": "localhost",
        "HTTP_PROXY": ""
      }
    },
    "webapp": {
      "commandName": "Project",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      },
      "applicationUrl": "http://localhost:8080"
    }
  }

I'd suggest adding this to the documentation / wiki as a know issue

Not working with publicpath

This doesn't appear to work well when using prefix'ed path. app.Map

The client-side routing can't be refreshed

Asp.net Core 2.1 and VueCliMiddleware 2.1

Hi,

I just want to share something on my development issue, i have asp.net core 2.1 and and using vue cli 3, I'm having issue when start debugging of the project and the issue is not consistent sometimes it work and sometimes it fails. please see screenshot below:

image

Thank you!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.