RSS

vNext and Class Libraries

25 Jan

This is a followup to the previous post discussing my first steps with vNext. I suggest reading it first.

vNext class libraries are similar in concept to a regular .NET library. Like ASP.NET vNext they do not actually build to a dll. What is great about them is that you can basically change the vNext library using notepad and it will be compiled on-the-fly when you re-run the page. However unfortunately code changes done in vNext, including vNext libraries, will require a restart of the host process in order to take effect. It would have been great if code changes did not require this restart and the state of the app would be maintained.

The good news is that you can reference regular .NET class libraries from vNext. This may sound trivial, but up until the recent beta 2 and VS2015 CTP 5 it wasn’t possible unless you pulled a github update and manually “k wrapped” your .NET assembly with a vNext library as explained here. Fortunately CTP 5 allows referencing a regular .NET library but it is still buggy as VS might raise build errors (as it does on my machine), but the reference will actually work and running code from a vNext MVC site actually invokes the compiled .NET dll.

Here’s how:

1. I create and open a new ASP.NET vNext web application. This time I’m using an Empty project and adding the bear minimum of code required to run an MVC app.
class lib1

project.json: Add a dependency to “Microsoft.AspNet.Mvc”.

{
    "webroot": "wwwroot",
    "version": "1.0.0-*",
    "exclude": [
        "wwwroot"
    ],
    "packExclude": [
        "node_modules",
        "bower_components",
        "**.kproj",
        "**.user",
        "**.vspscc"
    ],
    "dependencies": {
		"Microsoft.AspNet.Server.IIS": "1.0.0-beta2",
		"Microsoft.AspNet.Mvc": "6.0.0-beta2"
    },
    "frameworks" : {
        "aspnet50" : { },
        "aspnetcore50" : { }
    }
}

Startup.cs: Add configuration code and a basic HomeController like so:

using Microsoft.AspNet.Builder;
using Microsoft.Framework.DependencyInjection;

namespace WebApplication3
{
    public class Startup
    {
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddMvc();
        }

        public void Configure(IApplicationBuilder app)
        {
            app.UseMvc();
        }
    }

    public class HomeController
    {
        public string Index()
        {
            return "hello";
        }
    }
}

Running the code now “as is” should show a “hello” string in the web browser.

2. I am adding a vNext class library (this isn’t mandatory for running a .NET lib but I do it anyway for the sake of the demo).
class lib2

The class lib has a single class like so:

namespace ClassLibrary1
{
    public class vNextLib
    {
        public static string GetString()
        {
            return "hello from vNext lib";
        }
    }
}

It is now possible to “add reference” to this new ClassLibrary1 as usual or simple modify the project.json like so (partial source listed below):

	"dependencies": {
		"Microsoft.AspNet.Server.IIS": "1.0.0-beta2",
		"Microsoft.AspNet.Mvc": "6.0.0-beta2",
		"ClassLibrary1": ""
	},

Finally change the calling ASP.NET vNext web app to call the library and display the string (Startup.cs change):

    public class HomeController
    {
        public string Index()
        {
            return ClassLibrary1.vNextLib.GetString();
        }
    }

At this point I recommend to “Start without debugging” (Ctrl F5). If you don’t do that, any code changes will stop IISExpress and you’ll have to F5 again from VS. You can do that but it will not be easy to take advantage of the “on the fly” compilation.

Note the process ID in iisexpress. 2508.
class lib3

Now changing the ClassLibrary1 code to say “hello from vNext lib 2” and saving causes iisexpress to restart (note the different Process ID). A simple browser refresh shows the result of the change – no build to the Class Library was required:
class lib4

3. Now create a new Class Library, but this time not a vNext library but a regular .NET library.
class lib5

The code I use is very similar:

namespace ClassLibrary2
{
    public class RegLib
    {
        public static string GetString()
        {
            return "hello from .NET lib";
        }
    }
}

