Performance optimization reduces resource usage, minimizes load times, and enhances responsiveness, ultimately improving productivity and customer satisfaction while reducing operational costs. Today, we will explore the ASP.NET Core best practices to ensure the development of secure, scalable, and maintainable web applications.
Imagine being in a position where you have to wait for a store to open or if the salesperson is taking their time to show products or make bills!
Oh my! You really will go to a different store the next time, I heard!
The same situation exists with users or visitors to your online shop or website. Regarding the workings of a website or application, load time is one of the most important variables determining a site’s success. A mobile page with a 10-second load time has a 123% higher bounce rate than one that loads in one second.
ASP.NET Core is the most popular backend framework to achieve a robust and high-performance website. Microsoft-supported ASP. NET Core combines the best features of MVC.NET and ASP.NET.
Because of its robust security, extensive tool library, and special features, it’s a fantastic choice for building high-quality web applications. That’s why it is loved by 18.86% (Stack Overflow 2023 Survey) of worldwide professional developers.
You must wonder why ASP.NET core best practices, tips, and tricks are crucial. Here are some reasons:
- There is an improvement in stability, security, and performance.
- The application complies with accepted industry norms.
- When necessary, the program can be quickly scaled to meet the needs of the business.
- The complexity of the code and weak spots are decreased.
- Both confidentiality and data integrity are maintained.
It is, therefore, always advised to adhere to the .NET Core best practices. It assists in meeting the business needs and selecting a superior application for the long term.
In this write-up we will learn about these performance optimization tips or .NET Core best practices.
Before that let’s comprehend how .NET Core is the best choice for your project.
How is .NET Core Best for Your Project?
.NET Core is an open-source, free, and cross-platform framework developed by Microsoft. It offers a versatile and robust framework for building various applications. The latest version, .NET 7, comes with high performance and support for modern development paradigms like microservices and containerization, making it an attractive choice for developers across various domains.
Below are a few points supporting this framework for your business growth.
-
Increased Security
Security features like data protection and encryption libraries are pre-installed in .NET Core. In addition, it gets security patches and updates regularly, making it a safe option for application development.
-
Cross Platform Compatibility
.NET Core achieves cross-platform compatibility through a platform-agnostic runtime, platform-independent libraries, and platform-specific implementations. It leverages cross-platform tools, containerization support, and NuGet package management to enable .NET developers to create applications seamlessly running on Windows, Linux, and macOS.
-
Improved Performance
.NET Core is known for its exceptional performance. It includes a new just-in-time (JIT) compiler and runtime components that are optimized for speed. This makes it the best choice for building high-performance applications, especially web and cloud-based services.
-
Language & Platform Flexibility
.NET Core is intended to function on various operating systems, such as Windows, Linux, and macOS. Reaching a larger audience and deploying apps on multiple servers and devices depend on this cross-platform support.
Learn how to convert .NET framework to .NET Core.
-
Cost Effective
.NET Core offers cost-effective advantages through its open-source, cross-platform nature. It eliminates licensing fees and enables cross-platform development, reducing maintenance costs. Moreover, its efficient resource utilization, containerization support, and scalability optimize hardware expenses.
-
Unified Ecosystem
With the introduction of .NET 5 and beyond, Microsoft has unified the .NET ecosystem. This means that dedicated .NET developers can use a single framework to build various applications, including desktop, web, cloud, and mobile applications.
Explore Secure and Scalable .NET Core Best Practices
Following the best practices ensures your .NET Core applications are maintainable, performant, secure, and reliable. These guidelines help you create robust and scalable software while promoting collaboration and maintainability among development teams.
Here are some of the key best practices for .NET Core development:
1. Optimize Data Access Layer
A critical component of a .NET Core program is the Data Access Layer (DAL), which manages database and application communication. The DAL separates the business logic layer from the data storage layer and provides an interface for updating and querying data.
Most applications are database-dependent, meaning they must retrieve data from the database, process it, and then display it on the application. Thus, we must optimize the DAL layer to enhance the applications’ performance.
Use the .NET Core best practices listed below to optimize the data access layer:
- Use the asynchronous API methods to retrieve the data from the database.
- To aggregate and filter data, utilize LINQ queries such as Select, Where, Sum, and Average. We can apply the filters in the database section in this manner.Use Entity Framework Core or another suitable ORM for efficient data retrieval.
- Craft well-tailored SQL queries, use indexes, and minimize data retrieval.
- Enable connection pooling to manage database connections efficiently.
- Use bulk insert methods for bulk data manipulation.
- Design data models wisely to minimize redundant data and joins.
- Properly index database tables to speed up queries.
- **Avoid SELECT ***: Select only the necessary columns to minimize data transfer overhead.
- Securely manage and store connection strings.
- Continuously test and benchmark your data access layer for improvements.
By following these ASP.NET best practices, you can significantly enhance the performance of your data access layer in .NET Core, leading to faster and more responsive applications.
2. Use Asynchronous Programming
Asynchronous programming in .NET Core allows non-blocking execution of tasks. It uses async and await keywords to enable efficient multitasking, improving responsiveness and performance. This is crucial for I/O-bound operations, like network calls or database queries, where the dedicated .NET developers can continue executing other tasks while waiting for the results.
One of the.NET Core best practices for developing scalable, responsive, and efficient apps is asynchronous programming.
For example:
Wrong Approach
public class StreamReaderController : Controller
{
[HttpGet("/home")]
public ActionResult Get()
{
var json = new StreamReader(Request.Body).ReadToEnd();
return JsonSerializer.Deserialize(json);
}
}
Correct Approach- Asynchronous Programming
public class StreamReaderAsyncController : Controller
{
[HttpGet("/home")]
public async Task> Get()
{
var json = await new StreamReader(Request.Body).ReadToEndAsync();
return JsonSerializer.Deserialize(json);
}
}
3. Use Caching Techniques
Caching is a crucial technique in software development that can help improve the responsiveness and performance of applications. Caching pages or parts of pages is one of the .NET Core best practices that enhance application performance.
Caching loads frequently requested content into memory, reducing the number of requests sent to the server and accelerating page display. Applications that cache pages or parts of pages can improve the user experience, minimize server load, and provide faster response times to users.
In .NET Core, you can use various types of caching mechanisms. These caching types can be employed to store and retrieve data efficiently. Here are some common caching options:
-
In-Memory Caching
In-memory caching stores data in the application’s memory, making it readily accessible. .NET Core provides the IMemoryCache interface, which you can use to cache data in-memory. It is suitable for frequently accessed data within a single application instance. In-memory caching is unsuitable for applications with multiple instances or in a distributed environment.
In-memory caching is straightforward to use in .NET Core. You need to add Microsoft.Extensions.Caching.Memory NuGet package, and you can start caching data.
using Microsoft.Extensions.Caching.Memory;
// In Startup.cs, configure the cache
public void ConfigureServices(IServiceCollection services)
{
services.AddMemoryCache();
}
// In your service or controller:
private readonly IMemoryCache _memoryCache;
public YourService(IMemoryCache memoryCache)
{
_memoryCache = memoryCache;
}
public async Task GetCachedData()
{
// Try to get data from cache, if not found, retrieve and cache it
if (!_memoryCache.TryGetValue("cacheKey", out string cachedData))
{
cachedData = "Data to be cached";
var cacheEntryOptions = new MemoryCacheEntryOptions
{
AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(10)
};
memoryCache.Set("cacheKey", cachedData, cacheEntryOptions);
}
return cachedData;
}
-
Distributed Caching
Distributed caching is used when you have multiple instances of your application running and need to share cached data between them. .NET Core supports distributed caching using various providers like Redis, SQL Server, or even a custom provider. You can use the IDistributedCache interface to work with distributed caching in .NET Core.
In a distributed caching scenario, you often use a provider like Redis. To use Redis caching, you need to add the StackExchange.Redis NuGet package and configure it.
using StackExchange.Redis;
// In Startup.cs, configure the cache
public void ConfigureServices(IServiceCollection services)
{
services.AddStackExchangeRedisCache(options =>
{
options.Configuration = "your_redis_server_connection_string";
options.InstanceName = "your_instance_name";
});
}
// In your service or controller:
private readonly IDistributedCache _distributedCache;
public YourService(IDistributedCache distributedCache)
{
distributedCache = distributedCache;
}
public async Task < string > GetDistributedCachedData()
{
// Try to get data from the distributed cache, if not found, retrieve and cache it
var cachedData = await _distributedCache.GetStringAsync("cacheKey");
if (cachedData == null)
{
cachedData = "Data to be cached";
var cacheOptions = new DistributedCacheEntryOptions
{
AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(10)
};
await _distributedCache.SetStringAsync("cacheKey", cachedData, cacheOptions);
}
return cachedData;
}
-
Response Caching
Response caching is typically used in web applications to cache HTTP responses at the server or proxy level. .NET Core provides middleware and attributes (e.g., [ResponseCache]) to enable response caching for specific controller actions or endpoints.
It’s defined in the Startup.cs file. Here’s a brief example:
public void ConfigureServices(IServiceCollection services)
{
services.AddResponseCaching();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseResponseCaching(); // Add middleware
app.Use(async (context, next) =>
{
context.Response.GetTypedHeaders().CacheControl = new CacheControlHeaderValue
{
Public = true,
MaxAge = TimeSpan.FromMinutes(10)
};
await next();
});
// Your other middleware and routing configuration.
}
4. Use Content Delivery Network
A Content Delivery Network (CDN) is a geographically distributed server network that stores and delivers web content, such as images, scripts, and videos, to users. Using a Content Delivery Network (CDN) in ASP.NET Core is the best optimization technique because it optimizes content delivery by reducing latency, improving load times, and enhancing the performance and reliability of websites and web applications.
A Content Delivery Network (CDN) is considered as one of the .NET Core best practices since it improves online application speed through caching and distributing static assets from neighboring servers. This increases availability, decreases server load, and enhances the user experience by optimizing page load times.
Read the .NET developer skills essential for every project.
CDNs also improve reliability and resilience by mitigating traffic spikes and protecting against DDoS attacks. Overall, CDNs optimize content delivery, reduce server load, and contribute to a faster and more robust web application, making them an essential component of modern web development best practices.
5. Enable Compression
The actual performance of the application will improve if we decrease the response size since less data is sent back and forth between the client and server in this manner. As a result of the smaller response size, we can cut the bandwidth requirements with the aid of ASP.NET Core’s response compression capabilities.
In .NET Core, the two most widely used compression algorithms are GZip and Deflate.
Compression is a dependable way to enhance the functionality of your ASP.NET application. Implementing software via a content delivery network and the caching mechanism work well. To increase productivity and the rate of data transactions, you should set it for all company applications.
You can use the following code block to achieve compression in.NET core code:
public void ConfigureServices(IServiceCollection services_collection)
{
services_collection.AddResponseCompression();
services_collection.Configure
(opt =>
{
opt.Level = CompressionLevel.Fastest;
});
}
6. Utilize Dependency Injection
Dependency injection is one of the noticeable ASP.NET Net Core best practices that support testability, maintainability, and loose coupling. When you outsource .NET developers, they benefit from the built-in support for dependency injection that comes with .NET Core, making it simple to inject dependencies into your classes and components. Your code may become more modular as a result, which would make testing and maintenance easier.
Various techniques exist for performing dependency injection, including constructor injection, property injection, and service registration as a singleton.
Here’s an explanation of each technique with code examples:
-
Constructor Injection
This is the most common and recommended way to perform DI in .NET Core. Dependencies are injected through a class’s constructor.
public class MyService
{
private readonly IDependency _dependency;
public MyService(IDependency dependency)
{
_dependency = dependency;
}
}
-
Property Injection
In property injection, dependencies are injected through public properties. While less common, it can be useful in certain scenarios.
public class MyService
{
public IDependency Dependency { get; set; }
}
-
Service Registration as Singleton
In .NET Core’s Startup.cs file, you can register a service as a singleton, meaning only one instance is created and reused throughout the application’s lifetime.
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<IDependency, MyDependency>();
}
Every time IDependency is injected into a class, it will refer to the same instance of MyDependency.
Note* These techniques’ usage depends on your application’s specific requirements and design principles. Constructor injection is the most widely used and recommended approach due to its clarity and adherence to the inversion of control principle.
7. Avoid Boilerplate Code
Our view models and domain models must remain distinct from one another. We accomplish this by writing code that enables us to map our view model to our domain model.
However, we must write more mappers to map our domain models and view models when we add more views and domain models. In that case, our code won’t be clear and legible. By using Automapper, we can stay out of this situation.
Utilizing AutoMapper functionality is necessary to prevent writing boilerplate code. It is an object-to-object mapper that is convention-based and necessitates minimal configuration.
One of the ASP.NET Core best practices is to use AutoMapper to avoid writing repetitive and error-prone code. NET developers can create more succinct, reusable code as a result, cutting down on overall development time.
We can map the view model and the domain model to the AutoMapper, as shown below, to configure it.
public IActionResult GetStudent(int studentId)
{
var student= studentService.GetStudent(studentId);
var studentDTO = new StudentDTO();
studentDTO.StudentId = student.StudentId;
studentDTO.StudentName = student.StudentName;
studentDTO.StudentAge = student.StudentAge;
//Other code
......
}
8. Ensure Security Using JWT
Developing a secure application is a crucial component of any application development process, and .NET Core provides you with a wealth of features to help you achieve this goal. Validating all user input before processing is crucial because it is the first line of defense against security flaws and exploits.
Security is an essential part of developing any program. One of the .NET Core best practices is to use JWT (JSON Web Tokens) for secure authentication and authorization in .NET Core. JWT provides a standardized procedure for securely exchanging claims between parties.
When dedicated .NET developers use JWT in conjunction with robust encryption techniques, they can ensure that sensitive data is protected from external threats. This guarantees that all user data is protected and authorized users can only access the resource.
9. Environment Based Setting
When published, we must use the development environment while creating our application and the production environment. In addition, once our application has been published, we must update it or fix any bugs in accordance with the requirements. All of these tasks must be completed in the development environment. Therefore, it is always a .NET Core best practices to have a different configuration for each environment.
Building flexible and maintainable applications requires configuration files, and .NET Core offers a wealth of tools to facilitate managing your configuration settings. Configuration files can also make it simple and manageable to adjust settings in various environments, facilitating your application’s deployment and upkeep.
Key-value pairs in JSON files are used by the JsonConfigurationProvider to load configuration.
Overloads may indicate whether the file is required or not.
If a file changes, does the configuration need to be reloaded?
Take a look at this code:
using Microsoft.Extensions.DependencyInjection.ConfigSample.Options;
var builder = WebApplication.CreateBuilder(args);
builder.Configuration.AddJsonFile("MyConfig.json",
optional: true,
reloadOnChange: true);
builder.Services.AddRazorPages();
var app = builder.Build();
Using.NET Core makes this extremely simple to accomplish. The appsettings.json file is visible in the project folder. We can see the appsettings.Development.json file if you expand it. For the development environment, this file is used. We should add one more file, appsettings.Production.json for the production environment.
10. Bundling & Minification
Bundling and minification are the two .NET Core best practices that improve website performance. These techniques optimize the performance of .NET web applications by reducing the size and number of requests for static assets like CSS and JavaScript files.
Bundling
- Definition: Bundling is the process of combining multiple JavaScript files or CSS into a single file. This reduces the number of HTTP requests required to fetch these assets.
- Benefits: Bundling helps improve web page load times by minimizing latency and reducing the overhead of opening multiple connections to the server.
- In .NET Core: You can implement bundling using libraries like System.Web.Optimization, BundlerMinifier, or create your own custom solution.
Minification
- Definition: Minification is the process of removing unnecessary characters (like whitespace, comments, and line breaks) and shortening variable and function names in CSS and JavaScript files without affecting their functionality.
- Benefits: Minification reduces the file size, resulting in faster downloads and improved page load times.
- In .NET Core: .NET Core provides various tools and libraries, such as BundlerMinifier.Core and Microsoft.AspNetCore.Middleware.Minification, to automate the minification of assets during the build or on-the-fly.
Bundling and minification work together to provide your web application with optimized and effective static assets, which enhances the user experience and performance. This is especially significant for contemporary web applications, where it’s critical to minimize load times and network requests.
End Note
We are a team of enthusiastic and proficient .NET developers. Thus, this write-up is based on our years of experience in the ASP.NET Core or .NET framework.
Employing the above-mentioned .NET Core best practices ensures a fast, efficient, and user-friendly experience. Optimized websites load quickly, reducing bounce rates and improving SEO rankings. They minimize server load and bandwidth, reducing hosting costs and environmental impact.
Overall, these ASP.NET best techniques are fundamental for delivering a competitive, responsive, and reliable web presence, positively impacting user satisfaction and business success.
If you’re still unsure, get in touch with the eLuminous.NET development team to learn more about how improving the performance of your current website can boost returns on investment.
Project Delivery Head
Nitin has over 20 years of IT experience and 3+ years of experience in on-site work in Arizona, USA. In all these years, he has held the positions of delivery manager, module lead, and senior consultant. Expert in advocating product life cycle phases while using self-motivational skills and problem-solving abilities. He works on the principle of “Always Deliver More than Expected.”