Viae.Fluid.Markdown.Mvc 0.1.1-g4645b0a

This is a prerelease version of Viae.Fluid.Markdown.Mvc.
There is a newer version of this package available.
See the version list below for details.
dotnet add package Viae.Fluid.Markdown.Mvc --version 0.1.1-g4645b0a
                    
NuGet\Install-Package Viae.Fluid.Markdown.Mvc -Version 0.1.1-g4645b0a
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Viae.Fluid.Markdown.Mvc" Version="0.1.1-g4645b0a" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Viae.Fluid.Markdown.Mvc" Version="0.1.1-g4645b0a" />
                    
Directory.Packages.props
<PackageReference Include="Viae.Fluid.Markdown.Mvc" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Viae.Fluid.Markdown.Mvc --version 0.1.1-g4645b0a
                    
#r "nuget: Viae.Fluid.Markdown.Mvc, 0.1.1-g4645b0a"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Viae.Fluid.Markdown.Mvc@0.1.1-g4645b0a
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Viae.Fluid.Markdown.Mvc&version=0.1.1-g4645b0a&prerelease
                    
Install as a Cake Addin
#tool nuget:?package=Viae.Fluid.Markdown.Mvc&version=0.1.1-g4645b0a&prerelease
                    
Install as a Cake Tool

Viae.Fluid.Markdown.Mvc

ASP.NET MVC integration library for Viae.Fluid.Markdown, enabling seamless Markdown rendering in Fluid MVC views with proper HTML encoding handling.

License: MIT .NET

Features

  • One-Line Setup - Single extension method configures everything
  • No Double-Encoding - Properly handles HTML content in Razor views
  • Fluent Configuration - Chain configuration with other Fluid MVC options
  • Full MVC Integration - Works seamlessly with Fluid.MvcViewEngine
  • Inherits Core Features - All Markdown features from Viae.Fluid.Markdown
  • Fully Documented - Complete XML documentation for IntelliSense

What's Different from Viae.Fluid.Markdown?

This library extends Viae.Fluid.Markdown with MVC-specific functionality:

Feature Viae.Fluid.Markdown Viae.Fluid.Markdown.Mvc
Target Framework .NET Standard 2.0 .NET 8.0+
Use Case Console apps, APIs, non-MVC ASP.NET MVC with Razor views
Output Type Plain string HtmlString / IHtmlContent
Double-Encoding Prevention No Yes
Integration Method Manual setup Fluent extension method
Dependencies Fluid.Core Fluid.MvcViewEngine

When to use this library: If you're building an ASP.NET MVC application with Fluid views and need to render Markdown content in Razor views without double-encoding issues.

When to use the core library: For console apps, APIs, or non-MVC scenarios where you need direct Markdown-to-HTML conversion.

Installation

dotnet add package Viae.Fluid.Markdown.Mvc

This package automatically includes Viae.Fluid.Markdown as a dependency.

Quick Start

Basic Setup

In your Program.cs:

using Viae.Fluid.Markdown.Mvc;

var builder = WebApplication.CreateBuilder(args);

// Add Fluid MVC with Markdown support
builder.Services.AddFluid(options =>
{
    // Add Markdown filters with default configuration (GitHub Flavored Markdown)
    options.AddFluidMarkdownFilters();
});

var app = builder.Build();
app.Run();

In Your Views

Create a Fluid view (e.g., Views/Post/Show.liquid):

<article>
    <h1>{{ post.title }}</h1>
    <div class="content">
        {{ post.content | markdown }}
    </div>
</article>

The Markdown will be rendered as HTML without double-encoding issues.

Custom Configuration

Configure the Markdig pipeline with specific extensions:

builder.Services.AddFluid(options =>
{
    options.AddFluidMarkdownFilters(opts =>
    {
        opts.ConfigurePipeline = builder => builder
            .UseAdvancedExtensions()      // GitHub Flavored Markdown
            .UseEmphasisExtras()           // Extra emphasis features
            .UseEmojiAndSmiley()          // Emoji support
            .UseDiagrams();                // Mermaid diagrams
    });
});

