Westwind.AspNetCore.Markdown
An ASP.NET Core Markdown support library that provides Markdown parsing, a Markdown TagHelper and Markdown Page Handler Middleware
Install / Use
/learn @RickStrahl/Westwind.AspNetCore.MarkdownREADME
ASP.NET Core Markdown Support
![]()
This small package provides Markdown support for your ASP.NET Core applications. It has the following features:
- Markdown Parsing
- Parse Markdown to HTML Strings
Markdown.Parse(markdown)
@Markdown.ParseHtmlString(markdown) - Parse Markdown from Files
Markdown.ParseFromFile("~/MarkdownPartial.md")
Markdown.ParseFromFileAsync("~/MarkdownPartial.md")
Markdown.ParseHtmlStringFromFile("~/MarkdownPartial.md") - Parse Markdown from Urls
Markdown.ParseFromUrl("https://github.com/RickStrahl/Westwind.AspNetCore.Markdown/raw/master/readme.md")
Markdown.ParseFromUrlAsync("https://github.com/RickStrahl/Westwind.AspNetCore.Markdown/raw/master/readme.md") - Configurable Markdown Parser
Plug in your own or customize the Markdown Parser viaIMarkdownParserFactoryandIMarkdownParser
- Parse Markdown to HTML Strings
- Markdown TagHelper
- Embed Markdown text into Views and Pages
- Databind Model data as Markdown text via markdown attribute
- Render Markdown from files via filename attribute
- Supports white space normalization
- Markdown Page Processor Middleware
- Serve
.mdfiles as Markdown - Serve mapped extensionless URLs as Markdown
- Configure a Razor template to customize Markdown Page Container UI
- Serve
- Configuration and Support Features
- Uses the awesome MarkDig Markdown Parser by default
- Customizable Markdown Parsing Pipeline for Markdig
- Pluggable Markdown Parser Support
- Basic HTML Sanitation support built in
- RenderExtensions to inject custom functionality
Related links:
Installing the NuGet Package
You can install the package from NuGet in Visual Studio or from the command line:
PM> install-package westwind.aspnetcore.markdown
or the dotnet command line:
dotnet add package westwind.aspnetcore.markdown
Startup Configuration
To use these components you need to add the following to your Startup class at minimum. The following is for ASP.NET Core 3.0 and later using endpoint routing:
public void ConfigureServices(IServiceCollection services)
{
services.AddMarkdown();
// We need to use MVC so we can use a Razor Configuration Template
services.AddMvc()
// have to let MVC know we have a controller
.AddApplicationPart(typeof(MarkdownPageProcessorMiddleware).Assembly);
}
public void Configure(IApplicationBuilder app)
{
// if you use default files make sure you do it before markdown middleware
app.UseDefaultFiles(new DefaultFilesOptions()
{
DefaultFileNames = new List<string> { "index.md", "index.html" }
});
app.UseMarkdown();
app.UseStaticFiles();
// the following enables MVC and Razor Pages
app.UseRouting();
app.UseEndpoints(endpoints =>
{
// endpoints.MapRazorPages(); // optional
// MVC routing is required
endpoints.MapDefaultControllerRoute();
});
}
There are additional configuration options for the AddMarkdown() method available which are discussed in more detail later.
Configuration is optional Static
Markdownmethods or the TagHelperNote the above configuration is required only if you use the Markdown Middleware that processes loose Markdown pages. If you use the static Markdown functions or the TagHelper and you don't need custom Markdown configuration of the Markdown Parser, configuration is not required.
Markdown Parsing Helpers
At it's simplest this component provides Markdown parsing that you can use to convert Markdown text to HTML either inside of application code, or inside of Razor expressions.
Markdown to String
string html = Markdown.Parse(markdownText);
Markdown to Razor Html String
<div>@Markdown.ParseHtmlString(Model.ProductInfoMarkdown)</div>
Parse Markdown to String from a File
You can also convert Markdown using a file:
var html = Markdown.ParseFromFile("~/EmbeddedMarkdownContent.md");
// async
html = await Markdown.ParseFromFileAsync("~/EmbeddedMarkdownContent.md");
To embed in Razor Views:
@Markdown.ParseHtmlStringFromFile("~/EmbeddedMarkdownContent.md")
Parse Markdown to String from a Url
You can also load Markdown from a URL as long as it's openly accessible via a URL:
// sync
parsedHtml = Markdown.ParseFromUrl("https://github.com/RickStrahl/Westwind.AspNetCore.Markdown/raw/master/readme.md")
// async
parsedHtml = await Markdown.ParseFromUrlAsync("https://github.com/RickStrahl/Westwind.AspNetCore.Markdown/raw/master/readme.md");
HtmlString versions are also available of this method.
SanitizeHtml in Parser Methods to mitigate XSS
Both of the above methods include a few optional parameters including a sanitizeHtml parameter which defaults to false. If set to true any <script> tags that are not embedded inside of inline or fenced code blocks are stripped. Additionally any reference to javascript: inside of a tag is replaced with unsupported: rendering the script non-functional.
string html = Markdown.Parse(markdownText, sanitizeHtml: true)
MarkDig Pipeline Configuration
This component uses the MarkDig Markdown Parser which allows for explicit feature configuration via many of its built-in extensions. The default configuration enables the most commonly used Markdown features and defaults to Github Flavored Markdown for most settings.
If you need to customize what features are supported you can override the pipeline creation explicitly in the Startup.ConfigureServices() method:
services.AddMarkdown(config =>
{
// Create custom MarkdigPipeline
// using MarkDig; for extension methods
config.ConfigureMarkdigPipeline = builder =>
{
builder.UseEmphasisExtras(Markdig.Extensions.EmphasisExtras.EmphasisExtraOptions.Default)
.UsePipeTables()
.UseGridTables()
.UseAutoIdentifiers(AutoIdentifierOptions.GitHub) // Headers get id="name"
.UseAutoLinks() // URLs are parsed into anchors
.UseAbbreviations()
.UseYamlFrontMatter()
.UseEmojiAndSmiley(true)
.UseListExtras()
.UseFigures()
.UseTaskLists()
.UseCustomContainers()
.UseGenericAttributes();
//.DisableHtml(); // don't render HTML - encode as text
};
});
When set this configuration is used every time the Markdown parser instance is created instead of the default behavior.
Markdown TagHelper
The Markdown TagHelper allows you to embed static Markdown content into a <markdown> tag. The TagHelper supports both embedded content, or an attribute based value assignment or model binding via the markdown attribute.
To get started with the Markdown TagHelper you need to do the following:
- Register TagHelper in
_ViewImports.cshtml - Place a
<markdown>TagHelper on the page - Use
Markdown.ParseHtmlString()in Razor Page expressions - Rock on!
After installing the NuGet package you have to register the tag helper so MVC can find it. The easiest way to do this is to add it to the _ViewImports.cshtml file in your Views\Shared folder for MVC or the root for your Pages folder.
@addTagHelper *, Westwind.AspNetCore.Markdown
Literal Markdown Content
To use the literal content control you can simply place your Markdown text between the opening and closing <markdown> tags:
<markdown>
#### This is Markdown text inside of a Markdown block
* Item 1
* Item 2
### Dynamic Data is supported:
The current Time is: @DateTime.Now.ToString("HH:mm:ss")
```cs
// this c# is a code block
for (int i = 0; i < lines.Length; i++)
{
line1 = lines[i];
if (!string.IsNullOrEmpty(line1))
break;
}
```
</markdown>
The TagHelper turns the Markdown text into HTML, in place of the TagHelper content.
Razor Expression Evaluation
Note that Razor expressions in the markdown content are supported - as the
@DateTime.Now.ToString()expression in the example - and are expanded before the content is parsed by the TagHelper. This means you can embed dynamic values into the markdown content which gives you most of the flexibilty of Razor code now in Markdown. Embedded expressions are not automatically HTML encoded as they are embedded into the Markdown. Additionally you can also generate additional Markdown as part of a Razor expression to make the Markdown even more dynamic.
TagHelper Attributes
filename
You can specify a filename to pull Markdown from and render into HTML. Files can be referenced:
- Physical paths:
/temp/somefile.md - Relative paths:
somefolder/somefile.md- relative to current page - Virtual paths:
~/somefolder/somefile.md- relative to site root
Relative File Links load resources as *Host Page Relativ
Related Skills
openhue
333.7kControl Philips Hue lights and scenes via the OpenHue CLI.
sag
333.7kElevenLabs text-to-speech with mac-style say UX.
weather
333.7kGet current weather and forecasts via wttr.in or Open-Meteo
tweakcc
1.4kCustomize Claude Code's system prompts, create custom toolsets, input pattern highlighters, themes/thinking verbs/spinners, customize input box & user message styling, support AGENTS.md, unlock private/unreleased features, and much more. Supports both native/npm installs on all platforms.
