2017-12-06

Convert C# Anonymous (or Any) Types Into Dynamic ExpandoObject

There are scenarios when you need to convert an anonymous type in C#, or any other type, into a dynamic, or more specifically to the underlying ExpandoObject-type.

My specific need was to be able to move the data from an anonymous type from the current assembly into a dynamically executed external assembly. So I created an extension-method for this, which moves all the properties from any object into a new ExpandoObject.

public static ExpandoObject ToExpandoObject(this object obj)
{
    // Null-check

    IDictionary expando = new ExpandoObject();

    foreach (PropertyDescriptor property in TypeDescriptor.GetProperties(obj.GetType()))
    {
        expando.Add(property.Name, property.GetValue(obj));
    }

    return (ExpandoObject) expando;
}

You can use the extension-method on any type of object and choose to reference the resulting type by it's actual type ExpandoObject or as a dynamic.

var anonymous = new {Id = 123, Text = "Abc123", Test = true};

dynamic dynamicObject = anonymous.ToExpandoObject();
ExpandoObject expandoObject = anonymous.ToExpandoObject();

Since the code uses the type System.ComponentModel.TypeDescriptor, if you use .NET Core or .NET Standard, you might need to reference the Nuget-package named System.ComponentModel.TypeConverter.

2017-11-30

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 regular 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 therefore 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.

2017-11-28

C# DateTime to RFC3339/ISO 8601

According to Wikipedia the date and time-format RFC3339/ISO 8601 usages includes:

On the Internet, the World Wide Web Consortium (W3C) uses ISO 8601 in defining a profile of the standard that restricts the supported date and time formats to reduce the chance of error and the complexity of software.

My specific need to format a System.DateTime-value in a RFC3339-format came when I used one of Google's REST APIs and they required a parameter in the RFC3339-format. Here is the code is the extension-method which provides the functionality of formatting a DateTime as a string in RFC3339-format:

public static string ToRfc3339String(this DateTime dateTime)
{
    return dateTime.ToString("yyyy-MM-dd'T'HH:mm:ss.fffzzz", DateTimeFormatInfo.InvariantInfo);
}

2017-11-24

Convert C# URI/URL to Absolute or Relative

There are many situations when you handle URLs or URIs in applications today, no matter if it's a web-application or not. Often you need to handle absolute URLs, like https://testsite.com/section/page, and relative URLs, like /section/page.html.

To easily convert URLs between absolute and relative, or just ensure these two formats, I created extension-methods for the type System.Uri, which allows you to write code like this:

var absoluteToRelative = new Uri("https://www.test-relative.com/customers/details.html").ToRelative();
// Outputs: "/customers/details.html"

var relativeToAbsolute = new Uri("/orders/id-123/", UriKind.Relative).ToAbsolute("https://www.test-absolute.com");
// Outputs: "https://www.test-absolute.com/orders/id-123/"

The extension-methods which makes this possible are the following:

public static string ToRelative(this Uri uri)
{
    // Null-check

    return uri.IsAbsoluteUri ? uri.PathAndQuery : uri.OriginalString;
}

public static string ToAbsolute(this Uri uri, string baseUrl)
{
    // Null-checks

    var baseUri = new Uri(baseUrl);

    return uri.ToAbsolute(baseUri);
}

public static string ToAbsolute(this Uri uri, Uri baseUri)
{
    // Null-checks

    var relative = uri.ToRelative();

    if (Uri.TryCreate(baseUri, relative, out var absolute))
    {
        return absolute.ToString();
    }

    return uri.IsAbsoluteUri ? uri.ToString() : null;
}

2017-11-20

Registering Autofac & AutoMapper Circularly

Have you ever wanted to register Autofac and AutoMapper circularly? By this I mean to do the inception of these two things, at the same time, in the same application:

  • Register AutoMapper's mappings through Autofac's component-registration for dependency-injection
  • Use registered components in Autofac for dependency-injection into AutoMapper's mapped objects