How It Works

The Double-Encoding Problem

When rendering Markdown in ASP.NET MVC Razor views, you can encounter double-encoding:


&lt;p&gt;&lt;strong&gt;Bold&lt;/strong&gt;&lt;/p&gt;


<p><strong>Bold</strong></p>

The Solution

This library solves the problem through three components:

  1. HtmlContentFluidValue: Wraps IHtmlContent to preserve HTML encoding semantics in Fluid
  2. Value Converter: Automatically converts IHtmlContent values to HtmlContentFluidValue
  3. MVC Adapter: Returns Markdown output as HtmlString instead of plain strings
// What AddFluidMarkdownFilters() does internally:

// 1. Register value converter for IHtmlContent
options.TemplateOptions.ValueConverters.Add(x =>
    x is IHtmlContent h ? new HtmlContentFluidValue(h) : null
);

// 2. Build Markdown pipeline
var pipeline = opts.ConfigurePipeline(new MarkdownPipelineBuilder()).Build();

// 3. Create renderer and filter
var renderer = new MarkdigMarkdownRenderer(pipeline);
var core = new MarkdownFilter(renderer);

// 4. Wrap in MVC adapter and register
var adapter = new MarkdownMvcAdapter(core);
adapter.Register(options.TemplateOptions);

API Reference

FluidMarkdownExtensions.AddFluidMarkdownFilters

public static FluidViewEngineOptions AddFluidMarkdownFilters(
    this FluidViewEngineOptions options,
    Action<MarkdownFilterOptions>? configure = null
)

Adds Markdown filters to Fluid MVC view engine with proper HTML encoding handling.

Parameters:

  • options - The FluidViewEngineOptions to configure
  • configure - Optional configuration action for customizing the Markdown pipeline

Returns: The configured FluidViewEngineOptions for fluent chaining

Example:

services.AddFluid(options =>
{
    options.AddFluidMarkdownFilters(opts =>
    {
        opts.ConfigurePipeline = b => b.UseAdvancedExtensions();
    });
});

HtmlContentFluidValue

A Fluid value wrapper for IHtmlContent that preserves HTML encoding semantics.

This class is used internally and you typically don't need to interact with it directly. It's automatically registered as a value converter when you call AddFluidMarkdownFilters().

Supported Markdown Features

All features from Viae.Fluid.Markdown are supported:

  • Basic Markdown: Bold, italic, headings, links, images, code blocks
  • Tables: Pipe tables and grid tables
  • Task Lists: - [ ] and - [x] checkboxes
  • Strikethrough: ~~text~~
  • Auto-identifiers for headings
  • Footnotes
  • Definition lists
  • Abbreviations
  • And more via Markdig's advanced extensions

Filter Names

Both filters are registered with two names for compatibility:

  • markdown - Standard filter name
  • markdownify - Jekyll/Liquid compatible alias

{{ content | markdown }}
{{ content | markdownify }}

Examples

Blog Post View


<!DOCTYPE html>
<html>
<head>
    <title>{{ post.title }}</title>
</head>
<body>
    <article>
        <header>
            <h1>{{ post.title }}</h1>
            <time>{{ post.publishedAt | date: "%B %d, %Y" }}</time>
        </header>

        <div class="excerpt">
            {{ post.excerpt | markdown }}
        </div>

        <div class="content">
            {{ post.content | markdown }}
        </div>

        <footer>
            <p>Tags: {{ post.tags | join: ", " }}</p>
        </footer>
    </article>
</body>
</html>

Documentation Page


<div class="documentation">
    <aside class="sidebar">
        {{ page.toc | markdown }}
    </aside>

    <main>
        {{ page.content | markdown }}
    </main>
</div>

Comment System


<div class="comment">
    <div class="comment-author">{{ comment.author }}</div>
    <div class="comment-body">
        {{ comment.body | markdown }}
    </div>
    <div class="comment-meta">{{ comment.createdAt | date: "%B %d, %Y" }}</div>
</div>

