Getting Started With Vue.js And .NET Core 3

Web front-end framework is emerging nowadays. We all know about the giant names, such as Angular, React, and Vue. Angular provides two-way data binding when React has the one-direction data flow and Vue.js has both of them.
 

What is Vue Js?

 
Vue is a progressive framework for building modern user interfaces. It is suitable for SPA (Single Page Applications) which is a combination of modern tools and libraries. It is a JavaScript framework.
 

Why does the developer choose Vue.js?

 
Vue is an approachable, versatile, and performant JavaScript framework. It helps to build a more maintainable and testable code base.
 
Install Vue.js globally.
  1. npm install -g @vue/cli  
Check version of Vue.js   
  1. vue --version  

Install .NET Core 3 SDK 

 
Download the latest version of this SDK and install it.
 
Vue.js And .NET Core 3
 
Let's start with .NET Core 3 and Vue.js.
 
Create ASP.NET Core 3 web application project using API template.
  
Vue.js And .NET Core 3
 
It takes a few minutes to create an API project. Once completed, go to the package manager console and write the following command. Make sure the selected project is API project. After that, it will create one folder called client-app. 
  1. vue create client-app   
Vue.js And .NET Core 3
 
Add Microsoft.AspNetCore.SpaServices.Extensions package from NuGet Package or just replace the csproj file with below one. So, it will automatically add this package. 
  1. <Project Sdk="Microsoft.NET.Sdk.Web">  
  2.   
  3.   <PropertyGroup>  
  4.     <TargetFramework>netcoreapp3.0</TargetFramework>  
  5.     <SpaRoot>client-app\</SpaRoot>  
  6.     <DefaultItemExcludes>$(DefaultItemExcludes);$(SpaRoot)node_modules\**</DefaultItemExcludes>  
  7.     <TypeScriptCompileBlocked>true</TypeScriptCompileBlocked>  
  8.     <TypeScriptToolsVersion>Latest</TypeScriptToolsVersion>  
  9.     <IsPackable>false</IsPackable>  
  10.   </PropertyGroup>  
  11.   
  12.     
  13.   <Target Name="PublishRunWebpack" AfterTargets="ComputeFilesToPublish">  
  14.     
  15.     <Exec WorkingDirectory="$(SpaRoot)" Command="npm install" />  
  16.     <Exec WorkingDirectory="$(SpaRoot)" Command="npm run build" />  
  17.   
  18.     
  19.     <ItemGroup>  
  20.       <DistFiles Include="$(SpaRoot)dist\**" />  
  21.       <ResolvedFileToPublish Include="@(DistFiles->'%(FullPath)')" Exclude="@(ResolvedFileToPublish)">  
  22.         <RelativePath>%(DistFiles.Identity)</RelativePath>  
  23.         <CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>  
  24.       </ResolvedFileToPublish>  
  25.     </ItemGroup>  
  26.   </Target>  
  27.     
  28. <ItemGroup>  
  29.     <PackageReference Include="Microsoft.AspNetCore.SpaServices.Extensions" Version="3.0.0-preview6.19307.2" />  
  30.   </ItemGroup>  
  31.   
  32.   <ItemGroup>  
  33.      
  34.     <Content Remove="$(SpaRoot)**" />  
  35.     <None Remove="$(SpaRoot)**" />  
  36.     <None Include="$(SpaRoot)**" Exclude="$(SpaRoot)node_modules\**" />  
  37.   </ItemGroup>  
  38.   
  39.   <Target Name="DebugEnsureNodeEnv" BeforeTargets="Build" Condition=" '$(Configuration)' == 'Debug' And !Exists('$(SpaRoot)node_modules') ">  
  40.       
  41.     <Exec Command="node --version" ContinueOnError="true">  
  42.       <Output TaskParameter="ExitCode" PropertyName="ErrorCode" />  
  43.     </Exec>  
  44.     <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." />  
  45.     <Message Importance="high" Text="Restoring dependencies using 'npm'. This may take several minutes..." />  
  46.     <Exec WorkingDirectory="$(SpaRoot)" Command="npm install" />  
  47.   </Target>  
  48.   
  49.   
  50. </Project>  
Let us now inject the middleware at startup file and add connection.cs file for port forwrding.
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Threading.Tasks;  
  5. using Microsoft.AspNetCore.Builder;  
  6. using Microsoft.AspNetCore.Hosting;  
  7. using Microsoft.AspNetCore.HttpsPolicy;  
  8. using Microsoft.AspNetCore.Mvc;  
  9. using Microsoft.Extensions.Configuration;  
  10. using Microsoft.Extensions.DependencyInjection;  
  11. using Microsoft.Extensions.Hosting;  
  12. using Microsoft.Extensions.Logging;  
  13. using VueDemoWithAsp.NetCore.VueCoreConnection;  
  14.   
  15. namespace VueDemoWithAsp.NetCore  
  16. {  
  17.     public class Startup  
  18.     {  
  19.         public Startup(IConfiguration configuration)  
  20.         {  
  21.             Configuration = configuration;  
  22.         }  
  23.   
  24.         public IConfiguration Configuration { get; }  
  25.   
  26.         // This method gets called by the runtime. Use this method to add services to the container.  
  27.         public void ConfigureServices(IServiceCollection services)  
  28.         {  
  29.             services.AddControllers();  
  30.             // connect vue app - middleware  
  31.             services.AddSpaStaticFiles(options => options.RootPath = "client-app/dist");  
  32.         }  
  33.   
  34.         // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.  
  35.         public void Configure(IApplicationBuilder app, IWebHostEnvironment env)  
  36.         {  
  37.             if (env.IsDevelopment())  
  38.             {  
  39.                 app.UseDeveloperExceptionPage();  
  40.             }  
  41.             else  
  42.             {  
  43.                 // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.  
  44.                 app.UseHsts();  
  45.             }  
  46.   
  47.             app.UseHttpsRedirection();  
  48.   
  49.             app.UseRouting();  
  50.   
  51.             app.UseAuthorization();  
  52.   
  53.             app.UseEndpoints(endpoints =>  
  54.             {  
  55.                 endpoints.MapControllers();  
  56.             });  
  57.   
  58.             // use middleware and launch server for Vue  
  59.             app.UseSpaStaticFiles();  
  60.             app.UseSpa(spa =>  
  61.             {  
  62.                 spa.Options.SourcePath = "client-app";  
  63.                 if (env.IsDevelopment())  
  64.                 {  
  65.                       
  66.                     spa.UseVueDevelopmentServer();  
  67.                 }  
  68.             });  
  69.         }  
  70.     }  
  71. }  
