Skip to content
Riccardo De Agostini edited this page May 21, 2020 · 10 revisions

Upgrade guide for v2 users

General

  • The assembly name is now EmbedIO.dll (instead of Unosquare.Labs.EmbedIO.dll).
  • The root namespace is now EmbedIO (instead of Unosquare.Labs.EmbedIO).
  • Namespaces have been reorganized: instead of a code-type-based approach (Constants, Modules, etc.) now they follow a more common feature-based approach. For example you will find class WebApiModule, together with its support types, in namespace EmbedIO.WebApi (previously it was in Unosquare.Labs.EmbedIO.Modules).

Immutable configuration

Previous versions of EmbedIO allowed you to register and unregister modules, web API controllers, and virtual paths for static files while a web server was running. This had a direct impact on both code complexity and run-time performance.

Version 3 has immutable configuration: once a web server is started, its configuration (the set of properties that define the web server's behavior, as well as the list of registered modules) becomes read-only, and so does the configuration of all registered modules, lists of web API controllers, etc.

Another consequence of immutable configuration is that it is no longer possible to unregister modules, controllers, and virtual paths: the Unregister**** methods have simply been removed.

Immutable configuration has allowed us to simplify code in several places, removing locking mechanisms that had a direct impact on run-time performance.

New routing rules

Wildcard routing strategy has been removed: routing is Regex-based everywhere.

Base routes

In previous versions of EmbedIO, every single path or route (web API method routes, virtual paths for static files) was absolute. If you wanted a web API controller method to handle /api/customer/{id}, that's what you specified. If all your API method paths started with /api/, you had to specify it every time. For every request, the web server had to call into each module until it found one who could handle the requested path.

EmbedIO v3.0 introduces the concept of base route. Every module has its own base route, which is tested against the beginning of the requested path; the IHttpContext.RequestedPath property that handlers see is relative to the module's base route. For example, if a WebApiModule has a base route of /api/ (base routes always end with a slash) then a WebApiController method with a [Route("/customer/{id}")] attribute will handle a request for /api/customer/12345.

Base routes enable a web server to more quickly find out which module is "responsible" for a given path. If a base path has parameters, you can find their values in the IHttpContext.Route property, which implements IReadOnlyDictionary<string,string>.

Fluent initialization

A lot of work has been devoted in the development of EmbedIO v3.0 to ensure that a web server can be initialized entirely using "fluent" extension methods. This futher reduces the boilerplate code in applications, leaving you with a bare minimum that usually fits in a screenful and lets you see the structure and options of your web server at a glance.

You can obtain the most concise code by writing a private method to initialize a web server, using an expression body and lambdas, like this:

private WebServer CreateWebServer(int port, Database database)
    => new WebServer(port)
        .WithCors()
        .WithStaticFolder("/", "C:\\www", true)
        .WithWebApi("/api/", m => m
            .WithController(() => new CustomerController(database))
            .WithController(() => new InvoiceController(database))));

Fluent extension methods always start with With (or Handle if their purpose is to set a callback method) so Intellisense is your friend. You may also take a look at EmbedIO's source code: all extension methods are in classes whose name ends in Extensions, so they are rather easy to find.

HTTP context handlers

HTTP context handlers do not return bool any longer; instead, they are void functions (Subs, if you speak VB). Whether a HTTP context gets passed along to further modules is decided, by default, on a module-per-module basis, via the IWebModule.IsFinalHandler property; this default may be overridden by a handler, either by calling context.SetHandled() to stop futher processing, or with throw RequestHandler.PassThrough(); to skip the currently executing handler and pass the context along to subsequent modules.

Web API

Web API is probably the area that has undergone the most changes in EmbedIO v3.0. Writing web API controllers is now easier, there is less boilerplate code to write (if any), but porting controllers from previous versions requires some work. Let's see what has changed.

Relative routes

First of all, due to base routes, web API controller method routes (which are now specified with a RouteAttribute instead of WebApiHandlerAttribute) are now relative to the module's base route, as we saw a couple paragraphs above.

No construction parameters for controllers

WebApiController's constructor is now parameterless, so there is no need for derived classes to take constructor parameters just to pass them to base(). Your controller constructors will have just the parameters you need (a reference to a database, for example) instead of being compelled to always take an IHttpContext.

Of course the HTTP context is still available to controller methods as the HttpContext property, which now gets automatically injected post-construction.

No need to return bool

Another fundamental change is that web API controller methods do NOT need a bool or Task<bool> return type.

When a void controller method returns (or the Task returned by a controller method completes) a default 200 OK response is sent to the client - unless, of course, the method has crafted its own response.

A response with a status code different from 200 OK may be generated by throwing a HTTP exception (e.g. throw HttpException.Unauthorized();, throw HttpException.Redirect("/");, etc. - find them all here).

When a controller method generates a result, either by returning a value or when a returned Task<> completes, the result gets serialized and sent to the client. You don't need to generate your JSON any longer, just return the result and WebApiModule will take care of serialization. The default serialization callback used by WebApiModule leverages Swan.Json, but it's easy to write a serialization callback: it's just a method that takes an IHttpContext and an object and returns a Task. You can find the method signature defined as ResponseSerializationCallback.

For an example of how a web API controller changes when ported from EmbedIO v2.x to v3.0, you can check the PeopleController class from the sample project: here is the 2.x version and here is the 3.0 version.

BEWARE: Existing controller methods returning bool will generate JSON responses containing their serialized return value, as JSON is the default response serializer for web API modules.

Serving files

No more StaticFilesModule and ResourceFilesModule: the new FileModule (in namespace EmbedIO.Files, of course) uses an IFileProvider interface to abstract the file system and provides the same level of functionality (compression, caching, support for range requests) regardless of the underlying storage. File providers are available for static files, embedded resources, and (new!) ZIP files.

Fallback and "quick" actions

FallbackModule functionality has been split between ActionModule and RedirectModule. As you've probably guessed, their namespace is EmbedIO.Actions.

Unit testing support

Support types for unit testing have been moved to their own assembly EmbedIO.Testing.dll.