Writing Vue.js Applications in TypeScript on ASP.NET Core

In the previous post, we’ve briefly walked through how to build Vue.js application on ASP.NET Core. Like other modern JavaScript framework, VueJs also supports TypeScript out-of-the-box. If we can get full benefits from TypeScript to build a VueJs app, it would be awesome! There are many resources referring to the combination of VueJs and TypeScript. However, they are not using the basic template that VueJs provides, which brings about less confidence to those developers who just started using VueJs. Even worse, due to the recent version up of Webpack to 2.x, we might need a new tutorial to build a VueJs application using TypeScript. In this post, our goal will be:

  • To use the basic template provided by VueJs,
  • To use Webpack version 2.x, and
  • To run the app on ASP.NET Core.

The sample code used in this post can be found at here.

Prerequisites

We have already built a VueJs application running on ASP.NET Core in the previous post. So we’re going to re-use that.

Installing npm Packages

TypeScript

We can install TypeScript locally only for this application:

Or we can install it globally:

If TypeScript is installed globally, we should link it to this application:

ts-loader

ts-loader offers us to load .ts files to .js file without actually building them during the development time.

vue-class-component & vue-property-decorator

If we want to use .ts in our VueJs development, as the official document recommends, we should install the vue-class-component library for class decorators.

It may be necessary to install vue-property-decorator to extend vue-class-component. This is not relevant to this post, though.

vue-typescript-import-dts

TypeScript needs type definitions. vue-typescript-import-dts helps recognise .vue files as .ts.

All necessary npm packages are installed. Let’s move on.

Configurations for TypeScript

tsconfig.json

In order to use .ts, we firstly need tsconfig.json. In this post we just use the bare minimum settings to work. Further details about tsconfig.json can be found here.

Let me explain the configuration in-depth.

  • VueJs supports ECMAScript 5. Therefore, we need to target TypeScript to es5. It means that module should be CommonJs as well as lib should include dom, es2015 and es2015.promise.
  • types declares custom type definitions. As we’ve installed vue-typescript-import-dts, include it here so that the application can recognise .vue files as .ts files.
  • In order to use class decorators, we’ve installed vue-class-component. But this is not enough. We need to enable it by setting the experimentalDecorators value to be true.
  • Within the include property, we need to declare which directories are considered containing .ts files.

.eslintignore

While developing apps in TypeScript, .js files are automatically compiled and generated. But it’s not guaranteed those files comply to linting process. Therefore, we can’t be sure if those generated .js files are ESLint compliant or not. Therefore, to avoid linting errors from those generated .js files, we just turn it off by adding a line, src/**/*.js, to .eslintignore.

We just completed basic configurations for TypeScript compiling. Let’s move on.

Converting JavaScript to TypeScript

It’s time to convert existing .js files in the src directory to .ts ones situated. We’ll only look after both build and src directories.

build/webpack.base.conf.js

As Webpack is the only service to refer this file, so it’s not necessary to change this to .ts. But we do need to modify it.

First of all, the entry point should be changed from main.js to main.ts:

Then we need to replace the babel-loader part with the ts-loader one:

Every .ts file is handled by this loader. Here’s an interesting option, appendTsSuffixTo. If we use this, .vue files can be treated as .ts ones. VueJs uses the Single File Component approach – all HTML section, JavaScript section, and CSS sections are put in one single file called .vue. Therefore we need to handle it to be a TypeScript file, particularly for the JavaScript section.

We’ve completed webpack configuration to enable TypeScript handling. Let’s really convert JavaScript files to TypeScript ones.

src/main.jssrc/main.ts

Change the existing JavaScript syntax to the one for TypeScript like:

Spot on the new Vue({ ... }) part. Instead of template and components, the render function is placed. Everything has been compiled before hitting this point, and each component needs more control by itself, so we just use the render function. For more details about the render function, please refer to the official document.

src/router/index.jssrc/router/index.ts

We don’t have to worry about this. Just be cautious when using import ....

src/App.vuesrc/App.ts

Instead of using one single .vue file, we’re separating the TypeScript part from each .vue. Why are we doing this, by the way? We can still use .vue indeed. But for better maintainability, we’d better to create a separate .ts file. Let’s have a look how we can implement App.ts that is extracted from App.vue.

@Component decorator contains the name declaration so that the router can easily recognise it. The script part in the original App.vue can be altered like this:

Make sure that we should include lang="ts" as an attribute of the script tag.

src/components/Hello.vuesrc/components/Hello.ts

Now, we’re going to extract the script section from Hello.vue to Hello.ts. Let’s have a look.

Likewise, @Component contains the name declaration. Previously all two-way binding fields were defined within the data function. Using properties makes them more class-friendly. Functions became methods.

Maybe someone indicates a small change, comparing to the previous post. In order to use AJAX requests and responses, we used vue-resource. However, it’s changed to axios. According to the official VueJs blog post, vue-resource is no more supported as an official VueJs extension. Instead axios is recommended because of its richer features. In addition to this, axios provides TypeScript definitions, so there’s no reason not to use this. Its usage is almost identical to vue-resource.

Once Hello.ts is extracted, the original Hello.vue should now be changed to:

All done for conversion from JavaScript to TypeScript! It seems that we’ve done fairly massive conversion. The basic template is optimised to JavaScript, so what we’ve done so far is basically the conversion job. From now on, we can write all logic using TypeScript!

Press F5 key on your Visual Studio to run the application and see the result.

The right-hand side of the window on the picture above is Vue.js devtools, which is a Chrome extension. When we install it, we can use it right away through Chrome’s Developer Tools.

One More Thing …

So far, we’ve done the conversion of VueJs to TypeScript. As this is for local development environment, we need one last modification for deployment. Here’s the overall process of building applications for deployment:

  1. To compile .ts files and generate corresponding .js ones.
  2. To modularise and build bundles through webpack.
  3. To build ASP.NET Core libraries.
  4. To generate an artifact for deployment to Azure or IIS.
  5. To deploy.

By updating package.json and project.json we can easily achieve this goal.

package.json

Within package.json, the scripts was originally looking like:

We need to add another one for TypeScript compilation. Let’s change it like:

  • build:ts is to compile .ts files.
  • build:main is to be responsible for existing build.
  • build is to change to call both build:ts and build:main consecutively.
  • --no-deprecation flag may bring an attention. When compiling, ts-loader throws a deprecation warning. It’s OK but Visual Studio treats it as an error so build/deploy fails. By providing this flag will enable build/deploy through Visual Studio successfully.

project.json

Finally, open project.json to confirm the prepublish section.

All good now! After the deployment to Azure Web App, we can see the following screen:

Of course, if CI/CD is preferred, we can simply use dotnet publish feature.

We’ve so far had a quick look to write a VueJs application in TypeScript, bundle it on ASP.NET Core and deploy it to Azure. As mentioned earlier, the very first part is a bit complicating but it’s not that different from normal TypeScript development. We can now build the real application using VueJs and TypeScript!!

Running Vue.js on ASP.NET Core Applications

Vue.js has recently got many attentions as it is relatively easier to learn and lighter in size, comparing to other popular frameworks like Angular 1, Angular 2 or React. By providing a middleware, ASP.NET Core supports those front-end frameworks such as Angular2, Aurelia, React, Knockout, etc, while Vue has been excluded out-of-the-box. Even though we can find many good articles and code samples to integrate Vue and ASP.NET Core, as they don’t use the basic template that Vue is providing, it’s a little difficult for developers to apply at their first glance, who want to use both Vue and ASP.NET Core with minimum integration efforts. In this post, we are going to integrate Vue.js and ASP.NET Core using their basic templates, with minimum modification.

The code sample used in this post can be found at here.

Microsoft.AspNetCore.SpaServices

