Fork me on GitHub

ServiceStack's new HTML powers - the website framework

Razor Rockstars is a ServiceStack demo website showcasing ServiceStack's new MVC Razor Engine support and its enriched HTML story with multiple view engine support and No Controller / No Ceremony development options. In many cases we've gone beyond what MVC provides with many new and natural features optimized for developer happiness, fast iteration times and run-time performance, putting the fun back into .NET / Mono web development!

Install via NuGet

ServiceStack's Razor ViewEngine is an optional .NET 4.5 add-on that's self-contained within the RazorFormat plugin which can be easily added to any empty ASP.NET or Console Application project via NuGet with:

PM> Install-Package ServiceStack.Mvc

Once added to your project, opt-in to enable the Razor feature in your AppHost with:


    Plugins.Add(new RazorFormat());
    
Source code embedded in all pages

All pages includes the code and markup used to render itself

To make it easier to explore all features on this site and to provide a better idea of how it all fits together, all pages include gists of the source code used to render itself. Source code for this entire website is in the RazorRockstars Github project.

Website framework features

We've added features beyond MVC in true ServiceStack-style: by enhancing your existing services, working as you'd expect it to in a REST service framework:

Runs Everywhere

Like the rest of ServiceStack, you can create websites and REST services in any host on any platform, e.g:

Nothing to learn

Invisible API - just you and your IOC

One of ServiceStack's core objectives is to retain an invisible API that gets out of your way. The ServiceStack service itself is a classic example, it's just a simple C# class auto-wired with your registered dependencies that accepts any user-defined Request DTO and lets you return any object which is automatically serialized into the expected Response Content-Type. Composable and re-usable functionality can be applied to all your services via Request / Response Filters, Filter Attributes, Validators or by extending a common base class - all of which get auto-wired with your registered dependencies. Even Razor views have access to your IOC dependencies.

You retain complete control over the Request DTO, Implementation and Response - added features simply enhance your existing models and services. We refer to this style as starting from ideal C#, and project-out and is one of the key approaches we use to promote a frictionless dev workflow, i.e. instead of having your C# code bind to a foreign API abstraction, ServiceStack builds functionality around your untainted C# classes and DTOs (unhindered by artificial APIs). This makes your logic more re-usable and is how any new feature we add to the framework is immediately able to work with your existing services without any code-changes required. E.g. you can code as you would normally and throw C# Exceptions and the ideal HTTP Response gets emitted, you also have access to rich fluent validation that supports returning typed structured error responses back to C# clients.

Include Partials from other view engines

Unlike many web frameworks, ServiceStack lets you include Partial views from other registered view engines. This is ideal for Content heavy pages where you can use MVC Razor format for a precise layout whilst maintaining the content of your dynamic pages in Markdown.

All Dead and Alive individual Rockstar pages are maintained in this way.

A Complete Web + REST Services Stack

The new Razor and multiple HTML ViewEngine support now transforms ServiceStack from a Web Services framework to a complete Website + REST/SOAP/MQ services stack which provides a clean replacement for MVC, WCF or WebApi.

This is a clean-break from the layers of legacy frameworks that have been added to ASP.NET over the years. We've made everything simpler by removing all existing ASP.NET layers and xml-encumered providers added on top of IHttpHandler's since .NET 2.0 and replaced them with clean, testable code-first providers based on urls and clean POCOs - all working seamlessly together.

HTML format supports multiple pluggable view engines

HTML support works just as you would expect it to exist on a REST service framework - you get to re-use your existing web service implementation where HTML is just another Content-Type:

ServiceStack Architecture

ServiceStack supports multiple view engines out-of-the-box: By default HtmlReport and Markdown is pre-registered, whilst Razor support can be installed via NuGet.

When the client requests HTML Content-Type, ServiceStack will cycle through all registered view engines to find a matching view, if no matches are found the HtmlReport is used as a fallback which provides a readable and semantic HTML layout letting you visualize all the data returned from your web service at a glance.

One simple and unified HTTP stack

ServiceStack has a single, simple unified HTTP stack. There is no duplicate or supplementary functionality that only works for HTML vs Services. Everything is kept simple: There is 1 set of Routes, 1 way to create a Service, 1 set of Request / Response filters, 1 Validation model. All of ServiceStack's plugins and providers work equally well across all services and can even be shared from within MVC / WebForms hybrid solutions.

Add HTML views to existing services

The benefits of this are prominent, you only have a single implementation for all your Mobile, Desktop or Web Browser clients. By default, your clean C#-only services is accessible via HTML, JSON, XML, CSV, JSON, SOAP, ProtoBuf and MQ endpoints - all with no effort.

Solution view of Rockstars page

A live example of this is the RockstarsService.cs which is available by any of the defined custom routes, e.g:

/rockstars
json xml csv jsv
/rockstars/1
json xml csv jsv
/rockstars/aged/27
json xml csv jsv

When viewed in a browser it will return the HTML output generated by the Rockstars.cshtml view embedded inside the specified HtmlReport.cshtml template using the model populated by the RockstarsService.cs

