Showing posts with label C#. Show all posts
Showing posts with label C#. Show all posts

2020-02-13

C# Nullable Reference Types: IntelliSense Confusion

The feature and concept of Nullable reference types were introduced in C# 8.0 and it basically made all types non-nullable by default and ensured that these types could never be assigned the value null. This is one of my favorite features in C# recently, but there are scenarios where a mixed nullable environment could cause confusion.

Confusion

To enable the assignment of the value null to a type, you have to explicitly mark that type. This uses the same concept of nullable as introduced in C# 2.0, where you, for example, make an int nullable by adding a question mark after it: int?.

When we look at a regular example service-class, we can see which benefits can be had from Nullable reference types:

public class ProductService
{
    // This method accepts a non-null string for 'productId'
    // and always returns a string
    public string FormatProductId(string productId)
    {
        // ...
    }

    // This method accepts a nullable 'formattedProductId'
    // and returns a string or null
    public string? TryGetProductName(string? formattedProductId)
    {
        // ...
    }
}

This makes things all fine and clear. We know that the method FormatProductId never returns null and that it doesn't accept null in its parameter. We also know that the method TryGetProductName returns a string which could be null and that the parameter accepts a string which could be null.

This is great, this means that we don't have to perform a null-check on productId-parameter of the FormatProductId-method, right? Well, not exactly...

Confusion: Mixed nullable environments

In an environment where all your code has Nullable reference types enabled, you can trust the output of a method and the input to its parameters. In a mixed nullable environment, things are not as straight forward, especially when you look at how IntelliSense in Visual Studio signals what to expect from the code.

Scenario 1: Modern app & legacy library

Imagine that your new modern app has Nullable reference types enabled, but you're using an external library that is legacy and does not have this enabled. This external library can be your own old library or something you've included from NuGet.

The problem now becomes that the external library is signaling, for example, that it has a method that returns a string and not a string?, so you should be able to trust that it is not null, right? Unfortunately not. Even with a local non-nullable project, IntelliSense tells me that the returned string is not null, even when it is.

Value is not null

Scenario 2: Legacy app & modern library

Imagine that you have just put together a nice library that you want others to use, either in your project, organization or publicly through NuGet. One of the best parts about using Nullable reference types is that the compiler will warn you if you try to send in a null value as a parameter to a method that explicitly states that it doesn't support null.

Nice, now you can clean out all those noisy null-checks at the top of all the methods, right? Unfortunately not. Your code might be used by another assembly (or an older version of Visual Studio), which doesn't detect the non-nullability.

In a way, this means you have to reverse the way you do null-checks in your code.

public class ProductService
{
    // This method does not accept a null-value
    // and if it does, it should throw an exception
    public string FormatProductId(string productId)
    {
        if (productId == null)
            throw new ArgumentNullException(productId);
        // ...
    }

    // This method accepts null-values
    // and should adjust its logic accordingly
    public string? TryGetProductName(string? formattedProductId)
    {
        return
            formattedProductId != null
            ? GetProductName(formattedProductId)
            : null;
    }
}

Key takeaways

My own take-aways from exploring this aspect of Nullable reference types are:

  • When building a library, always check for null in incoming method-arguments, even when Nullable reference types is enabled
  • When consuming an external legacy library, don't trust the return-type to not be null (even if it says it's not)
  • In a mixed nullable environment, the feature to guard us against NullReferenceExceptions is likely to mistakenly cause some more of them
  • When this feature is fully adopted, there will be a reduction in a lot of the overhead in null-handling code

Thoughts

Hopefully, in .NET 5, this feature is enabled by default and these kinds of confusions, and described associated errors can be avoided.

One idea for an improvement to the IntelliSense-behavior around assemblies that are not known to have Nullable reference types enabled could be to show all these types as nullable. Both because it makes things super-clear, but also because of the fact that they actually are nullable.

This change would make everything in the whole .NET Core CLR light up as nullable, but as of .NET Core 3.1, it all is nullable, by definition.

2019-07-15

PowerShell LINQ with Short Aliases