In order to support front-end development in ASP.NET Core, Visual Studio uses Bower. However, as we are already aware how fast front-end development environment changes, another option like Webpack helps developers work a lot easier by offering bundling, moduling and so forth. ASP.NET Core, of course supports Webpack as a separate extension. Microsoft.AspNetCore.SpaServices helps developers integrate front-end frameworks using Webpack with ease.

Prerequisites

Throughout this post, we need some preparations:

We can also use Visual Studio Code (VSC), but we’re assuming to use VS for this post.

Creating ASP.NET Core Web Application

Open Visual Studio and create a new ASP.NET Core web application project. As this web application likely uses .NET Core version 1.0.1, we need to update it to 1.1 by updating global.json:

Also, update project.json so that all NuGet packages in the web application can be complied to .NET Core 1.1:

As mentioned earlier, we’re using Webpack instead of Bower, so remove Bower-related configuration files as well as ASP.NET Core native bundling & minification setting files:

  • .bowerrc
  • bower.json
  • bundleconfig.json

And finally, all directories and files under the wwwroot directory need to be deleted. We’re all set now at the ASP.NET Core application side. Let’s add Vue.

Installing Vue.js

We can use Vue as a stand-alone library by simply including the script from CDN. However, if we want to use its powerful features especially for componentising, module bundlers like Webpack should be considered. In order to use Webpack for Vue.js, if node.js and npm have already been installed, install vue-cli:

Then, install the basic template by running the following command:

During installation, just leave all the question as default value and finally template gets installed. Now, run the following command to install all npm packages and run the Vue app:

Since Vue uses the port number of 8080, we can see the result as expected. However, this is just a Vue app running independently, not the one integrated with ASP.NET Core. Let’s move on.

Integrating Vue.js with ASP.NET Core

This is the main part of this post. We need to touch configurations at both sides.

Configuring Vue.js

First things first. We need to install the npm package, aspnet-webpack, to enable communication between front-end framework and back-end application through Webpack:

Once installed, update config/index.js to setup the root directory:

And finally, create webpack.config.js and save it to the root directory of the ASP.NET Core project:

We now got Vue.js setup done. What’s next?

Configuring ASP.NET Core

aspnet-webpack corresponding package in the ASP.NET Core side is Microsoft.AspNetCore.SpaServices. Install it through NuGet package manager and register a middleware at Startup.cs:

We also need to add a routing configuration for SPA like above. Is the ASP.NET Core side relatively simple? Let’s punch the F5 key to run the app and see how it’s going.

We now can see a different port number that is handled by the ASP.NET Core app. So, technically we completed integration between Vue.js and ASP.NET Core! How can we ensure if they are actually working together? Let’s implement a basic AJAX call to see whether they get along with each other. Of course further modification is required. Who can stop us?

Handling AJAX Request/Response

As Vue.js core is lightweight, if we want to implement more sophisticated works like handling AJAX request/response, we need to install another npm extension called vue-resource.

Once installed, add it to the Vue instance for use. Update src/main.js like:

Now we need to implement AJAX request/response codes. Open /src/components/Hello.vue and modify it like:

What we can expect from this change is the message Welcome to Your Vue.js App will be replaced with the value from res.body.message. Now we need to implement the Web API. Here’s the Web API controller and action:

All good. Build the app, press the F5 key and confirm the result.

We can see Hello World, instead of the original message.

Side note: Another benefit of using Webpack is Hot Module Replacement (HMR). As long as the app is up and running on our local machine, we can instantly change something and check the result with no time, without reloading the page. Of course, if we install .NET Core Watcher tool, we don’t even need to rebuild and rerun the app itself either.

Deploying App to Azure

We’ve built an ASP.NET Core web application with Vue.js. Now it’s time for deployment. We don’t use View features provided by ASP.NET Core. Instead we just use a static(?) wwwroot/index.html. In our local development, we don’t really have to worry about that as our development environment automatically detects that. However, in a production environment, we have to specify we’re using the static index.html page; otherwise Azure web app can’t recognise it. To enable this feature, we need to update Startup.cs:

Make sure that the UseDefaultFiles() method must always come before the UseStaticFiles() method. Finally update deployment/publish related settings in project.json for Vue.js:

Everything is done! Deploy this web app to Azure and see the result. Can we see it as expected?

So far, we have installed Vue.js, integrated it with ASP.NET Core, implemented whether both are working together or not, and deployed the app to Azure web app instance. Some may think this looks too complicated, but actually, it’s not that tricky. Rather, we’ve got another option on ASP.NET Core application development using a different front-end framework. As long as a new front-end framework emerges and it supports Webpack, we can make it working like this approach. The next post will discuss how to write VueJs apps in TypeScript, running on ASP.NET Core.

Adding YAML Settings into ASP.NET Core Apps

Unlike traditional ASP.NET web apps using web.config for configuration, ASP.NET Core apps supports various file formats for it. When we actually see the source codes, configuration supports XML, JSON, INI, Azure Key Vault, in-memory collection, command line arguments and environment variables. However, another popular format, YAML is not officially supported in ASP.NET Core at the time of writing. In this post, we are going to walk through how we can import YAML settings file to support ASP.NET Core web application.

You can find sample codes used in this post at here

Analysis of ConfigurationBuilder

When we first create a new ASP.NET Core application project, no matter it is a web app or an API app, we can always see how ConfigurationBuilder is implemented.

As we can see above, appsettings.json is included as a default, followed by secret settings, if it’s a development mode, then environment variables. If we want, we can add an XML file by adding builder.AddXmlFile("appsettings.xml"); or an INI file by adding builder.AddIniFile("appsettings.ini");, or others from various sources. In this case, we MUST make sure that the order of adding settings is very important. The settings defined in the latter file always overwrite the settings previously defined. For example, if JSON settings is loaded first then XML settings is loaded later, if a same key exists in both settings files, the value from the XML settings will always be considered.

AddYamlSettings()

As YAML settings is not supported out-of-the-box, we need to implement an extension. As there’s already a NuGet package for this extension, we will just use it. Here are sample appsettings.json and appsettings.yml files:

Now, we’re modifying the existing Startup.cs file to load YAML settings.

The builder.AddYamlFile() method has been added right after the builder.AddJsonFile() method. Therefore, we are expecting the clientId value will be FROM appsettings.yml. Let’s check it out. First of all, we need to inject the settings into a controller. Here’s a code bits to deserialise the settings into a strongly-typed instance and inject into the built-in IoC container.

Now, we need to resolve that instance from the controller level, which is a typical DI stuff.

We’re all set. Let’s run the app and see how it’s going. Can we see the result like below?

Order is Important!

As we’ve dealt above, the latter settings takes precedence for the same key. Now, let’s change between JSON settings and YAML one the other way around like:

Then try the web app again. What can we expect?

So far we have looked how to import/load YAML settings into our ASP.NET Core web apps. Can we use YAML for our ASP.NET Core web app now? Yes, we can!

Implementing HTTP Request Handler on ASP.NET Core Applications

ASP.NET WebForm or MVC applications rely on global.asax to process HTTP request pipelines. Within global.asax, each HTTP request goes through declared HTTP modules and HTTP handlers based on events. On the other hands, ASP.NET Core applications use OWIN middlewares. Actually, those middlewares now take care of what HTTP modules and HTTP handlers do. In this post, we are going to implement an HTTP request handler on a ASP.NET Core application.

Why Does It Matter?

Single Page Applications (SPA) is now a trend of web application development. SPA only contains UI logics and all other business logics are processed by calling APIs. Calling APIs through AJAX is not a problem. For example, if we use jQuery, typical AJAX call will look like:

If we need an API key for the call, the AJAX call might look like:

We might be feeling agitated here because auth key and API key are exposed within the JavaScript block, which is not we want. In this case, we usually implement API proxy (or API facade or whatever we call) so that we hide that sensitive information from the UI side. Instead, the proxy takes care of those details. Well, how can we implement the proxy then? We can implement this proxy through MVC controllers or middlewares. The good thing with middlewares to handle this is that WE DON’T NEED CONTROLLERS AT ALL. Let’s have a look.