Unlike MVC (which has a convention for views based on the name of the controller), ServiceStack's view selection is based on the name of the Response or Request model (DTO) returned. E.g. If your Service returns a RockstarsResponse then we first look for a view of the same name as the Request DTO called Rockstars.cshtml followed by the Response DTO name RockstarsResponse.cshtml (in all registered view engine extensions).

As ServiceStack requires Request DTO's to be unique, you are free to layout the views in any logical file system structure you wish under the /Views folder and are not forced into any existing MVC /Views/ControllerName/ViewName convention.

Change Views and Layout templates at runtime

The above convention is overrideable where you can change both what View and Layout Template is used at runtime by returning your Response inside a decorated HttpResult:


    return new HttpResult(dto) {
        View = {viewName},
        Template = {layoutName},
    };
    

This is useful whenever you want to display the same page in specialized Mobile and Print Preview website templates. You can also let the client change what View and Template gets used by attrubuting your service with the [ClientCanSwapTemplates] Filter:


    [ClientCanSwapTemplates]
    public class RockstarsService : Service { ... }
    

This attribute allows the client to change what View gets used with the View and Template QueryString or FormData Request Params. A live example of this feature is used to change the /rockstars page:

The No Ceremony option - Dynamic pages without Controllers

Many times (especially for read-only pages) Controllers add un-necessary overhead and just calling your dynamic Razor (or Markdown) pages directly will promote more cohesive pages requiring less code. Especially if you're already encapsulating your data access logic behind domain services and repositories - the overhead of a controller and action methods just adds un-necessary noise, that ends up being harder to test than pure C# code.

Pretty urls by default (no custom Routes needed)

ServiceStack has great support for this story where it lets you omit the .cshtml or .md page extensions and it still executes the desired page but with a pretty url. When calling dynamic pages with .ext (as done by VS.NET when hitting F5 inside a page) it is automatically re-directed to the pretty url version (saving a YSOD you might be used to with MVC):

Default pages for directories

The Above url shows the behaviour when requesting the default document default.cshtml which gets redirected to the alias url of its parent directory.

Single vs Multiple directories

The Dave Grohl and Eddie Vedder content pages show different ways of structuing the same page components whilst retaining the same url. The Dave Grohl example shows how you can keep all Rockstar pages in a single directory with different names for each Grohl.cshtml razor page and GrohlContent.md partial markdown view.

Eddie Vedder (and all the other Rockstars) use multiple sub directories to maintain their dynamic content pages and the different components that make up each page. Regardless of which layout you go with, you can still access the each page with the same case-insensitive pretty url:

Keep all views and their assets together

Despite both options yielding the same result, whenever you have many similar content pages it becomes a good idea to adopt the 'multiple sub-directory' convention which apart from giving each page more symmetry, it will allow you to group all the websites dynamic and static content, images and css within the same folder that makes copying, updating and deploying as easy as dragging and dropping a folder.

Layout templates

Specifying Layouts for Razor Views and Pages follow MVC's convention where it looks for the Layout in your /Views/Shared folder. In this case the Razor Page of each Rockstar references either /Views/Shared/AliveLayout.cshtml or /Views/Shared/AliveLayout.cshtml to give each Rockstar a different look:

Rockstars that have passed

Rockstars still Rocking it

Smart View Pages

One features Controllers have is the ability to inspect the incoming request. Inside Services, ServiceStack takes care of Request Binding and automatically populates your Request DTO based upon the HTTP Request Params. When calling pages directly (i.e. without Controllers) there are still a few ways to access the incoming HTTP Request data:

Pages with typed View Models

In the same way ServiceStack populates the Request DTO in Services, it will auto populate your View model by in Views when inheriting from the Generic ViewPage<TModel> base class that's specified in the _ViewImports.cshtml as seen in /TypedModelNoController:


    @model SearchRockstars
    

This will result in the typed @Model being populated from the HTTP Request params

Pages with dynamic View Models

The above solution requires an existing typed Request DTO / Input Model. There's also the option of not requiring a View Model when inheriting from the non-Generic ViewPage as seen in /NoModelNoController:


    @inherits ViewPage
    

In this case @Model is a ViewDataDictionary that's populated from the Request's QueryString, FormData, Cookies and Items.

Access Request / Response properties in Views

In addition to the @Model property, each View also has access to base.Request / base.Response properties for more fine-grained access to ServiceStack's IHttpRequest and IHttpResponse types.

Access IOC dependencies directly in Views

For dynamic views to also fullfill the roles of Controllers they need to be smart, which is why we've enabled views the ability to resolve your registered IOC dependencies with:


    var provider = TryResolve<IYourProvider>();
    

In addition to accessing IOC debendencies, base classes also provide quick access to the most common providers like ADO.NET's IDbConnection as well as ServiceStack's clean Session and Caching providers.