Most modern applications or code today deal with some kind of filtering or querying. In C# and .NET, we have Language Integrated Query (LINQ), which we also have access to in PowerShell, because it's built on .NET.

To list the top 10 largest files in the Windows temporary folder, which is larger than 1 Mb and starts with the letter W, skipping the first 5, ordering by size, the C#-code with LINQ would look somewhat like this:

new System.IO.DirectoryInfo(@"C:\Windows\Temp")
    .GetFiles()
    .Where(x => x.Length > 1024 && x.Name.StartsWith("W"))
    .OrderByDescending(x => x.Length)
    .Select(x => new { x.Name, x.Length })
    .Skip(5)
    .Take(10)
    .ToList()
    .ForEach(x => Console.WriteLine($"{x.Name} ({x.Length})"));

The equivalent logic in PowerShell has a bit of a more daunting syntax, especially if you're not used to it:

Get-ChildItem "C:\Windows\Temp" `
| Where-Object {$_.Length -gt 1024 -and $_.Name.StartsWith("W")} `
| Sort-Object {$_.Length} -Descending `
| Select-Object -Property Name, Length -First 10 -Skip 5 `
| ForEach-Object {Write-Host "$($_.Name) ($($_.Length))"}

That's a bit explicit and verbose, but if you use the command Get-Alias in PowerShell, you will see a lot of useful aliases, which make the syntax a bit terser and easier to get an overview of:

gci "C:\Windows\Temp" `
| ?{$_.Length -gt 1024 -and $_.Name.StartsWith("W")} `
| sort{$_.Length} -Descending `
| select Name, Length -First 10 -Skip 5 `
| %{write "$($_.Name) ($($_.Length))"}

In a real scenario, you probably wouldn't write each result to the console, but let PowerShell present the result in its default grid format.

2019-06-27

HTML Encode TagHelper in ASP.NET Core

For a specific scenario recently, I wanted to display the HTML-encoded output of a TagHelper in ASP.NET Core. So I wanted to use the TagHelper, but not output its actual result, but see the raw HTML which would have been included in my template.

HTML

So I created another TagHelper, which allows me to wrap any HTML, inline code in ASP.NET Core and other TagHelpers, and get all the content inside the TagHelper's tag to be HTML-encoded, like this:

<html-encode>
    <a href="@Url.Action("Index")">Read More</a>
    @Html.TextBox("No_Longer_Recommended-TagHelpers_Preferred")
    <my-other-tag-helper />
</html-encode>

From this, I will get the raw HTML of the link with an UrlHelper-result, the result of the HTML-helper and the result of my other TagHelper.

The source-code for the html-encode-TagHelper is as follows:

[HtmlTargetElement("html-encode", TagStructure = TagStructure.NormalOrSelfClosing)]
public class HtmlEncodeTagHelper : TagHelper
{
    public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
    {
        var childContent = output.Content.IsModified
            ? output.Content.GetContent()
            : (await output.GetChildContentAsync()).GetContent();

        string encodedChildContent = WebUtility.HtmlEncode(childContent ?? string.Empty);

        output.TagName = null;
        output.Content.SetHtmlContent(encodedChildContent);
    }
}

2019-02-18

API Rate Limit HTTP Handler with HttpClientFactory

Most APIs have a Rate Limit of some sort. For example, GitHub has a limit of 5000 requests per hour. This can be handled, as a consumer of the API, by limiting your use by timing your requests to the API or through caching of the results.

What about when an API limits your requests per second? This is probably something you would want to handle somewhere central in your code and not spread out everywhere where you make an HTTP call to the API.

Funnel

For me, the solution was to add a Outgoing request middleware to the setup of the HttpClientFactory.

With this, I can just configure the startup services to use this RateLimitHttpMessageHandler-class with the HttpClientFactory:

services
    .AddHttpClient<IApi, Api>()
    .AddHttpMessageHandler(() =>
        new RateLimitHttpMessageHandler(
            limitCount: 5,
            limitTime: TimeSpan.FromSeconds(1)))
    .AddDefaultTransientHttpErrorPolicy();

This ensures that wherever I use the class IApi, through dependency injection, it will limit the calls to the API to only 5 calls per second.

The simplified version of code for the RateLimitHttpMessageHandler:

public class RateLimitHttpMessageHandler : DelegatingHandler
{
    private readonly List<DateTimeOffset> _callLog =
        new List<DateTimeOffset>();
    private readonly TimeSpan _limitTime;
    private readonly int _limitCount;

    public RateLimitHttpMessageHandler(int limitCount, TimeSpan limitTime)
    {
        _limitCount = limitCount;
        _limitTime = limitTime;
    }

    protected override async Task<HttpResponseMessage> SendAsync(
        HttpRequestMessage request,
        CancellationToken cancellationToken)
    {
        var now = DateTimeOffset.UtcNow;

        lock (_callLog)
        {
            _callLog.Add(now);

            while (_callLog.Count > _limitCount)
                _callLog.RemoveAt(0);
        }

        await LimitDelay(now);

        return await base.SendAsync(request, cancellationToken);
    }

    private async Task LimitDelay(DateTimeOffset now)
    {
        if (_callLog.Count < _limitCount)
            return;

        var limit = now.Add(-_limitTime);

        var lastCall = DateTimeOffset.MinValue;
        var shouldLock = false;

        lock (_callLog)
        {
            lastCall = _callLog.FirstOrDefault();
            shouldLock = _callLog.Count(x => x >= limit) >= _limitCount;
        }

        var delayTime = shouldLock && (lastCall > DateTimeOffset.MinValue)
            ? (limit - lastCall)
            : TimeSpan.Zero;

        if (delayTime > TimeSpan.Zero)
            await Task.Delay(delayTime);
    }
}

2018-08-10

API-Versioning in ASP.NET

The ASP.NET Route Versions-library was created after I was inspired by a discussion with a colleague and reading the great article Your API versioning is wrong by Troy Hunt, where he concludes that you don't need a war of preferences between different ways of versioning your API, you can actually support multiple ways in the same API.

In his article, Troy lists 3 ways (to do it wrong), which I have implemented for ASP.NET Core, and added support for one more way, which is URL versioning. This library supports the following ways to version your API:

  • URL versioning
  • Query string versioning
  • Custom request header
  • Content type

URL versioning:

HTTP GET:
https://my-web-app.com/api/v2/customers

Query string versioning:

HTTP GET:
https://my-web-app.com/api/customers?api-version=2

Custom request header:

HTTP GET:
https://my-web-app.com/api/customers
api-version: 2

Content type:

HTTP GET:
https://my-web-app.com/api/customers
Accept: application/vnd.api-version.v2+json

[RouteVersion]-attribute

All you need to do is use the [RouteVersion]-attribute on the Controller-Actions you want to version and provide the route-version as an argument:

[Route("api/v{api-version}/[controller]")]
[Route("api/[controller]")]
[ApiController]
public class CustomersController : ControllerBase
{
    [HttpGet]
    [RouteVersion(1)]
    public ActionResult<string> GetV1()
    {
        return "Get Customers Version 1";
    }

    [HttpGet]
    [RouteVersion(2)]
    public ActionResult<string> GetV2()
    {
        return "Get Customers Version 2";
    }

    [HttpPost]
    [RouteVersion(1)]
    public ActionResult<string> PostV1()
    {
        return "Post Customers Version 1";
    }

    [HttpPost]
    [RouteVersion(2)]
    public ActionResult<string> PostV2()
    {
        return "Post Customers Version 2";
    }
}

The attribute will only resolve versioning between Controller-Actions, everything else is handled by the regular ASP.NET Core routing, and behave as you're used to.

Configuration

In your Startup.cs you can configure what ways of API-versioning you want to support (all activated by default). You can also change the keys of the routing, query string, custom header and content type.

