Scott Hanselman

Integrating Visual Studio Code with dnx-watch to develop ASP.NET 5 applications

October 21, 2015 Comment on this post [20] Posted in ASP.NET | Open Source
Sponsored By

Visual Studio Code is a great cross platform code editor that is also free. You can get it at code.visualstudio.com for Mac, Windows, or Linux. It's great for web development, and particularly shines with node.js. Since ASP.NET 5 is still in active beta and moving very fast, some of the features I want when VSCode is used with ASP.NET aren't there yet. Fortunately VSCode is very configurable and I was able to get it to do what I wanted in about 10 minutes of messing around.

dnx-watch in VSCode

One of the promises of ASP.NET is the ability to write code, hit Ctrl-S (Save) in your editor and then hit F5 (refresh) in your browser to see the results. Rinse, repeat. Any "build" step should be basically hidden.

After you've got .NET Core and ASP.NET 5 with the DNX (for now, the "dotnet execution engine") you should take a look at the dnx-watcher command. It's a command you can install in one line:

dnu commands install Microsoft.Dnx.Watcher

This convenience command wraps dnx, so when you want to run your app rather than "dnx web" you'll say "dnx-watch web." It will watch your source files directory for changes. When you make a change, be it in VSCode or in Notepad, dnx-watch will kick the process and start it again so you can hit F5 in your browser.

Visual Studio Code doesn't have a Build or Debug menu for ASP.NET today, but I wanted to be able to "Ctrl-Shift-B" and build/start my web application. Specifically I wanted to run dnx-web on the current app.

Here's how you do that today. First, install dnx-watch as above.

This next part with tasks.js is totally optional, but I like it because it makes VSCode and the Ctrl-Shift-B hotkey I'm used to work the way I want.

Make a folder at the top of your project called ".vscode" and put a file called "tasks.json" inside it. This is a special file that lets you tell Visual Studio Code what gulp tasks it should know about.

Here I'm saying there's a task (that we'll create in a second) called "watch" (I decide on the name) and it's the Build command for this project. I could make a Test command if I wanted, as well. I want to see the output.

{
"version": "0.1.0",
"command": "gulp",
"isShellCommand": true,
"tasks": [
{
"taskName": "watch",
"isBuildCommand": true,
"showOutput": "always",
"isWatching": true
}
]
}

Now where does this "watch" task go? Well it goes in my project's gulpfile.js! It's a gulp task like any other.

I want to shell out and run dnx-watch, so I'll have to bring in a small library called gulp-shell by adding it to my package.json, then running npm.install. That will give me the ability to shell out to arbitrary command line apps like dnx-watch. Visual Studio Code will capture and stream the output as seen in the screenshot above.

Then I just add one line to my gulpfile after adding the appropriate require at the top.

gulp.task('watch', shell.task(['dnx-watch web']))

ASIDE: There is the beginnings of a gulp plugin for ASP.NET called "gulp-dnx" that knows about DNX and ASP.NET 5 but since I just wanted this one feature, this was easier. When gulp-dnx knows about dnx-watch, it might be easier, but the general flow would remain the same.

At this point, I can code all I want, press Save and dnx-watch will automatically restart my application. I can put Visual Studio Code side by side with my browser and Save/Refresh over and over.

Now you can always add your own keybindings by editing keybindings.js from File | Preferences | Keyboard Shortcuts. For example, here Ctrl-Q is bound to Terminate Task (that will let me stop dnx-watch). However, because we said "isBuildCommand: true" in the tasks.js file, we've told Visual Studio Code that our "watch" gulp command IS our project's command to build. You could add test commands, make your gulp file more sophisticated; the sky's the limit.

Give it a try!


Sponsor: Many thanks to Atalasoft for sponsoring the feed this week. If your project requires image viewing, format freedom, scanning, or other document-centric workflows, Atalasoft’s document imaging experts can help. Evaluate their developer tools for 30 days with remarkable human support.

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Hosting By
Hosted in an Azure App Service
October 21, 2015 7:20
It's funny how after nearly 20 years since Classic ASP's inception, we're finally getting back to being able to edit web source code and refresh the browser and see our changes. It's rather nostalgic!

Can't wait til ASP.NET 5 arrives!
October 21, 2015 8:35
Visual Interdev is coming! ;)
October 21, 2015 10:08
Well, the funny thing is that the javascript and .net "compilation world" go into a completely opposite direction.
In the good old days, there was not such a thing as JavaScript compilation/transpilation, just open an html page with JavaScript (even without web server) and it just works. Today you need to be gulp/babel/typescript guru just to get some basic javascript working.
The .net world (surprise surprise) is taking the path of the radical simplification thanks to roslyn. That's really great. For my javascript, I would already be very happy if there was some equivallent of msBuild.
October 21, 2015 16:50
I'm expecting to see Visual Studio Code with custom plugins. Imagine that power.
October 21, 2015 17:55
Cool ... VSCode would be more powerful if it accept plugins the same way that notepad++ do
Sam
October 21, 2015 19:11
LiveReload support would be nice... Then we could get rid of that pesky 'reload the browser' step.
October 21, 2015 23:54
So, I tried this using beta8 on Fedora 22 (running on Mono), and it doesn't work :(
dnx-watch web
crashes with the following:
Error: This application requires DNX version 1.0.0-rc1-15838 or newer to run.
Is there something I can do to get it working?
October 22, 2015 14:30
Mikael, I think you need to use the dnvm upgrade command
October 22, 2015 16:46
For Windows why would anyone use VSCode and not Visual Studio 2015 Community Edition?
October 22, 2015 22:24
Phil,
dnvm upgrade
doesn't upgrade anything, since beta8 is the latest "stable" release. I ran upgrade just before trying dnx-watch to get up to beta8 from beta7. 1.0.0-rc1-15838 looks like the version number of a nightly build to me.
October 23, 2015 4:05
@scottt732