Custom Pipeline Example

// In Program.cs - Enable diagrams and emoji
builder.Services.AddFluid(options =>
{
    options.AddFluidMarkdownFilters(opts =>
    {
        opts.ConfigurePipeline = pipeline => pipeline
            .UseAdvancedExtensions()
            .UseEmojiAndSmiley()
            .UseDiagrams()
            .UseYamlFrontMatter();
    });
});

Then in views:

{{ post.content | markdown }}


Architecture

Component Relationships

Viae.Fluid.Markdown (core library)
├── IMarkdownRenderer
├── MarkdigMarkdownRenderer
├── MarkdownFilter
├── MarkdownMvcAdapter
└── MarkdownFilterOptions

Viae.Fluid.Markdown.Mvc (this library)
├── FluidMarkdownExtensions ──> Uses all components from core
└── HtmlContentFluidValue    ──> Wraps IHtmlContent for Fluid

Integration Flow

1. Application Startup
   └─> AddFluidMarkdownFilters() called
       ├─> Registers HtmlContentFluidValue converter
       ├─> Builds Markdig pipeline
       ├─> Creates MarkdownMvcAdapter
       └─> Registers filters with TemplateOptions

2. View Rendering
   └─> {{ content | markdown }}
       ├─> MarkdownMvcAdapter.InvokeAsync()
       ├─> MarkdownFilter renders to HTML string
       ├─> Wraps in HtmlString
       ├─> Converts to HtmlContentFluidValue
       └─> Writes to output without encoding

Dependencies

Target Framework

  • .NET 8.0+
  • .NET 10.0+

Testing

This library includes comprehensive test coverage with 46+ unit tests using MSTest and FluentAssertions:

cd tests/Viae.Fluid.Markdown.Mvc.Tests
dotnet test

Test Coverage:

  • HtmlContentFluidValueTests (24 tests) - Tests for the IHtmlContent wrapper

    • Constructor and null handling
    • Type system conversions (boolean, number, string)
    • Equality comparisons
    • WriteToAsync and HTML encoding preservation
    • Custom IHtmlContent implementations
  • FluidMarkdownExtensionsTests (22 tests) - Tests for the extension method

    • Filter registration (markdown, markdownify)
    • Value converter registration
    • Markdown rendering (basic and complex)
    • Custom pipeline configuration
    • All Markdown features (tables, task lists, links, code, etc.)
    • HTML encoding preservation (no double-encoding)
    • Null and empty input handling

All tests pass with zero warnings and follow DRY principles with shared test helpers.

Troubleshooting

Markdown is displayed as text instead of HTML

Problem: You see <p><strong>text</strong></p> in your browser instead of rendered HTML.

Solution: Make sure you're not using | escape or other encoding filters after | markdown:


{{ content | markdown | escape }}


{{ content | markdown }}

HTML is double-encoded in views

Problem: You see &lt;p&gt; instead of <p> tags.

Solution: Ensure you're using Viae.Fluid.Markdown.Mvc (not just Viae.Fluid.Markdown) and called AddFluidMarkdownFilters():

// Correct:
options.AddFluidMarkdownFilters();

Markdown features not working

Problem: Tables, task lists, or other features don't render.

Solution: Configure the pipeline with the extensions you need:

options.AddFluidMarkdownFilters(opts =>
{
    opts.ConfigurePipeline = b => b.UseAdvancedExtensions(); // Enables most features
});

Contributing

This library is part of the Viae project. Contributions are welcome!

License

This project is licensed under the MIT License - see the LICENSE file for details.

Credits

Support

For questions, issues, or feature requests:

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.1.5 242 10/29/2025
0.1.4-g74ff342 169 10/29/2025
0.1.3-g5a6d330 166 10/29/2025
0.1.2-gb6155a2 173 10/29/2025
0.1.1-g4645b0a 171 10/29/2025
0.0.0-dev.9.g4a5c5df 130 10/29/2025
0.0.0-dev.9 129 10/29/2025
0.0.0-dev.2.g07cad15 222 10/29/2025