public void ConfigureServices(IServiceCollection services)
{
    services.ConfigureRouteVersions(options =>
    {        
        options.UseRoute = true;
        options.UseQuery = true;
        options.UseCustomHeader = true;
        options.UseAcceptHeader = true;

        // Set route-name in template used. For example: "api/v{version}/[controller]"
        // Default: "api-version"
        options.RouteKey = "version";

        // Set query string-key used. For example: "/api/customers?v=1"
        // Default: "api-version"
        options.QueryKey = "v"; // To use: '/api/customers?v=1'

        // Set custom version header used. For example: "my-app-api-version"
        // Default: "api-version"
        options.CustomHeaderKey = "my-app-api-version";

        // Set Accept-header vendor used. For example: "application/vnd.my-custom-api-header.v1+json"
        // Default: "application/vnd.api-version.v1+json"
        options.SetAcceptHeader("my-custom-api-header");

        // Set Accept-header regex-pattern. For example: "application/pre.my-custom-vendor-api.v1+json"
        options.AcceptRegexPattern = @"application\/pre\.my-custom-vendor-api\.v([\d]+)\+json";
    });

    services.AddMvc();
}

Default version

If you know that your new version of an API-endpoint is compatible with previous version, and if you want to support it, you can use the IsDefault-parameter with the [RouteVersion]-attribute. For example, if you've just added new fields to the next version and you find that is compatible enough to be the default version of the API-endpoint:

[Route("api/[controller]")]
[ApiController]
public class CustomersController : ControllerBase
{
    [HttpGet]
    [RouteVersion(1)]
    public ActionResult<string> GetV1()
    {
        return "Get Customers Version 1";
    }

    [HttpGet]
    [RouteVersion(2, IsDefault = true)]
    public ActionResult<string> GetV2()
    {
        return "Get Customers Version 2";
    }
}

Then you can make a call to the URL for the API-endpoint without specifying the version and get the default version, which in this example is v2:

HTTP GET:
https://my-web-app.com/api/customers/
> "Get Customers Version 2"

Contributing

You can find the source code on GitHub, the newest unstable build on MyGet and the latest version of the library on NuGet

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);
}

2016-03-08

Display Local DateTime with Moment.js in ASP.NET

Moment.js

Displaying a DateTime in local format in C# is relatively easy, but it will only use the server's settings to tell what "local" is.

For example, you might want 2016-03-07 14:35 UTC to show as 2016-03-07 15:35 for a visitor from a CET-timezone.

If you want to dynamically show the local date and time you can use the web-client's information through JavaScript and format it with Moment.js, for any user, anywhere in the world.

To do this in a way that is fault-tolerant and also SEO-friendly I want the UTC-DateTime to be hard-coded in the HTML and let Moment.js format it on the fly, when the page loads. To do this I need to populate my .cshtml-file with the following:

<span class="local-datetime"
        title="@(Model.DateUtc.ToString("yyyy-MM-dd HH:mm")) UTC"
        data-utc="@(Model.DateUtc.GetEpochTicks())">
    @(Model.DateUtc.ToString("yyyy-MM-dd HH:mm")) UTC
</span>

Make sure you run .ToUniversalTime() on your DateTime first.

Notice the .GetEpochTicks()-extension method. It makes sure the format of the DateTime is passed in a format that Moment.js can handle easily. The implementation looks like this:

private static readonly DateTime Epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);

public static double GetEpochTicks(this DateTime dateTime)
{
    return dateTime.Subtract(Epoch).TotalMilliseconds;
}

The last step is to tell Moment.js to format our DateTime to a local format:

$('.local-datetime').each(function() {
    var $this = $(this), utcDate = parseInt($this.attr('data-utc'), 10) || 0;

    if (!utcDate) {
        return;
    }

    var local = moment.utc(utcDate).local();
    var formattedDate = local.format('YYYY-MM-DD HH:mm');
    $this.text(formattedDate);
});

If this (or other, unrelated) JavaScript-code would fail for any reason the UTC-DateTime is the actually HTML-content and will still be displayed.

2015-03-25

NullableGuidConstraint for ASP.NET MVC & WebApi

Have you ever written a very usable Route-constraint in ASP.NET MVC or in WebAPI than you wanted to share between them both? For example a constraint that supports nullable Guids (Guid?) as route-parameter.

This can be done by implementing both System.Web.Routing.IRouteConstraint and System.Web.Http.Routing.IHttpRouteConstraint.