Middleware

The main differences between HTTP modules and HTTP handler are:

  • HTTP modules process requests and pass them to another modules.
  • HTTP handlers process requests and return their responses to browsers.

As middlewares in ASP.NET Core take care of both HTTP modules and HTTP handlers, implementation becomes a lot easier and simpler. Here’s a basic middleware looking like:

And, in order to easily use this middleware at Startup.cs, we can just create an extension method like:

And this extension method is placed into the Configure method of Startup.cs like:

Within the OWIN pipeline, middlewares are invoked by an order where they are declared. Therefore, MyMiddleware is invoked after the previous middleware then passes HttpContext instance to the next middleware for further processing. Here’s the clue. If we want to implement the middleware as an HTTP handler, we simply don’t run the this._next.Invoke(context) method so that all HTTP requests complete processing at this point. Let’s make a working example.

All codes used in this post here can be found at: https://github.com/devkimchi/ASP.NET-Core-HTTP-Request-Handler-Sample

HTTP Request Header Handler Middleware

We don’t need MVC controller for our ASP.NET Core application any more because the middleware takes all AJAX requests, put some additional header and pass the requests to API server. Therefore, we can simply remove MVC middleware from the Startup.cs and add HttpRequestHeaderHandlerMiddleware into it.

Then, implement HttpRequestHeaderHandlerMiddleware like:

As we can see above, it processes the request and sends HttpContext back with response. This perfectly works as API proxy, without needing controllers. Let’s go further.

Middleware with Options Pattern

The potential problem of HttpRequestHeaderHandlerMiddleware written above is that all custom headers are hard-coded. If we add/update/delete header values, we have to update the code. Fortunately, ASP.NET Core provides Options Pattern. This is basically for dependency injection for configuration values that are declared within appsettings.json or environment variables. We can use this pattern for our middleware implementation with additional extension methods.

We have HttpRequestHeaderHandlerMiddlewareOptons and this will be injected to HttpRequestHeaderHandlerMiddleware by calling Options.Create(options) method, which creates IOptions instance. Here’s another extension method to declare options with lambda expressions.

Once it’s done, the HttpRequestHeaderHandlerMiddleware needs to be updated to accept the options instance as a parameter.

Now we can use options within our middleware. Those options can be defined within appsettings.json file, populated as a strongly-typed instance and injected to the middleware like:

So far, we have implemented a middleware as an API proxy to capture all HTTP requests, put extra header information into it and process it. With this approach, our SPA backed by ASP.NET Core would be much simpler and light-weighted.

Long Path Error While Publishing ASP.NET Core Applications

If you are writing an ASP.NET Core application, there are chances to publish your app to either a Azure Website or another place, by right-mouse clicking in Visual Studio.

In most cases, it should be alright. However, if your app has a NuGet package with a long name, it would be an issue. You might be seeing an error like this:

DNU(0,0): Error : The specified path, file name, or both are too long. The fully qualified file name must be less than 260 characters, and the directory name must be less than 248 characters.

Yes, this is the notorious PathTooLongException that Windows OS has had. There’s no silver bullet for easy fix for it. In this post, I’ll show you a couple of options that you might consider.

Cause

While creating a package to publish, it uses the following path:

For example, I’m using Justin as my [USERNAME] and my project has a name of MyProject and its full length is 163 then, the package publish path will look like:

In addition to that, an ASP.NET Core application creates three different directories under that path – approot, logs and wwwroot. The approot path actually contains all NuGet packages and DNX runtime library. Here’s the issue arising. If any of NuGet package has a very long name, it can’t be fit into the temp folder. If any node_module has a deeper dependency, it will also throw an error for packaging.

Then, how can we solve the problem? I would suggest two approaches.

Update Environment Variables

There are two environment variables – TEMP and TMP. This determines your temp directory. Therefore, change it to a shorter ones like:

This is the easiest and quickest way to fix the issue. However, the biggest caveat of this approach is that all other applications using those temp folder will be affected and we might have unwanted side effects. We need to find another way that only impacts on my current web application project.

Update .xproj

Fortunately, when you open your .xproj file of your ASP.NET Core application, you will find the line almost at the bottom:

This provides us with a great clue! Let’s find out what we can to do with that Microsoft.DNX.targets file. First of all, open the Microsoft.DNX.targets that is located in C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v14.0\DNX. It also points another file, $(_WebPublishTargetsPath)\Web\Microsoft.DNX.Publishing.targets that is located in the C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v14.0\Web directory. Open the file.

Then, find the Global Properties section and you will find:

Here’s the magic property – PublishOutputPathNoTrailingSlash. This property is used at the bottom of that targets file like:

This Dnu node basically emulates the msdeploy.exe so the Out attribute defines the output folder where the package is published. Now, we know what needs to be changed. Within our .xproj file, we can add this PublishOutputPathNoTrailingSlash node like:

Once you add the property, save it and restart your Visual Studio to get this change applied to your ASP.NET Core application project. Run the Publish menu again and it will not fail. This is a better approach comparing to the first one, because it doesn’t impact on other applications on Windows.

Of course, if you use msdeploy by your hand, it wouldn’t be an issue as you can choose the -output value based on your preference.

So far, we have had a walkaround to fix the PathTooLongException issue during the deployment of your ASP.NET Core application. I hope that Microsoft will update Visual Studio that the publish path can be customised by individual project rather than sticking onto the default temp path.

ASP.NET Core Tips & Tricks – Global Exception Handling

Exception handling is one of most important but irritating jobs for developers. There are tons of articles about the importance of exception handling. Fortunately, ASP.NET Core application has got a lot of improvement for exception handling through the request/response pipeline. In this article, we’re going to have a brief look how we can handle exceptions.

Sample application can be found here: https://github.com/devkimchi/ASP.NET-Core-Tips-and-Tricks-Sample

Global Exception Filter – OWIN Pipeline

Unlike ASP.NET MVC applications, ASP.NET Core applications only use OWIN pipelines to handle requests and responses. In order to handle exceptions, UseExceptionHandler() middleware extension is provided out of the box. Therefore, it can be easily implemented like this:

However, if you want to do more control, creating a custom exception filter class would be recommended. The following code is a simple GlobalExceptionFilter class:

Microsoft.AspNet.Mvc package provides an interface called IExceptionFilter. It declares the OnException() method so the GlobalExceptionHandler implements it. As this class accepts the ILoggerFactory instance as its constructor parameter, we can write logs when an exception is thrown. It is implemented with log4Net, NLog and ApplicationInsights libraries. You can choose anything in your taste.

So, the GlobalExceptionFilter class can be resolved within the ConfigureServices() method on Startup.cs like:

Then, raise an exception within a controller and you will be able to see the error log like this:

Exception Handling outside OWIN Pipeline

As stated above, the GlobalExceptionFilter only works within the OWIN pipeline. How about handling outside OWIN pipeline? There are only three places to handle exceptions outside OWIN pipeline – Startup() constructor, ConfigureServices() method and Configure() method. Let’s have a look at the code below:

This is how the Configure() method handles exceptions. Note that this is the only place where we can handle exceptions. In other words, the other two places, Startup() and ConfigureServices() can throw exceptions but can’t handle them. It is because of the IApplicationBuilder.Run() method. This method takes HttpContext instance to write responses. Hence, using try...catch block catches any exception and writes response messages back to browsers.

One question still remains. How can the other two places handle exceptions? Here’s a trick for them:

All codes should be surrounded by try...catch block. If any exception is thrown, the _exceptions field having type of Dictionary<string, List<Exception>> stores the exception. If any exception is thrown from Startup() or ConfigureServices(), this is handled within the Configure() method like above.

Now, we can handle all exceptions inside/outside OWIN pipeline. As this is just an example, if you apply this approach into your production code, you need to carefully review and do a bit of refactoring.