sebnilsson.com | Liquid Development Is What I Do
Seb Nilsson

KeyLocks: Lock .NET/C#-code on Specific Values

If you've ever needed to ensure that multiple threads are not running the same code, you've probably used a lock-statement in your .NET/C#-code.

Sometimes a general lock can be too aggressive and lock too much running code for too long. You can solve this by cleverly locking on unique objects, but that handling is complex, error-prone and can become tedious.

Many times you know that you have a specific value or ID which is the key you want to lock on. For instance, you might want your code to not write to the database from multiple actions performed in parallel on your web-application. Using the Nuget-package KeyLocks will give you easy to write syntax to handle this:

private static KeyLock<string> _keyLock = new KeyLock<string>();

public void Main()
{
    Parallel.Invoke(
        () => { UpdateData("entity-123", "First new value"); },
        () => { UpdateData("entity-123", "Second new value"); }, // This will await line above
        () => { UpdateData("another-entity-456", "Another new value"); },        
        () => { UpdateData("yet-another-entity-789", "Yet another new value"); });
}

private void UpdateData(string id, string value)
{
    _keyLock.RunWithLock(id, () =>
    {
        // Execute locked code
    });
}

Make sure the instance of KeyLock<T> is shared between threads executing the code you want to lock on. In this case I solved it by making the instance static, and therefor shared across all instances of the code using it.

The package also contains the type NameLock is a short-hand term for KeyLock<string>. It defaults to being case-sensitive, but that can be changed by passing the correct IEqualityComparer<T> as a constructor-argument like this:

var nameLock = new NameLock(StringComparer.InvariantCultureIgnoreCase)

See the README-file on GitHub for the latest detailed information about KeyLocks. Or try it out through Nuget by running Install-Package KeyLocks in your project. You can even follow the absolutely latest build on MyGet.

ASP.NET Core MVC SEO-Framework

Following my last post on my ASP.NET MVC SEO-Framework I started looking at adding support also for ASP.NET Core MVC, with its superior Dependency Injection and Tag Helpers.

The previous post shows examples on how to use attributes to set SEO-specific values for Controller-Actions and in Views, which is also used in ASP.NET Core MVC. What is new to Core MVC is how you register the SEO-helper as a Service for Dependency Injection and use Tag Helpers instead of HTML Helpers.

To register the SEO-helper as a service for Dependency Injection you just need to use the framework's provided extension-method in the ConfigureServices-method inside Startup.cs:

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddMvc();

        services.AddSeoHelper();
    }
}

These SEO-values can easily be accessed and rendered as HTML-tags inside Views through provided Tag Helpers:

<head>
    <seo-title />

    <seo-link-canonical />
    <seo-meta-description />
    <seo-meta-keywords />
    <seo-meta-robots-index />
</head>

To access these Tag Helpers you need to reference them in you _ViewImports.cshtml:

@addTagHelper *, AspNetSeo.CoreMvc
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

See the README-file on GitHub for the latest detailed information about this ASP.NET SEO-framework. Or try it out through Nuget by running Install-Package AspNetSeo.CoreMvc or Install-Package AspNetSeo.Mvc in your project. You can even follow the absolutely latest build on MyGet.

ASP.NET MVC SEO-Framework

For any serious web-application you should always implement a solid Search engine optimization-strategy, but there is no standardized way to handle this in ASP.NET MVC, out of the box.

You could easily use the ViewBag-object to send dynamic values from Controller-Actions into Views, like this, for example:

public ActionResult Index()
{
    this.ViewBag.PageTitle = "This is the page title";

    return this.View();
}

Then you'd have to make sure you correctly spell or copy-paste ViewBag.PageTitle correctly into your View:

<head>
    <title>@ViewBag.PageTitle</title>
    <!-- More head-values -->
</head>

One problem is that if you refactor the naming for ViewBag.PageTitle into, for example ViewBag.Title, this will break the functionality, potentially website-wide, because you won't get any tooling-help from Visual Studio for that rename.

This is why I created a framework for ASP.NET MVC SEO, to get structured and reusable functionality around the SEO-data for a web-application. The framework is available on Nuget, with the source-code on GitHub.

Setting SEO-values

You can set SEO-values using the properties on a SeoHelper-object in Controller-Actions and Views, or you can use ActionFilter-attributes in Controllers, to set SEO-related data like:

  • Meta-Description
  • Meta-Keywords
  • Title, split on page-title and base-title (website-title)
  • Canonical Link
  • Meta No-index for robots

This can be done inside Controllers and Controller-Actions:

[SeoBaseTitle("Website name")]
public class InfoController : SeoController
{
    [SeoTitle("Listing items")]
    [SeoMetaDescription("List of the company's product-items")]
    public ActionResult List()
    {
        var list = this.GetList();

        if (list.Any())
        {
            this.Seo.Title += $" (Total: {list.Count})";
            this.Seo.LinkCanonical = "~/pages/list.html";
        }
        else
        {
            this.Seo.MetaRobotsNoIndex = true;
        }

        return this.View(model);
    }
}

If you don't want to inherit from SeoController to get access to the this.Seo-property, you can use the extension-method GetSeoHelper:

public class InfoController : Controller
{
    public ActionResult List()
    {
        var seo = this.GetSeoHelper();

        seo.Title = "Page title";

        return this.View(model);
    }
}

You can even set SEO-values inside Views:

@{
    this.Layout = null;
    this.Seo.MetaRobotsNoIndex = true; // Always block Robots from indexing this View
}

Rendering SEO-values

These SEO-values can easily be accessed and rendered as HTML-tags inside Views through provided HtmlHelper-extensions:

<head>
    @Html.SeoTitle()

    @Html.SeoLinkCanonical()
    @Html.SeoMetaDescription()
    @Html.SeoMetaKeywords()
    @Html.SeoMetaRobotsIndex()
</head>

See the README-file on GitHub for the latest detailed information about this ASP.NET MVC SEO-framework. Or try it out through Nuget by running Install-Package AspNetSeo.Mvc in your project. You can even follow the absolutely latest build on MyGet.

ViewSource - View Source in Mobile Browsers

ViewSource Screenshot

Here's another small app that I created to play around with some code, but mostly because I felt I had a need for it.

ViewSource is an app for viewing the HTML-source of any website from your web-browser. Which enables you to view source from mobile browsers.

Just enter any URL and view the HTML-source. You also get a list of CSS-files and JavaScript-files, which you can view the source of, instantly in your browser.

You can quickly reach the app through bit.ly/vsource.

Fork on GitHub

As always, the source is available on GitHub for forking.

Squishify - Minify JavaScript & CSS Online

Squishify Screenshot

Squishify was created out of the need of a minifier for JavaScript. I quickly put together a web-app on AppHarbor to make minification always available quickly. The code is hosted on GitHub.

The application is an ASP.NET MVC-app, using Justin Etheredge's framework for minification called SquishIt. The app also uses ASP.NET Web API together with some simple jQuery to display the results of the minifications without any page-reloads.

The SquishIt-framework is a very easy to use and provides multiple minifiers for both JavaScript and CSS.

JavaScript minifiers:

* At the moment of writing this post, Google Closure is not working as expected, but should hopefully work soon.

CSS minifiers:

Enjoy it at squishify.apphb.com and fork it on GitHub.