Hopefully this article will be obsolete with the release of ASP.NET 5, but until then, here's how you solve this problem:

public class NullableGuidConstraint : IRouteConstraint, IHttpRouteConstraint
{
    // ASP.NET MVC-signature
    public bool Match(
        HttpContextBase httpContext,
        Route route,
        string parameterName,
        RouteValueDictionary values,
        RouteDirection routeDirection)
    {
        return MatchInternal(parameterName, values);
    }

    // WebAPI-signature
    public bool Match(
        HttpRequestMessage request,
        IHttpRoute route,
        string parameterName,
        IDictionary values,
        HttpRouteDirection routeDirection)
    {
        return MatchInternal(parameterName, values);
    }

    private static bool MatchInternal(string parameterName, IDictionary values)
    {
        object value;
        if (!values.TryGetValue(parameterName, out value))
        {
            return false;
        }

        if (value is Guid)
        {
            return true;
        }

        string stringValue = Convert.ToString(value, CultureInfo.InvariantCulture);

        Guid guid;
        bool isMatch = string.IsNullOrWhiteSpace(stringValue) || Guid.TryParse(stringValue, out guid);
        return isMatch;
    }
}

Then you register this constraint through, for example, DefaultInlineConstraintResolver in System.Web.Mvc.Routing for ASP.NET MVC and System.Web.Http.Routing for WebAPI.

var constraintResolver = new DefaultInlineConstraintResolver();
constraintResolver.ConstraintMap.Add("guid?", typeof(NullableGuidConstraint));

// ASP.NET MVC
routes.MapMvcAttributeRoutes(constraintResolver);

// WebAPI
routes.MapHttpAttributeRoutes(constraintResolver);

Now you can write attribute-routes like this:

[Route("{controller}/{action}/{id=guid?}")]

2014-03-02

Serialize HtmlString & MvcHtmlString in JSON.NET

JSON

The HtmlString-class (and MvcHtmlString) that is and has been used in the ASP.NET-platform, including WebPages, since the introduction of ASP.NET MVC is basically just a wrapped string, that doesn't gets automatically HTML-encoded when used in Razor-views. Despite this fact, if you want to serialize or deserialize this object in JSON.NET it will come back as null.

To be able to serialize an object containing a property of a type inheriting from IHtmlString, like HtmlString and MvcHtmlString, to then, for instance, cache the serialized object, you need to implement your own Newtonsoft.Json.JsonConverter that handles the serialization and deserialization.

HtmlStringConverter : Newtonsoft.Json.JsonConverter

public override bool CanConvert(Type objectType)
{
    return typeof(IHtmlString).IsAssignableFrom(objectType);
}

public override object ReadJson(
    JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
    var value = reader.Value as string;
    // Specifically MvcHtmlString
    if (objectType == typeof(MvcHtmlString))
    {
        return new MvcHtmlString(value);
    }
    // Generally HtmlString
    if (objectType == typeof(HtmlString))
    {
        return new HtmlString(value);
    }

    // Fallback for other (future?) implementations of IHtmlString
    return Activator.CreateInstance(objectType, value);
}

public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
    var htmlString = value as HtmlString;
    if (htmlString == null)
    {
        return;
    }

    writer.WriteValue(htmlString.ToString());
}

You then have to register this Converter in your JsonSerializerSettings like this:

CurrentConverter.Converters.Add(new HtmlStringConverter());

2014-02-28

Rewrite Old URLs with Regex into RouteValueDictionary

Rewrite

Have you ever needed to rewrite/redirect old URLs that have very similar pattern as your new, modern URLs, but want to do it with simple, maintainable code?

In the following URL you very specifically can see an ID-value and a potential Category-value.

http://test.com/products/details.aspx?id=123&category=tea-cups

So you probably want to use Regex and point out named groups in above URL.

^(?:.*)\/?products\/details\.aspx\?id=(?<id>[\d]*)(&category=(?<category>[^&]*))?

Then you want to get those named values into a RouteValueDictionary, with above named Keys, like <id> and <category> with the Regex-matched Values in the URL. You can then, for example, send it to a UrlHelper. This is what the following method does:

public static RouteValueDictionary GetRegexRouteValues(string url, string urlPattern)
{
    if (url == null)
    {
        throw new ArgumentNullException("url");
    }
    if (urlPattern == null)
    {
        throw new ArgumentNullException("urlPattern");
    }

    var regex = new Regex(urlPattern);
    var match = regex.Match(url);
    if (!match.Success)
    {
        return null;
    }

    var namedGroupNames = regex.GetGroupNames().Where(x => x != null && !Regex.IsMatch(x, @"^[0-9]+$"));
    var groups = (from groupName in namedGroupNames
                  let groupItem = match.Groups[groupName]
                  where groupItem != null
                  select new KeyValuePair<string, string>(groupName, groupItem.Value)).ToList();

    var routeValues = new RouteValueDictionary();
    groups.ForEach(x => routeValues.Add(x.Key, x.Value));

    return routeValues;
}

Now you can write code that is more easy to read and maintain to redirect specific URLs:

private static void RedirectProductDetails(string requestUrl) {
    string urlRegex = @"^(?:.*)\/?products\/details\.aspx\?id=(?<id>[\d]*)(&category=(?<category>[^&]*))?";
    var routeValues = GetRegexRouteValues(requestUrl, urlRegex);

    routeValues["controller"] = "Products";
    routeValues["action"] = "Details";
    return this.Url.RouteUrl(routeValues);
}

2013-01-23

MVC: Get Current Action and Controller in View

Have you ever needed to know what Action and/or Controller that is currently used in your View? This might be most helpful in an Layout-file, used by another View.

string currentAction =
    ViewContext.Controller.ValueProvider.GetValue("action").RawValue.ToString();
string currentController =
    ViewContext.Controller.ValueProvider.GetValue("controller").RawValue).ToString();

Then you can do customization code like this in your _Layout.cshtml-file.

bool isIndexPage = currentAction.Equals("index", StringComparison.InvariantCultureIgnoreCase)
    && currentController.Equals("blog", StringComparison.InvariantCultureIgnoreCase);

Disclaimer: Of course this breaks the fundamental rules of separation of concerns in MVC, between the View and the Controller, but sometimes you just don't want, or can, pass around sufficient data between the View and the Controller.

2013-01-16

Create Human-Readable File Size Strings in C#

After needing functionality in C# for getting a human-readable file-size string I posted a question about it on Stackoverflow, as one does.

The accepted answer had about 72 lines of code. One explanation for this could be that I did specify that I wanted the solution to implement IFormatProvider. Not sure why I did that, probably seemed right at the time, in the end of 2008.

One creative solution was to use a Win32 API call to StrFormatByteSizeA

[DllImport("Shlwapi.dll", CharSet = CharSet.Auto)]
    public static extern long StrFormatByteSize(long fileSize, [MarshalAs(UnmanagedType.LPTStr)] StringBuilder buffer, int bufferSize);

Compact, clean, cross-platform solution

For the sake of simplicity, readability and the bonus of cross-platform I re-implemented an earlier solution I found, that was written in JavaScript. But the solution was easily translateble into C#.

public static class FileSizeHelper
{
    private static readonly string[] Units = { "B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB" };

    private static string GetReadableFileSize(long size) // Size in bytes
    {
        int unitIndex = 0;
        while (size >= 1024)
        {
            size /= 1024;
            ++unitIndex;
        }

        string unit = Units[unitIndex];
        return string.Format("{0:0.#} {1}", size, unit);
    }
}

2013-01-10

FTP Upload File Using Only .NET Framework

Here an example of how to upload a file to a FTP-server, using the class FtpWebRequest, which is included in the .NET Framework.

string ftpPath = string.Format("ftp://{0}/{1}", urlOrIpNumber, filePath);
FtpWebRequest request = (FtpWebRequest)WebRequest.Create(ftpPath);
request.Method = WebRequestMethods.Ftp.UploadFile;
request.Credentials = new NetworkCredential (userName, password);

byte[] fileContents = GetFileContent();
request.ContentLength = fileContents.Length;