The new file should look like below.
  1. using Microsoft.AspNetCore.Builder;  
  2. using Microsoft.AspNetCore.SpaServices;  
  3. using Microsoft.Extensions.DependencyInjection;  
  4. using Microsoft.Extensions.Logging;  
  5. using System;  
  6. using System.Diagnostics;  
  7. using System.IO;  
  8. using System.Linq;  
  9. using System.Net.NetworkInformation;  
  10. using System.Runtime.InteropServices;  
  11. using System.Threading.Tasks;  
  12.   
  13. namespace VueDemoWithAsp.NetCore.VueCoreConnection  
  14. {  
  15.     public static class Connection  
  16.     {  
  17.          
  18.         private static int Port { get; } = 8080;  
  19.         private static Uri DevelopmentServerEndpoint { get; } = new Uri($"http://localhost:{Port}");  
  20.         private static TimeSpan Timeout { get; } = TimeSpan.FromSeconds(60);  
  21.          
  22.         private static string DoneMessage { get; } = "DONE  Compiled successfully in";  
  23.   
  24.         public static void UseVueDevelopmentServer(this ISpaBuilder spa)  
  25.         {  
  26.             spa.UseProxyToSpaDevelopmentServer(async () =>  
  27.             {  
  28.                 var loggerFactory = spa.ApplicationBuilder.ApplicationServices.GetService<ILoggerFactory>();  
  29.                 var logger = loggerFactory.CreateLogger("Vue");  
  30.   
  31.                 if (IsRunning())  
  32.                 {  
  33.                     return DevelopmentServerEndpoint;  
  34.                 }  
  35.   
  36.                 
  37.                 var isWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows);  
  38.                 var processInfo = new ProcessStartInfo  
  39.                 {  
  40.                     FileName = isWindows ? "cmd" : "npm",  
  41.                     Arguments = $"{(isWindows ? "/c npm " : "")}run serve",  
  42.                     WorkingDirectory = "client-app",  
  43.                     RedirectStandardError = true,  
  44.                     RedirectStandardInput = true,  
  45.                     RedirectStandardOutput = true,  
  46.                     UseShellExecute = false,  
  47.                 };  
  48.                 var process = Process.Start(processInfo);  
  49.                 var tcs = new TaskCompletionSource<int>();  
  50.                 _ = Task.Run(() =>  
  51.                 {  
  52.                     try  
  53.                     {  
  54.                         string line;  
  55.                         while ((line = process.StandardOutput.ReadLine()) != null)  
  56.                         {  
  57.                             logger.LogInformation(line);  
  58.                             if (!tcs.Task.IsCompleted && line.Contains(DoneMessage))  
  59.                             {  
  60.                                 tcs.SetResult(1);  
  61.                             }  
  62.                         }  
  63.                     }  
  64.                     catch (EndOfStreamException ex)  
  65.                     {  
  66.                         logger.LogError(ex.ToString());  
  67.                         tcs.SetException(new InvalidOperationException("'npm run serve' failed.", ex));  
  68.                     }  
  69.                 });  
  70.                 _ = Task.Run(() =>  
  71.                 {  
  72.                     try  
  73.                     {  
  74.                         string line;  
  75.                         while ((line = process.StandardError.ReadLine()) != null)  
  76.                         {  
  77.                             logger.LogError(line);  
  78.                         }  
  79.                     }  
  80.                     catch (EndOfStreamException ex)  
  81.                     {  
  82.                         logger.LogError(ex.ToString());  
  83.                         tcs.SetException(new InvalidOperationException("'npm run serve' failed.", ex));  
  84.                     }  
  85.                 });  
  86.   
  87.                 var timeout = Task.Delay(Timeout);  
  88.                 if (await Task.WhenAny(timeout, tcs.Task) == timeout)  
  89.                 {  
  90.                     throw new TimeoutException();  
  91.                 }  
  92.   
  93.                 return DevelopmentServerEndpoint;  
  94.             });  
  95.   
  96.         }  
  97.   
  98.         private static bool IsRunning() => IPGlobalProperties.GetIPGlobalProperties()  
  99.                 .GetActiveTcpListeners()  
  100.                 .Select(x => x.Port)  
  101.                 .Contains(Port);  
  102.     }  
  103. }  
It's time to run the Vue.js application. 
 
Vue.js And .NET Core 3
 
Above is the default view which is provided by Vue. I made some changes with my code and finally, the output looks like below GIF. Also, you can download my full source code by clicking here.
 
Vue.js And .NET Core 3
 
Let's recap this article. We learned about what Vue.js is, why a developer chooses it, what the process of installation is and the main concept of Vue to implement with .NET Core 3. 
 
Keep learning. 
 
 
Here are the links to my previous articles.