.Net Core Copyright tag helper

I've created a simple copyright tag helper for .Net Core that will read your version information from appsettings.json

I used to use the AssemblyInfo.cs file to extract the version number but .Net Core as removed that file. That's ok though because we can stick our version information into the appsettings file and can get a strongly typed version information with IOptions.

Step 1: Create the node in appsettings.json like so:

"Version": {
    "Company": "Your Co",
    "Major": 2018,
    "Minor": 3,
    "Build": 3,
    "Revision": 1923

Step 2: Create a matching configuration/options cs file:

public class VersionConfiguration
	public int Major { get; set; }

	public int Minor { get; set; }

	public int Build { get; set; }

	public int Revision { get; set; }

	public string Company { get; set; }

Step 3: Register the configuration in ConfigureServices in Startup.cs:


Step 4: Create a TagHelper that takes an IOptions<VersionConfiguration> in the constructor. .Net Core will handle the injection here.

public class CopyrightTagHelper : TagHelper
	private readonly VersionConfiguration _version;

	public CopyrightTagHelper(IOptions versionConfiguration)
		_version = versionConfiguration.Value;

	public override void Process(TagHelperContext context, TagHelperOutput output)
		output.TagName = "p";
			.SetHtmlContent($"{_version.Company} &copy; {DateTime.UtcNow.Year} Version: {_version.Major}.{_version.Minor:00}.{_version.Build:00}.{_version.Revision:0000}"

Final Step: Put the tag helper in the footer of your app.


That's it you're all done! Just change the information in appsettings and the tag helper will do the rest.

.Net Core error pages per area

I’m working on a new .Net Core MVC project where I have a front facing site and an area called “App” where signed up users will spend their time.

The default OTB .net core project has the following in Startup.cs


if (env.IsDevelopment())

The problem with this approach is that first there’s no 404 catching as that’s not technically an exception and secondly, my front facing site and App area have two very different layouts. What happens then, is that if an exception occurs under App the user will get redirect to the supplied path making it difficult to get back to the App section.

Read More

ActionMailer for MVC 5.3

I've used ActionMailer.Net by Scott Anderson for a long time. That is, until he stopped supporting it. Fortunately, Crossvertise decided to pick up the torch and carry it a while longer. Crossvertise’s repo of ActionMailerNext has made some improvements over the years and has provided Mandrill and Sendgrid api support.

For those unfamiliar with it, ActionMailer is a .Net mailer library that allows the use of Razor views to send templated emails. You can pass models and view data into a View to fully script your transactional emails. Crossvertise’s supports both HTML and plain text variants and will automatically send one or both.

Unfortunately, the latest version ActionMailerNext.Mvc5-2 NuGet package includes dependencies on a Mandrill package and a Sendgrid package. It also is targeted at MVC 5.2 instead of 5.3.

I was recently challenged that if you don’t like something in Open Source…. FIX IT! 

So I did. 

As of this writing, my PR is still pending but as I wanted to use it in a timelier fashion, I’ve published the NuGet package myself. If Crossvertise elects to merge my PR, they are welcome to ownership of the package, however until such time: enjoy.


PM> Install-Package ActionMailerNext.Mvc5-3

Two Level Multi-Tenancy Part 2

This is part two of my series on Two Level Multi-Tenancy. You’ll probably want to read part one first.

Last time, we looked at how to use the subdomain as part of our multi-tenant MVC application and how to bring that together. Now, we’re going to look at adding the secondary layer.

For this project, we ended up with three base model classes. A base model that adds Id and DateAdded, a First Level base model that has the Level1Id, and now our Second Level base model that add an Id field for Level2 models.

Each of our EF models then inherit from the Level2 base model with the exception of that model class that inherits from the Level1 model. And so all models inherit from the Level1 base model, which will cause all of them to have our Level1 Id field.

Our routes at this point look like subdomain.domain.com/Level2/Thing/Create. The project has a helper method that pulls the Level2 value from the route.

I also added another base controller, which again inherits from our Level1 base controller we set up in part 1.

public class Level2BaseController : Level1BaseController
    protected string Level2Name => GetFromRoute();

    protected override void OnActionExecuting(ActionExecutingContext filterContext)
        if (string.IsNullOrEmpty(Level2Name))
            filterContext.Result = RedirectToAction("Index", "Home");

        var identity = Thread.CurrentPrincipal.Identity as ClaimsIdentity;
        if (!identity.IsAuthenticated) return;
        var claim = identity.Claims.FirstOrDefault(c => c.Type == CustomClaims.Level2Id);
        if (claim == null || (claim.Value != Sessions.Level2Id.ToString())) Users.AddL2Claim(Level2Name);

Read More

Two Level Multi-Tenancy Part 1

Recently, I’ve been working on a multi-tenancy project. Like most projects I tend to gravitate towards, it wasn’t that simple.

For those of you who know don’t know what that means, multi-tenancy is when an application is designed to be used by multiple companies/users at the same time, keeping all data separated from each other.

Typically if you want something like this done, you add a ClientId or some other restriction to your Models to help identify which tenant that Thing belongs to.

In the world of Entity Framework, you’d probably do Thing.Where(x => x.ClientId == clientId). You’d do this for each select statement, each update, and each delete to verify that the client that was logged in had the correct permissions to that resource. That’s boring, annoying, tedious and prone to errors.

Enter stage left comes Entity Framework interceptors. EF interceptors do what you’d expect them to do and intercept your EF queries before they hit the SQL server. Because they do this, it is possible to manipulate or log those queries.

Following some code by Charalampos Karypidis, I was able to get the basics setup. Because the rest of this article is an expansion of Charalampos’ code, I’ll not be reposting parts of his code that I didn’t change. You’ll want to go read and understand his article (or get the code on GitHub) before continuing. 

Where I part from Charalampos’ code is where I think things get interesting. Charalampos’ setup involves using the interceptor to assign TenantId to the UserId. That’s all fine and well, but what if there is actually a group of individuals all utilizing the same Tenant?

Read More

Resharper Magic Tricks

Last week, I gave a presentation at the GSP Developers’ Guild’s monthly meeting where I talked about some of the cool (maybe hidden) things that ReSharper can do for you. In this article I’m going to summarize my talk and give links to where you can get the Custom Live Templates, and Extensions. I realize that this post is lessened by not having some of the visuals (no projector, etc).


ReSharper Intro


ReSharper can do some really cool things. 


ReSharper can bulk fix code style issues like variable names conventions.




Code completion is made easier and code simplification is highlighted.


It  can also help with if statement nesting or showing you extra code that can be reduced.


New to Resharper 9 is finding references on NuGet. I referenced a type from MomentSharp - a DateTime library that I wrote - but I don’t have it referenced in the project. I can use the light blub or Alt + Enter and “Find this type on nuget.org”.


Also new to ReSharper 9 is support for C# 6 features like string interpolation.

Read More

Making Bookmarklets Cool Again

At some point Bookmarklets died and no one played their dirge.


If you don’t know what a bookmarklet is, it’s a small piece of javascript code embedded in a bookmark. In some cases, the script injects a javascript file into the the website where the bookmark was clicked. This injection is makes them super useful but is probably also what made them disappear. 


XSS (Cross-site scripting) is a topic for another day, but you should beware of it you're not. Go look it up, I’ll wait. No really, this article will still be here when you get back.


In the past few weeks, I’ve been creating some interesting bookmarklets to help with my web development. Some of these I’ve found, others I’ve created (mine). To use them, simply drag each headings link to your bookmark bar.


Last Modified:




Want to know the last time an asset was updated? Do note that this bookmarklet only works with static content. It won’t work on server side rendered content like Asp.Net or PHP. If the alert shows you today, right now, it’s most likely dynamically generated.


Read More

Magical one page telerik reporting viewer

In an effort to simplify a project that used Telerik’s Reporting Engine, I wanted to create a single View that listed the available reports and a single View to hold the HTML Report Viewer. In the middle of the project a new requirement was added; you know how that goes. Some reports needed to be able to have querystring parameters come from a related View. This is how I did it. Behold the magic.


First I built my View to list the reports. Each report had a link like this:


@Html.ActionLink("Click Me", "Report", 
    new { title = "Report Title", path = "Namespace.Path.To.Report" }, 
    new { target = "_blank", @class = "btn btn-primary" })


You can get the Namespace path from the code behind file of the report.


Set up an ActionResult like this:


public ActionResult Report(string path, string title)


    ViewBag.ReportPath = path + ", ProjectNS";

    ViewBag.Title = title;

    return View();



ProjectNS should be your root Namespace. 


Read More

Using Grunt to JSHint and JSCS your JavaScript code.

This is part 2 to my last post, which you’ll want to read first since I’m going to assume some of your gruntfile.js has some necessary settings.


Using Grunt to JSHint (Code Quality) and jscs (Code Style checker) your JavaScript code.


In this post, I'm going to show you how to get Gruntjs to check your JavaScript Code for quality in Visual Studio 2015.


Add this to your package.json file.


"grunt-jscs": "latest",
"grunt-contrib-jshint": "latest"


This will add JSCS and JSHint to your node_modules folder and let us run our tasks.






to gruntfile.js at the bottom with the rest of your loadNpmTasks


Read More

How to get Grunt to compile your LESS files on save, and at build, in VS 2015.

I’m trying out Visual Studio (VS) 2015, which at the time of this writing, is in RC. Like most developers, the first thing I do with a shiny new VS is to install my tools and plugins. Of course I got Resharper (R#) installed and the PostFix Templates extension for R# installed.


Lately, I’ve been playing around with Win 8/10 JS apps that I’ve started in VS 2015, but I hadn’t opened any existing applications in VS 2015 since I work on some team projects. VS 2013 had one-way project upgrading and I had some issues with a previous team where not everyone was on the same version of VS.


Today, I had both VS 2013 and 2015 opened at the same time. This caused some issues with R#’s licensing platform so I made the leap and opened one of my web projects in VS 2015.


Let me back up a little: since I mostly do web development, I work with LESS quite a bit. Once upon a time I used a Post Build event to execute an npm command to compile my LESS files. As most web developers do, I have Web Essentials (WE) installed and at some point it finally stopped giving me issues with Bootstrap’s LESS files.


Moving forward: I had opened a web application in VS 15 and tried to save a LESS file. I noticed that it didn’t recompile the LESS file to CSS. That’s when I noticed that I had forgotten to install WE! Off to the VS Extension Manager! What’s this? WE installed and in this version, they’ve stripped the compilers out.


Which brings me to writing this post:


How to get Grunt to compile your LESS files on save, and at build, in VS 2015.


Read More

About Me

Hello, I’m Jonathan Peterson (aka Eonasdan)! I’m a web developer and CEO of Paladin Cloudware.

I have over 11 years of experience developing a wide array of web applications and websites. In my free time, I contribute to several open source projects.

As a die-hard developer, you’ll find me programming in my head on the rare occasions when I'm without an Internet connection.

Find me on:


telerik, MVC, Entity Framework, ReSharper, Tips And Tricks, less, grunt, C#, visual studio, code quality, NuGet, visual studio 2015