you can do it by using browser sync plugin, its not as easy as with livereload but it works quite good.
October 23, 2015 8:49
When can we expect a create,build,run,debug asp.net project in vscode. That would be awesome... it would be like spreading pollen throughtout the world for great programming experience
October 23, 2015 19:02
@suraj

1. VS Code
2. Asp.net project directory tree
3. A .vscode subdirectory
4. Html form in .vscode subdirectory with a few text fields, dropdowns, a compile button, a debug button, a run button, ...
5. A REST service running in node.js
6. JavaScript on the html form in #4 to call the REST service from #5
7. Code in the REST service to do a build, a debug or a run on the asp.net application

It is all just waiting to be built and tagged "inspired by tcl/tk".
Ted
November 02, 2015 1:44
Is dnx-watch for Windows only? I'm getting a null reference exception trying to run it on Ubuntu :(
November 04, 2015 22:01
I wish we could push development and execution away from the same location. Executing code in the development directory has side effects that make things difficult. It eliminates the ability to have a "compile" operation which can enable operations to construct the final output. It also makes development workstation isolation and unit testing difficult when unique configuration settings are also source controlled.


Why can't web sites be developed more like assemblies or applications where there is a clean isolation between the source code and output? I'll inject database development into this because it also is busted. If database development actually isolated schema from "data" and the physical database instance abstraction patterns could be used plus could enhance the physical upgrade capabilities and version of the schema tracking.

The only reasons I think of is the carryover from having limited access to spawn http server instances to a compiled output location. IISExpress and the embedded support for asp.net grealy enhance the abilty to build solutions to "build" and execute from the compiled location.

What is the real advantage of running a web site from the same location as your source code?
November 06, 2015 2:41
@Ellyll
I am working on a MAC, and it works (or at least executes without errors).
November 07, 2015 23:54
Hmm, anyone have any ideas what my problem is? Here's what I'm using:

mono --version
Mono JIT compiler version 4.0.4 (Stable 4.0.4.1/5ab4c0d Tue Aug 25 23:11:51 UTC 2015)

dnvm list

Active Version Runtime Architecture OperatingSystem Alias
------ ------- ------- ------------ --------------- -----
1.0.0-beta7 mono linux/osx
* 1.0.0-beta8 mono linux/osx default

And here's what I get:

dnx-watch web
System.NullReferenceException: Object reference not set to an instance of an object
at Microsoft.Dnx.Watcher.Program..ctor () [0x00000] in <filename unknown>:0
at Microsoft.Dnx.Watcher.Program.Main (System.String[] args) [0x00000] in <filename unknown>:0
at (wrapper managed-to-native) System.Reflection.MonoMethod:InternalInvoke (System.Reflection.MonoMethod,object,object[],System.Exception&)
at System.Reflection.MonoMethod.Invoke (System.Object obj, BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) [0x00000] in <filename unknown>:0
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw () [0x00000] in <filename unknown>:0
at Microsoft.Dnx.Runtime.Common.EntryPointExecutor.Execute (System.Reflection.Assembly assembly, System.String[] args, IServiceProvider serviceProvider) [0x00000] in <filename unknown>:0
at Microsoft.Dnx.ApplicationHost.Program.ExecuteMain (Microsoft.Dnx.ApplicationHost.DefaultHost host, System.String applicationName, System.String[] args) [0x00000] in <filename unknown>:0
at Microsoft.Dnx.ApplicationHost.Program.Main (System.String[] args) [0x00000] in <filename unknown>:0
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw () [0x00000] in <filename unknown>:0
at Microsoft.Dnx.Runtime.Common.EntryPointExecutor.Execute (System.Reflection.Assembly assembly, System.String[] args, IServiceProvider serviceProvider) [0x00000] in <filename unknown>:0
at Microsoft.Dnx.Host.Bootstrapper.RunAsync (System.Collections.Generic.List`1 args, IRuntimeEnvironment env, System.String appBase, System.Runtime.Versioning.FrameworkName targetFramework) [0x00000] in <filename unknown>:0
November 10, 2015 1:46
@peter
To have something cross platform? And then sneak in android and ios builds? Replacing Xamarin?
Ed
November 21, 2015 14:26
Great article!

I feel that adding tasks to gulp that can be directly run by npm is more complex than necessary so instead of using gulp I just added a command to the script section of package.json like so:


{
"scripts": {
"setup": "npm install && bower install && dnu restore && dnu build",
"start": "dnx-watch web"
}
}


Even though this does not give me a task in vs code (easily fixed), it does correspond well to what I'm used to, i.e using npm for web projects and just running

npm run setup
npm start
December 13, 2015 22:49
Scott, is anything being done to speed up the load time for dnx web to start serving pages? I'm using nodemon to look for changes and reissue the dnx web command (dnx-watch was not working for me) and this flow is PAINfully slow. As in there is no way I can do quick edits to front-end files and wait for dnx web to reload each time I want to see an update to a view, css or JS edit. Any thoughts on this would be appreciated, thanks in advance!

Comments are closed.

Disclaimer: The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.