using(var requestStream = request.GetRequestStream())
{
    requestStream.Write(fileContents, 0, fileContents.Length);
    requestStream.Close();
}

All you need to do is reference the System.Net namespace.

Update: Shorter code version

This code comes from Mads Kristensen, written in the middle of 2006.

private static void Upload(string ftpServer, string userName, string password, string filename)
{
   using (var client = new WebClient())
   {
      client.Credentials = new NetworkCredential(userName, password);
      client.UploadFile(ftpServer + "/" + new FileInfo(filename).Name, "STOR", filename);
   }
}

I'm not sure if there are any scenarios that this code doesn't work with.

2010-02-15

C# 4: Reflected Dynamics

In Scott Hanselman's blog-entry titled Back to Basics: C# 4 method overloading and dynamic types , Scott talks about method-overloads in C# 4 and the dynamic -keyword.

class Program {
    static void f(Int32 x) { }
    static void f(dynamic x) {}
    static void f(Int32 x, dynamic y) {}
    static void f(dynamic x, Int32 y) {}
    static void f(Int32 x, dynamic y, Int32 z) {}
    static void f(dynamic x, Int32 y, dynamic z) {}
    static void Main(string[] args) {
        f(10); // Works - obvious
        f(10, 10); // Ambiguous - obvious
        f(10, 10, 10); // Ambiguous - not so obvious - since it should be possible to resolve
    }
}

...the behavior is totally by design:

  • dynamic in method signatures doesn’t come into it: it behaves like System.Object does.
  • Given that, neither of the ternary signatures is better because each fits better than the other on some arguments (Int32 fits 10 better than object does)

The key point here, in bold, because it's significant is: having the type dynamic means "use my runtime type for binding".

It all becomes very clear when Reflector is used on the code. This loosens up some thought-patterns and makes it easier to really understand the dynamic -keyword.

Another way to look at this is with Reflector. This C# code:

static void f(Int32 x, dynamic y, Int32 z) {}

is essentially this, from a method signature point of view:

static void f(int x, [Dynamic] object y, int z) {}

and if there was a method that returned dynamic, it'd look like this:

[return: Dynamic]
        private static object GetCalculator() {}
    

2010-02-12

C# Coding Style Conventions

From the book Framework Design Guidelines: Conventions, Idioms, and Patterns for Reusable .NET Libraries (2nd Edition).

I write this blog post as reference for myself and others. It's a summarized version of the chapter named 'C# coding style conventions' in above named book.

General Style Conventions

Brace usage

DO place the opening brace at the end of the preceding statement.

DO align the closing brace with the beginning of the line containing the corresponding opening brace, unless closing a single-statement block.

DO place the closing brace at the beginning of a new line.

if(someExpression){
    DoSomething();
}

CONSIDER single statement blocks that have braces that begin and end on the same line. Property accessors often use this style.

public int Foo{
    get{ return foo; }
    set{ foo = value; }
}

CONSIDER single accessor properties having all brackets on the same line.

public int Foo{ get { return foo; } }

DO place the closing brace on its own line, unless followed by an else, else if or while statement.

if(someExpression){
    do{
        DoSomething();
    } while(someOtherCondition);
}

AVOID omitting braces, even if the language allows it.

Braces should not be considered optional. Even for single statement blocks, you should use braces. This increases code readability and maintainability.

for(int i=0; i<100; i++){ DoSomething(i); }

There are very limited cases when omitting braces might be acceptable, such as when adding a new statement after an existing single-line statement is either impossible or extremely rare. For example, it is meaningless to add a statement after a throw statement.

if(someExpression) throw new ArgumentOutOfRangeException(...);

Another exception to the rule is braces in case statements. These braces can be omitted as the case and break statements indicate the beginning and the end of the block.

case 0:
    DoSomething();
break;

Space Usage

DO use one space after the opening and before the closing of braces.

public int Foo{ get{ return foo; } }

AVOID using space before the opening braces.

Preferred:  if(someExpression){
Acceptable: if(someExpression) {

DO use a single space after a comma between parameters.

Right: public void Foo(char bar, int x, int y)
Wrong: public void Foo(char bar,int x,int y)

AVOID using space between arguments.

Preferred:  Foo(myChar,0,1)
Acceptable: Foo(myChar, 0, 1)

AVOID using spaces after the opening or before the closing parentheses.

Preferred:  Foo(myChar,0,1)
Acceptable: Foo( myChar,0,1 )

DO NOT use space between a member name and opening parenthesis.

Right: Foo()
Wrong: Foo ()

DO NOT use spaces after or before the brackets.

Right: x = dataArray[index];
Wrong: x = dataArray[ index ];

DO NOT use spaces before flow control statements.

Right: while(x==y)
Wrong: while (x==y)

AVOID using space before and after binary operators.

Preferred:  if(x==y){ ... }
Acceptable: if(x == y){ ... }

DO NOT use space before or after unary operators.

Right: if(!y){ ... }
Wrong: if(! y){ ... }

Indent Usage

DO use 4 consecutive space characters for indents.

DO NOT use the tab character for indents

DO indent contents of code blocks.

if(someExpression){
    DoSomething();
}

DO indent case blocks even if not using braces.

switch(someExpression){
    case 0:
        DoSomething();
    break;
        ...
}

Other

CONSIDER using the var keyword whenever the resulting type of the variable is obvious. Avoid using it if it decreases readability.

var names = new List<string>(); // good usage of var

string source = GetSource();
var tokens = source.Split(' '); // ok; most developers know String.Split

var id = GetId(); // probably not good; it's not clear what the type if id is

Naming Conventions

In general, we recommend following the Framework Design Guidelines for naming identifiers. However, there are some additional conventions and exceptions to using the Framework Design Guidelines for naming internal and private identifiers.

DO follow the Framework Design Guidelines for naming identifiers, except for naming private and internal fields.

DO use PascalCasing for namespace, type, and member names, except for internal and private fields.

DO use camelCasing for private and internal fields.

DO use camelCasing for local variables.

DO use camelCasing for parameters.

DO NOT use Hungarian notation (i.e., do not encode the type of a variable in its name).

AVOID prefixing local variables.

DO use C# aliases instead of Framework type names. For example, use int instead of Int32 and object instead of Object.


Comments

Comments should be used to describe the intent, algorithmic overview, and logical flow. It would be ideal, if from reading the comments alone, someone other than the author could understand the function's behavior and purpose. Although there are no minimum comment requirements and certainly some very small routines need no commenting at all, it is desirable for most routines to have comments reflecting the programmer's intent and approach.

DO NOT use comments unless they describe something not obvious to someone other than the developer who wrote the code.

AVOID multiline syntax (/* --- */) for comments. The single-line syntax (// ...) is preferred even when a comment spans multiple lines.

DO NOT place comments at the end of a line unless the comment is very short.

//Avoid
public class ArrayList {
    private int count; // -1 indicates uninitialized array
}

File Organization

DO NOT have more than one public type in a source file, unless they differ only in the number of generic parameters or one is nested in the other.
Multiple internal types is one file are allowed.

DO name the source file with the name of the public type it contains. For example, String class should be in String,cs file and List<T> class should be in List.cs file.

DO organize the directory hierarchy just like the namespace hierarchy. For example, the source file for System.Collections.Generic.List<T> should be in the System\Collections\Generic directory.

CONSIDER grouping members into the following sections in the specified order:

  • All fields
  • All constructors
  • Public and protected properties
  • Methods
  • Events
  • All explicit interface implementations
  • Internal members
  • Private members
  • All nested types

DO use #region blocks around not publicly callable and explicit interface implementation groups.

#region internal members
...
#endregion
#region private members
...
#endregion

CONSIDER organizing members of each group in alphabetical order.

CONSIDER organizing overloads from the simplest to the most complex.

DO place the using directives outside the namespace declaration

using System;

namespace System.Collections{
    ...
}

Own additions

DO place namespaces that are not included in .NET Framework on their own separate lines below the .NET Framework namespaces and all in alphabetical order.

using System;
using System.Collections;
using System.Collections.Generic;
using System.Xml;

using MyNamespace;
using MyNamespace.SubNamespace;
...