Showing posts with label Razor. Show all posts
Showing posts with label Razor. Show all posts

Monday, December 3, 2018

Simplifying Razor logic with C# Local Functions in ASP.NET Core

How could we use C# Local functions and reduce the boilerplate on our ASP.NET Core pages?

One common requirement developers face is to add custom classes to links dynamically. On this post, I want to show how to do it cleanly in ASP.NET Core by combining two important C# language features: local functions and string interpolation.

Local Functions

Starting with C# 7.0, Microsoft introduced local functions to C#. Local functions are:
private methods of a type that are nested in another member. They can only be called from their containing member. Local functions can be declared in and called from: Methods, Constructors, Property accessors, Event accessors, Anonymous methods, Lambda expressions, Finalizers and Other local functions.

A simple example of how local functions are used is listed below. Note the AppendPathSeparator function: it's what's called a local function in a C# context:
     private static string GetText(string path, string filename)
    {
         var sr = File.OpenText(AppendPathSeparator(path) + filename);
         var text = sr.ReadToEnd();
         return text;    

         // Declare a local function.
         string AppendPathSeparator(string filepath)
         {
            if (! filepath.EndsWith(@"\"))
               filepath += @"\";

            return filepath; 
         }
    }

Now let's look at how we could use local functions in Razor.

Local functions in ASP.NET Core Razor

As we expect, Razor understands local functions. As an example, let's look at a common requirement: adding custom classes on menus depending on the Url the user is in. There are multiple ways to do this. On this post, I want to show how to do it cleanly in Asp.Net Core by using local functions. The solution is done in 3 (three) steps:
  1. Step 1 - Get the controller name
  2. Step 2 - Define the GetClass function to build the css class based on the controller name and link
  3. Step 3 - Use the function in our link;

Step 1 - Get the controller name

In Asp.NET Core, we access the controller name with:
    var controllerName = ((ControllerActionDescriptor)ViewContext.ActionDescriptor).ControllerName;

Step 2 - Define the GetClass function

The next step is to define a local function to toggle the css class based on the controller name. This function gets the controller name as a parameter and appends the class active to the currently set nav-link using string interpolation, another nice feature from C#:
    string GetClass(string controller)
    {
        return $"nav-link { (controllerName == controller ? "active" : "" ) }";
    }

Step 3 - Use the GetClass function in our link

Last step is to use the function in our cshtml templates like:
<a class="@GetClass("Users")" asp-controller="Users" asp-action="Index">Users</a>

Source Code

Here's the full source. See how clean the code got just by using this simple local function and string interpolation in a Bootstrap template layout:

Conclusion

On this post we examined how to use 2 very useful C# language features - local functions and string interpolation - to simplify the development of our Razor templates. Just remember to not violate DRY. If you need the same function elsewhere, move to an extension method so you can re-use it.

References

See Also

About the Author

Bruno Hildenbrand      
Principal Architect, HildenCo Solutions.