This is actually possible! It's done by providing AutoMapper with Autofac's IComponentContext-object, which is not dependent on if you've registered everything you need in the Autofac component-registrations, before configuring AutoMapper. So you can register more components after registering your AutoMapper-configuration and still access all these in your AutoMapper context when they get resolved later in your code.

We'll start with the code for registering the Autofac-components and follow it with some explaining:

public IContainer RegisterComponents()
{
    var builder = new ContainerBuilder();

    builder.RegisterType<PreMapperComponent>().As<IPreMapperComponent>();

    builder.Register(ConfigureMapper).SingleInstance();

    builder.RegisterType<PostMapperComponent>().As<IPostMapperComponent>();

    return builder.Build();
}

private IMapper ConfigureMapper(IComponentContext context)
{
    var configuration = new MapperConfiguration(config =>
    {
        var ctx = context.Resolve<IComponentContext>();

        config.CreateMap<EntityType, DtoType>()
            .ConstructUsing(_ =>
                new DtoType(ctx.Resolve<IPreMapperComponent>(), ctx.Resolve<IPostMapperComponent>()));
    });

    return configuration.CreateMapper();
}

The method RegisterComponents is included to show a somewhat realistic scenario, and for this case specifically showing that you can register components in Autofac both before and after configuring AutoMapper.

The code var ctx = context.Resolve<IComponentContext>() might look strange, but is crucial for this solution to work. Why not use the context-argument directly in the ConfigureMapper-method? Because it will throw an exception starting with This resolve operation has already ended, and instructs you to resolve IComponentContext again, which is what we're doing here.

Running the AutoMapper-code

Then we run the code using AutoMapper and the mapping of types needing dependency-injection of constructor-parameters:

public static void Run(IContainer container)
{
    var mapper = container.Resolve<IMapper>();

    var source = new EntityType(123, "Test-text", "Test-description");

    var dto = mapper.Map<DtoType>(source);

    dto.RunComponents();
}

The code dto.RunComponents() is the one that executes the injected implementations of the interfaces IPreMapperComponent and IPostMapperComponent used in the type DtoType.

You can find all the code-files involved in this example in this Gist.

This can all also be done through the recommended approach of Modules in Autofac and Profiles in AutoMapper.

2017-11-15

C# Clamp: Limit IComparable Between Two Values

If you've ever needed to limit a value between two known limits of values, then you have been looking for Clamping.

Sometimes when you do calculations on values you know that the result should not fall outside two specific values. For example, if your calculating a percentage-value as an int-value, then you know the result should be between 0 and 100.

public int GetPercentage(int val1, int val2)
{
    // TODO: Check for 0 on val2-parameter

    var calculation = val1 / val2;
    var ensuredPercentage = calculation.Clamp(0, 100);
    return ensuredPercentage;
}

This functionality can easily be extended to all classes which inherits from System.IComparable<T>, which are for example all types of numbers like int, double, long and so on, but also DateTime and more.

The following extension-method adds the Clamp-method to all objects of types inheriting from IComparable<T>:

public static T Clamp<T>(this T value, T min, T max)
    where T : IComparable<T>
{
    var comparer = Comparer<T>.Default;

    if (comparer == null)
        throw new ArgumentException($"Failed to get default comparer for type '{typeof(T).FullName}'.");

    var isMinGreaterThanMax = comparer.Compare(min, max) > 0;

    if (isMinGreaterThanMax)
    {
        throw new ArgumentOutOfRangeException(
            nameof(min),
            "Minimum value cannot be larger than maximum value.");
    }

    var isValueLessThanMin = comparer.Compare(value, min) < 0;
    var isValueGreaterThanMax = !isValueLessThanMin && comparer.Compare(value, max) > 0;

    return isValueLessThanMin ? min : (isValueGreaterThanMax ? max : value);
}

2017-05-18

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.

2017-01-18

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.