Many Micro ORMs like (OrmLite and Dapper) provide extension methods on ADO.NET's IDbConnection making it trivial to perform common db tasks. Here's an example of filtering the results of the Rockstar table with a typed Request Param:


    var rockstars = Db.Select<Rockstar>(q => q.Age == Model.Age);
    

Easily configure custom error pages in code

Since all common web tasks should be easy to configure, we've made it easy to register your own custom IHttpHandler's for different HTTP Status codes which you can do in your AppHost with:


    this.CustomErrorHttpHandlers[HttpStatusCode.Unauthorized] = new RazorHandler("/login");
    

For NotFound requests we recommend instead to use .NET Core's convention of just registering a Catch-All Middleware at the end of the App Builder Pipeline. ServiceStack HttpHandlers can be registered as a .NET Core module as-is so we're able to re-use our existing RazorHandler here as well, e.g:


    app.Use(new RazorHandler("/notfound"));
    

Which you can test by looking for a Rockstar that doesn't exist on this site, e.g:

This rule tells ServiceStack to execute the /notfound Razor page for all 404 requests. The page referenced by Razor handler can be any dynamic razor page (i.e. not just a static html page) - which is extremely useful for Single Page Apps taking advantage of the DOM's history.pushState().

Markdown built-in

Another templating language we're especially fond of is Markdown. Although as the name suggests it's more of a Mark Down language since it's able to express commonly used HTML elements used for structuring content down into a simple syntax you may conventionally see published in ascii-only environments like plain-text email.

Maintain Content in Markdown (ideal for Content)

Markdown's overriding design goal is to be as human readable as possible where markdown text published on its own is still readable as-is and can be easily written in any text editor, without the need for any Visual HTML designer. These properties make Markdown the choice language to capture and maintain user content as done in many popular sites including StackOverflow and GitHub.

Include Partial Markdown views in Razor pages

As we expect Razor + Markdown to be an increasingly popular combination we've extend @Html.PartialMarkdown() support to also embed Partials from Markdown pages inside Razor Views. This feature lets you embed any Markdown Page as we've done in each of the content-heavy Rockstar pages using the Razor syntax below:


    @Html.PartialMarkdown("Content")
    

Which tells ServiceStack to embed a Partial named Content.md inside the page at that location. Initially it searches the current directory, followed by any matching Partials in the /Views/Shared folder. If you wanted to render a Markdown string instead you can use @Html.RenderMarkdown(), e.g:


    @Html.RenderMarkdown("## Heading")
    

Optimized for developer productivity

One of the areas where dynamic languages are holding over .NET is with fast iteration times enabling quick dev cycles. Whilst compilation times increase with every new page and class added to an ASP .NET Web project, many popular dynamic languages are experimenting with Live Reloading letting them quickly see changes in their browser after hitting Ctrl+S. Iteration times are one of the areas in most need of TLC in .NET and it's something we aim to optimize as much as possible without sacrificing run-time performance by maintaining 2 modes: 'Debug' (Development) optimized for start times and a 'Release' (Deployment) mode optimized for runtime performance. This mode is automatically inferred by ServiceStack on Start-up but is overridable with:


    SetConfig(new HostConfig {
        DebugMode = true,
    });
    

Future developer productivity enhancements

Optimizing for Single Page Apps

One way we're currently improving the situation (that also provides a better UX for end-users) has been focusing on making ServiceStack the ideal platform for Single Page Apps - to this end, we're already shipping many best-of-class features and since Single Page Apps rely on client-side views for rendering, they escape the .NET compilation tax.

With the latest release of WebStorm, JetBrains gives us a glimpse into the development experience of Live Editing where they showcase the instant feedback loop possible when developing a rich client-side AngularJS App With WebStorm and Chrome.

With this release of MVC Razor support, ServiceStack is a complete and integrated Web and Web Service Framework where we're able to simplify Web and Web Service development using just Services and Razor for generating HTML UIs.

ServiceStackVS Single Page App Templates

Included in ServiceStackVS are Single Page App templates for the most popular client-side frameworks: React and AngularJS, our exciting React Desktop Apps template takes this one step further and provides all the tools to package your ASP.NET React Web App into an Winforms, OSX Cocoa and Linux/Win/OSX Console App We'll continue to improve this story and ensure first-class support for advanced Web App features with integration with SPA Routing frameworks, which has always awkward to be able to do in MVC.

Implementation

AppHost /Startup.cs

In every ServiceStack web service there is a single AppHost which contains all your services configuration and registration (in code). The source for the Razor Rockstars AppHost is below, it performs the following things in this order:

  1. Tells ServiceStack which Assemblies to scan for registering existing services
  2. Register the MVC Razor Plugin (requires .NET 4.5)
  3. Register which DB to use - Razor Rockstars uses OrmLite + Sqlite (32bit/Mono compat)
  4. Create the Rockstar table if it doesn't already exist and insert all Seed Data
  5. Override ServiceStack's 404 Handler with the /NotFound.cshtml Razor page
ServiceStack/5.121 NetCore/Linux