Serving DocFX Static Site From .NET With Authentication

bazen

Bazen

Posted on June 16, 2021

Serving DocFX Static Site From .NET With Authentication

DocFX is a static site generator from source code files and markdown. Its primary use is for documentation. However, it is essential to mention that it is flexible and is applicable for many different purposes. Some use it for blogging and profile sites. It is really up to you to define what to use it for. For more information on DocFX you can visit their official website.

Why Serve It From .NET?

There are different advantages to serving the static site generated by DocFX from .NET since it allows adding different functionalities on top of the static site. One practical advantage is adding authentication to access the static site. The reason for adding the authentication could be that you have internal documentation within your company and want it to be accessible only by authorized persons. This scenario is only to demonstrate a practical use case, & the use case can be different depending on your scenario.

Pre-request

  1. IdentityServer4: For authentication
  2. DocFX: For generating static site
  3. Add DocFX to environment variable for smooth build process

I used IdentityServer4 for authentication in this article, however this implementation works fine with other methods of authentications as well.

Setting up IdentityServer4

Create IdentityServer4 project



dotnet new is4inmem -n Identity


Enter fullscreen mode Exit fullscreen mode

The templates for IdentityServer4 projects is available on IdentityServer's Github repo. After creating the identity project we don't need to make further change.

Setting up Static site server

Create ASP.NET Api project



dotnet new webapi -n StaticSiteServer


Enter fullscreen mode Exit fullscreen mode

Add reference to Microsoft.AspNetCore.Authentication.OpenIdConnect NuGet package.

There are a couple of changes to be made here and there when setting up the authentication. Not to go off topic, I will not cover that in this article. However, the source code can be found in my Github repository.

Setting up static site

In the same directory as StaticSiteServer create static site project:



docfx init -q -o Docs


Enter fullscreen mode Exit fullscreen mode

Setting up the build process

Let's update StaticSiteServer.csproj to define the root directory of the DocFX file system:



<PropertyGroup>
      .
      .
      .
    <DocFXRoot>Docs\</DocFXRoot>
</PropertyGroup>


Enter fullscreen mode Exit fullscreen mode

Next, let's update the StaticSiteServer.csproj to generate static site on both during build & publish.



<ItemGroup>
  <Content Remove="$(DocFXRoot)**" />
  <None Remove="$(DocFXRoot)**" />
  <None Include="$(DocFXRoot)**" Exclude="$(DocFXRoot)_site\**" />
</ItemGroup>
<Target Name="DebugEnsureDocFXEnv" BeforeTargets="Build" Condition=" '$(Configuration)' == 'Debug' And !Exists('$(DocFXRoot)node_modules') ">
  <Exec Command="docfx --version" ContinueOnError="true">
    <Output TaskParameter="ExitCode" PropertyName="ErrorCode"/>
  </Exec>
  <Error Condition="'$(ErrorCode)' != '0'" Text="DocFX is required to build and run this project. To continue, please install DocFX from https://github.com/dotnet/docfx/releases, and then restart your command prompt or IDE." />
  <Message Importance="high" Text="Generate static sites from Markdown and code files. This may take several minutes..." />
  <Exec WorkingDirectory="$(DocFXRoot)" Command="docfx build"/>
</Target>
<Target Name="PublishRunWebpack" AfterTargets="ComputeFilesToPublish">
  <Exec WorkingDirectory="$(DocFXRoot)" Command="docfx build"/>
  <ItemGroup>
    <DistFiles Include="$(DocFXRoot)_site\**" />
    <ResolvedFileToPublish Include="@(DistFiles->'%(FullPath)')" Exclude="@(ResolvedFileToPublish)">
      <RelativePath>%(DistFiles.Identity)</RelativePath>
      <CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
      <ExcludeFromSingleFile>true</ExcludeFromSingleFile>
    </ResolvedFileToPublish>
  </ItemGroup>
</Target>  


Enter fullscreen mode Exit fullscreen mode

Now, with these changes, the build will generate the static site. However, the StaticSiteSeserved web API is not serving the static site. To server the static site, let's update the ConfigureServices method in the Startup.cs file. Moreover, we will add authorization:



public void ConfigureServices(IServiceCollection services) {
    .
    .
    .
    services.AddAuthorization(options => {
        options.FallbackPolicy = new
        AuthorizationPolicyBuilder()
            .RequireAuthenticatedUser()
            .Build();
    });
    .
    .
    .
}


Enter fullscreen mode Exit fullscreen mode

Again in the Startup.cs file let's update the Configure method to serve static files.



public void Configure(IApplicationBuilder app, IWebHostEnvironment env) {
    .
    .
    .
    app.UseFileServer(new FileServerOptions {
        FileProvider = new
        PhysicalFileProvider(
            Path.Combine(env.ContentRootPath,
                "Docs", "_site")),
    });
    .
    .
    .
}


Enter fullscreen mode Exit fullscreen mode

NOTE app.UseFileServer* must be added after app.UseAuthentication() and app.UseAuthorization().

That's it. When accessing the StaticSiteServer, the user is redirected for authentication. After authenticating, the user can access the static site, as shown below:

1. StaticSiteServer
Alt StaticSiteServer

2. Authentication page
Alt Authentication page

3. Documentation static site
Alt Documentation static site1

4. Documentation static site
Alt Documentation static site2

Complete source code can be found on Github

Thanks for reading, cheers!

💖 💪 🙅 🚩
bazen
Bazen

Posted on June 16, 2021

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related