This time you can’t just go to project.json directly as before because the .NET library isn’t a “dependency” as the vNext library. You must first add a reference the “old fashion way” (VS 2015 – CTP 5, remember?):
class lib6

This automates several things:

  • It “wraps” the .NET dll with a vNext lib wrapper which can be viewed in a “src” sibling “wrap” folder. It actually performs what was previously “k wrap” from that github pull mentioned earlier:
    class lib7
  • It adds the “wrap” folder to the “sources” entry in the global.json. If you recall from the previous post, global.json references source folders for the vNext solution so this is a clever way to include references to the class lib:
    {
      "sources": [
        "src",
        "test",
        "wrap"
      ]
    }
    

Now that you have a “ghost vNext lib” wrapping the real .NET code. This isn’t enough. You need to add a dependency to the project.json just like with a regular vNext lib (you may have to build your .NET DLL first before the ClassLibrary2 is available):

	"dependencies": {
		"Microsoft.AspNet.Server.IIS": "1.0.0-beta2",
		"Microsoft.AspNet.Mvc": "6.0.0-beta2",
		"ClassLibrary1": "",
		"ClassLibrary2": ""
	},

Now changing the Startup.cs code:

    public class HomeController
    {
        public string Index()
        {
            //return ClassLibrary1.vNextLib.GetString();
            return ClassLibrary2.RegLib.GetString();
        }
    }

Now it seems like in VS2015 CTP 5 this is buggy because building results with an error that complains of a missing ClassLibrary2:

Error CS0103 The name ‘ClassLibrary2’ does not exist in the current context.

If you ignore the build error and still run using ctrl+F5 – it will work:
class lib9

Changing the regular .NET code and saving has no effect as expected, until you recompile it.

Why referencing a regular .NET lib so important? I can think of several reasons:

  1. Migrating a .NET web app to vNext. You may want to use vNext for the ASP.NET tier and use your older business logic and data layers regular .NET assemblies until you decide to migrate them.
  2. Security: If you deploy a vNext app which is not precompiled, a hacker might change your code and vNext will compile on-the-fly. You may claim that you should not deploy non-precompiled apps, but I think differently. I see it as a great advantage to be able to make changes on a server using notepad, in order to perform a quick fix or debug an issue. The downside is the potential hacking. Not sure if MS will allow a single vNext class lib to be precompiled while the rest of the site to be deployed with its source code. If not, perhaps the solution is to use a pre-compiled regular .NET class library for sensitive code, deployed with a non-precompiled vNext app.
  3. Referencing a 3rd party .NET library which does not have a vNext package might be useful.

 

Summary

I assume that Microsoft will spend more time making this wrapping mechanism transparent and flawless. Basically I see no reason why adding the dependency to the wrapping vNext lib isn’t a part of adding a reference to a .NET lib.

A good reference to vNext Class Libraries can be found in the video session of Scott Hanselman and David Fowler: http://channel9.msdn.com/Events/TechEd/NorthAmerica/2014/DEV-B411.

 
1 Comment

Posted by on 25/01/2015 in Software Development

 

Tags: , ,

One response to “vNext and Class Libraries

  1. Mark Redman

    06/02/2016 at 12:42

    Hi,

    This is great, I can now reference a standard .net class library.
    (I need to do this at t his stage as T4 templating with multiple files wont work in a class library package, otherwise would use that)

    You mention:

    “Now it seems like in VS2015 CTP 5 this is buggy because building results with an error that complains of a missing ClassLibrary2:

    Error CS0103 The name ‘ClassLibrary2’ does not exist in the current context.

    When I reference the code in the library class, I get this error:

    Error CS0246 The type or namespace name ‘xxx’ could not be found (are you missing a using directive or an assembly reference?) Web.DNX Core 5.0

    and the web project wont run..

    Any ideas. seems like the code is not available? I am referencing the class code in the startup.cs

    Thanks.

     

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

 
%d bloggers like this: