ASP.NET Core

ASP.NET Core

ASP.NET Core is a cross-platform, high-performance, open-source framework for building modern, cloud-enabled, internet-connected apps.

...see more

To make your ASP.NET Core services easy to test and maintain, follow this proven pattern. The example below demonstrates how to register a service and configure an HttpClient with custom handlers, while keeping the design flexible for unit testing.

1. Register your service separately

Register your service interface and implementation as a singleton (or other lifetime as needed). This keeps the service replaceable in tests:

services.AddSingleton<IMyService, MyService>();

Tip: Use TryAdd for safe registration in reusable code

If your registration code is part of a shared library or package, use TryAdd to avoid overriding existing registrations accidentally:

services.TryAddSingleton<IMyService, MyService>();

2. Configure an HttpClient with handlers

Use a named HttpClient to add retry and logging handlers. These handlers improve reliability and diagnostics:

services.AddHttpClient(nameof(MyService))
    .AddHttpMessageHandler(s => new RetryHandler(s))
    .AddHttpMessageHandler(s => new LoggingHandler(s));

3. Add memory caching safely

You can call AddMemoryCache() without worry — it internally prevents duplicates:

services.AddMemoryCache();

Full Sample Method:

public static class ServiceCollectionExtensions
{
    public static IServiceCollection AddMyClientServices(this IServiceCollection services)
    {
        ArgumentNullException.ThrowIfNull(services);

        services.AddMemoryCache();

        services.TryAddSingleton<IMyService, MyService>();

        services.AddHttpClient(nameof(MyService))
            .AddHttpMessageHandler(s => new RetryHandler(s))
            .AddHttpMessageHandler(s => new LoggingHandler(s));

        return services;
    }
}

Why This Matters

  • Separation of concerns makes your code easier to test.
  • Named HttpClient with handlers improves reliability and debugging.
  • TryAdd keeps your library safe and reusable.
  • Memory cache registration is simple and safe.

Using this approach ensures your ASP.NET Core apps are easier to maintain, test, and extend.

...see more

It’s best practice to tailor logging levels per environment (Development, Staging, Production) by using environment-specific configuration files like appsettings.Development.json or appsettings.Production.json.

Example for Development (verbose logging):

{
  "Logging": {
    "LogLevel": {
      "Default": "Debug",
      "Microsoft": "Information",
      "System": "Warning",
      "YourAppNamespace": "Trace"
    }
  }
}

Example for Production (concise logging):

{
  "Logging": {
    "LogLevel": {
      "Default": "Warning",
      "Microsoft": "Warning",
      "System": "Warning",
      "YourAppNamespace": "Information"
    }
  }
}

By adjusting log levels per environment, you can capture detailed diagnostics during development while reducing noise and performance impact in production.

...see more

ASP.NET Core allows you to customize logging behavior per provider, such as Console or Application Insights. This is useful when you want different verbosity or volume controls depending on the sink.

Example:

{
  "Logging": {
    "LogLevel": {
      "Default": "Warning",
      "Microsoft": "Warning",
      "System": "Warning",
      "YourAppNamespace": "Trace"
    },
    "Console": {
      "LogLevel": {
        "Default": "Information",
        "YourAppNamespace": "Debug"
      }
    },
    "ApplicationInsights": {
      "LogLevel": {
        "Default": "Error"
      }
    }
  }
}
  • Console logs are more verbose for development and debugging (Information and Debug).
  • Application Insights only logs errors to reduce telemetry volume and cost.

Use per-provider overrides when you want finer control over logging destinations.

...see more

In ASP.NET Core, you can configure logging levels to control the verbosity of logs across your application and third-party frameworks.

A common pattern is to set a default minimum log level (e.g., Warning) and enable verbose logging (Trace) only for your own application namespace.

Example configuration in appsettings.json or an environment-specific file:

{
  "Logging": {
    "LogLevel": {
      "Default": "Warning",
      "Microsoft": "Warning",
      "System": "Warning",
      "YourAppNamespace": "Trace"
    }
  }
}
  • "Default": "Warning" sets a baseline for all logs.
  • "Microsoft" and "System" are explicitly set to Warning to reduce noise from framework logs.
  • "YourAppNamespace": "Trace" enables detailed logging for your application code.

This ensures your app logs detailed information while keeping system logs concise and manageable.

...see more

Logging is a critical aspect of application monitoring and diagnostics. ASP.NET Core provides flexible logging configuration options to help you balance verbosity and noise across different environments and providers.

This series covers best practices for configuring logging levels, including:

  • Setting baseline and application-specific log levels
  • Customizing logging behavior per provider (e.g., Console, Application Insights)
  • Tailoring logging configurations for different environments (Development, Production, etc.)

Explore the related Snipps below to implement a robust, maintainable logging strategy in your ASP.NET Core applications.

...see more

DelegatingHandlers can be tested in isolation:

  1. Mock the Inner Handler:

    var mockHandler = new Mock<HttpMessageHandler>();
    mockHandler.Protected()
               .Setup<Task<HttpResponseMessage>>("SendAsync", ...)
               .ReturnsAsync(new HttpResponseMessage(HttpStatusCode.OK));
  2. Inject into DelegatingHandler:

    var customHandler = new CustomHandler
    {
        InnerHandler = mockHandler.Object
    };
  3. Create HttpClient:

    var client = new HttpClient(customHandler);

This approach allows for unit testing the DelegatingHandler's logic without making actual HTTP calls.

...see more

Multiple DelegatingHandlers can be chained to create a pipeline:

services.AddTransient<LoggingHandler>();
services.AddTransient<AuthenticationHandler>();
services.AddHttpClient("ChainedClient")
        .AddHttpMessageHandler<LoggingHandler>()
        .AddHttpMessageHandler<AuthenticationHandler>();

In this setup, LoggingHandler processes the request first, followed by AuthenticationHandler. The order of registration determines the sequence of execution.

...see more

To create a custom DelegatingHandler:

  1. Inherit from DelegatingHandler:

    public class CustomHandler : DelegatingHandler
    {
        protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
        {
            // Pre-processing logic
            var response = await base.SendAsync(request, cancellationToken);
            // Post-processing logic
            return response;
        }
    }
  2. Register the Handler:
    In ASP.NET Core, register the handler using IHttpClientFactory:

    services.AddTransient<CustomHandler>();
    services.AddHttpClient("NamedClient")
            .AddHttpMessageHandler<CustomHandler>();
...see more

Summary:
This video demonstrates how to generate a TreeView structure using data directly from a SQL Server database in an MVC 4 application. The example uses recursive methods to fetch hierarchical data from a parent-child table (such as a category structure). The TreeView is rendered using a combination of Razor and recursive HTML helpers.

Key Steps:

  • Create a SQL table with ID and ParentID fields.
  • Use Entity Framework to fetch data into a recursive model.
  • Write recursive logic in the controller to build the tree.
  • Use a partial view or helper method to render nested HTML in the view.

Best For:
Developers working with older ASP.NET MVC versions who need to generate TreeViews from database-driven content, particularly with dynamic data structures.

...see more

Summary:
This tutorial walks through building a TreeView in ASP.NET Core using ViewModel binding and JSON serialization. The TreeView is rendered on the client side using a simple recursive HTML structure. The backend constructs the hierarchy from a static or database source and passes it to the view. The data is structured using parent-child relationships, and the final JSON is passed to the view for rendering. No third-party libraries are used, making it a lightweight and transparent solution.

Key Steps:

  • Define a hierarchical ViewModel with recursive child collections.
  • Populate the ViewModel with data (manually or from a database).
  • Serialize the structure into JSON.
  • Render the TreeView in a Razor view using JavaScript.

Best For:
Developers using ASP.NET Core who want a lightweight, client-side rendered TreeView without relying on jQuery plugins or third-party UI components.

Add to Set
  • .NET
  • Agile
  • AI
  • ASP.NET Core
  • Azure
  • C#
  • Cloud Computing
  • CSS
  • EF Core
  • HTML
  • JavaScript
  • Microsoft Entra
  • PowerShell
  • Quotes
  • React
  • Security
  • Software Development
  • SQL References
  • Technologies
  • Testing
  • Visual Studio
  • Windows
 
Sets