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.
Check version of Vue.js
Install .NET Core 3 SDK
Download the latest version of this SDK and install it.
Let's start with .NET Core 3 and Vue.js.
Create ASP.NET Core 3 web application project using API template.
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.
- <Project Sdk="Microsoft.NET.Sdk.Web">
-
- <PropertyGroup>
- <TargetFramework>netcoreapp3.0</TargetFramework>
- <SpaRoot>client-app\</SpaRoot>
- <DefaultItemExcludes>$(DefaultItemExcludes);$(SpaRoot)node_modules\**</DefaultItemExcludes>
- <TypeScriptCompileBlocked>true</TypeScriptCompileBlocked>
- <TypeScriptToolsVersion>Latest</TypeScriptToolsVersion>
- <IsPackable>false</IsPackable>
- </PropertyGroup>
-
-
- <Target Name="PublishRunWebpack" AfterTargets="ComputeFilesToPublish">
-
- <Exec WorkingDirectory="$(SpaRoot)" Command="npm install" />
- <Exec WorkingDirectory="$(SpaRoot)" Command="npm run build" />
-
-
- <ItemGroup>
- <DistFiles Include="$(SpaRoot)dist\**" />
- <ResolvedFileToPublish Include="@(DistFiles->'%(FullPath)')" Exclude="@(ResolvedFileToPublish)">
- <RelativePath>%(DistFiles.Identity)</RelativePath>
- <CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
- </ResolvedFileToPublish>
- </ItemGroup>
- </Target>
-
- <ItemGroup>
- <PackageReference Include="Microsoft.AspNetCore.SpaServices.Extensions" Version="3.0.0-preview6.19307.2" />
- </ItemGroup>
-
- <ItemGroup>
-
- <Content Remove="$(SpaRoot)**" />
- <None Remove="$(SpaRoot)**" />
- <None Include="$(SpaRoot)**" Exclude="$(SpaRoot)node_modules\**" />
- </ItemGroup>
-
- <Target Name="DebugEnsureNodeEnv" BeforeTargets="Build" Condition=" '$(Configuration)' == 'Debug' And !Exists('$(SpaRoot)node_modules') ">
-
- <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." />
- <Message Importance="high" Text="Restoring dependencies using 'npm'. This may take several minutes..." />
- <Exec WorkingDirectory="$(SpaRoot)" Command="npm install" />
- </Target>
-
-
- </Project>
Let us now inject the middleware at startup file and add connection.cs file for port forwrding.
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Threading.Tasks;
- using Microsoft.AspNetCore.Builder;
- using Microsoft.AspNetCore.Hosting;
- using Microsoft.AspNetCore.HttpsPolicy;
- using Microsoft.AspNetCore.Mvc;
- using Microsoft.Extensions.Configuration;
- using Microsoft.Extensions.DependencyInjection;
- using Microsoft.Extensions.Hosting;
- using Microsoft.Extensions.Logging;
- using VueDemoWithAsp.NetCore.VueCoreConnection;
-
- namespace VueDemoWithAsp.NetCore
- {
- public class Startup
- {
- public Startup(IConfiguration configuration)
- {
- Configuration = configuration;
- }
-
- public IConfiguration Configuration { get; }
-
-
- public void ConfigureServices(IServiceCollection services)
- {
- services.AddControllers();
-
- services.AddSpaStaticFiles(options => options.RootPath = "client-app/dist");
- }
-
-
- public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
- {
- if (env.IsDevelopment())
- {
- app.UseDeveloperExceptionPage();
- }
- else
- {
-
- app.UseHsts();
- }
-
- app.UseHttpsRedirection();
-
- app.UseRouting();
-
- app.UseAuthorization();
-
- app.UseEndpoints(endpoints =>
- {
- endpoints.MapControllers();
- });
-
-
- app.UseSpaStaticFiles();
- app.UseSpa(spa =>
- {
- spa.Options.SourcePath = "client-app";
- if (env.IsDevelopment())
- {
-
- spa.UseVueDevelopmentServer();
- }
- });
- }
- }
- }
The new file should look like below.
- using Microsoft.AspNetCore.Builder;
- using Microsoft.AspNetCore.SpaServices;
- using Microsoft.Extensions.DependencyInjection;
- using Microsoft.Extensions.Logging;
- using System;
- using System.Diagnostics;
- using System.IO;
- using System.Linq;
- using System.Net.NetworkInformation;
- using System.Runtime.InteropServices;
- using System.Threading.Tasks;
-
- namespace VueDemoWithAsp.NetCore.VueCoreConnection
- {
- public static class Connection
- {
-
- private static int Port { get; } = 8080;
- private static Uri DevelopmentServerEndpoint { get; } = new Uri($"http://localhost:{Port}");
- private static TimeSpan Timeout { get; } = TimeSpan.FromSeconds(60);
-
- private static string DoneMessage { get; } = "DONE Compiled successfully in";
-
- public static void UseVueDevelopmentServer(this ISpaBuilder spa)
- {
- spa.UseProxyToSpaDevelopmentServer(async () =>
- {
- var loggerFactory = spa.ApplicationBuilder.ApplicationServices.GetService<ILoggerFactory>();
- var logger = loggerFactory.CreateLogger("Vue");
-
- if (IsRunning())
- {
- return DevelopmentServerEndpoint;
- }
-
-
- var isWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows);
- var processInfo = new ProcessStartInfo
- {
- FileName = isWindows ? "cmd" : "npm",
- Arguments = $"{(isWindows ? "/c npm " : "")}run serve",
- WorkingDirectory = "client-app",
- RedirectStandardError = true,
- RedirectStandardInput = true,
- RedirectStandardOutput = true,
- UseShellExecute = false,
- };
- var process = Process.Start(processInfo);
- var tcs = new TaskCompletionSource<int>();
- _ = Task.Run(() =>
- {
- try
- {
- string line;
- while ((line = process.StandardOutput.ReadLine()) != null)
- {
- logger.LogInformation(line);
- if (!tcs.Task.IsCompleted && line.Contains(DoneMessage))
- {
- tcs.SetResult(1);
- }
- }
- }
- catch (EndOfStreamException ex)
- {
- logger.LogError(ex.ToString());
- tcs.SetException(new InvalidOperationException("'npm run serve' failed.", ex));
- }
- });
- _ = Task.Run(() =>
- {
- try
- {
- string line;
- while ((line = process.StandardError.ReadLine()) != null)
- {
- logger.LogError(line);
- }
- }
- catch (EndOfStreamException ex)
- {
- logger.LogError(ex.ToString());
- tcs.SetException(new InvalidOperationException("'npm run serve' failed.", ex));
- }
- });
-
- var timeout = Task.Delay(Timeout);
- if (await Task.WhenAny(timeout, tcs.Task) == timeout)
- {
- throw new TimeoutException();
- }
-
- return DevelopmentServerEndpoint;
- });
-
- }
-
- private static bool IsRunning() => IPGlobalProperties.GetIPGlobalProperties()
- .GetActiveTcpListeners()
- .Select(x => x.Port)
- .Contains(Port);
- }
- }
It's time to run the Vue.js application.
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.
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.