Authentication and authorization are essential components of any web application, ensuring the security and proper access control for users. In NET Core, these concepts play a crucial role in protecting resources and determining user permissions. Authentication in NET Core Authentication is the process of verifying the identity of a user, ensuring they are who they claim to be. This is typically done by presenting credentials, such as a username and password, and validating them against a trusted source, such as a database or an external authentication provider. Once authenticated, the user is assigned an identity, which is then used for subsequent authorization checks. Authentication in NET Core Authentication in NET Core revolves around the concept of authentication schemes. An authentication scheme represents a specific method or protocol used to authenticate users. NET Core supports various authentication schemes out of the box, including cookie authentication, JWT bearer authentication, and external authentication providers like OAuth and OpenID Connect. Understanding Authentication Schemes Authentication schemes are registered in the application’s startup class using the AddAuthentication method. This method allows you to specify one or more authentication schemes and their respective options. For example, to enable cookie authentication, you can use the AddCookie services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme) .AddCookie(options => { // Configure CookieAuthenticationDefaults options }); Configuring Cookie Authentication To configure cookie authentication, you need to specify the authentication scheme as CookieAuthenticationDefaults.AuthenticationScheme and provide the necessary options, such as the cookie name, login path, and authentication endpoint. Here's an example: services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme) .AddCookie(options => { options.Cookie.Name = "MyCookie"; options.LoginPath = "/Admin/Login"; }); In this example, the cookie authentication middleware is configured to use the scheme named “MyCookie” and redirect users to the “/Admin/Login” page if they try to access a protected resource without being authenticated. The options object allows you to customize various aspects of cookie authentication, such as cookie expiration and sliding expiration. Implementing Claim-Based Authentication A claim represents a piece of information about the user, such as their name, email address, or role. By using claims, you can easily extend the user’s identity with additional data and make authorization decisions based on these claims. In NET Core, claim-based authentication is implemented using the ClaimsIdentity and ClaimsPrincipal classes. The ClaimsIdentity represents a collection of claims associated with a user, while the ClaimsPrincipal represents the user's identity as a whole. When a user is authenticated, their claims are stored in a ClaimsPrincipal, which is then attached to the current request's HttpContext.User property. To implement claim-based authentication, you need to create and populate a ClaimsIdentity object with the relevant claims. This can be done during the authentication process, typically in a custom authentication handler. Here's an example of how to create a ClaimsIdentity with a username claim: var claims = new List<Claim> { new Claim(ClaimTypes.Name, "Himanshu") }; var identity = new ClaimsIdentity(claims, "MyAuthenticationScheme"); var principal = new ClaimsPrincipal(identity); await HttpContext.SignInAsync(principal); External Authentication Providers External authentication allows users to sign in to your application using their existing accounts from popular platforms like Google, Facebook, Twitter, and Microsoft. To enable external authentication, you need to configure the desired authentication provider and register it in your application’s startup class. services.AddAuthentication() .AddGoogle(options => { options.ClientId = "YOUR_GOOGLE_CLIENT_ID"; options.ClientSecret = "YOUR_GOOGLE_CLIENT_SECRET"; }); Securing APIs with JWT Bearer Authentication .NET Core provides built-in support for securing APIs using JSON Web Tokens (JWT) and the JWT bearer authentication scheme. JWTs are self-contained tokens that contain information about the user and their permissions. By validating the integrity and authenticity of a JWT, you can trust the claims it contains and authenticate API requests. To enable JWT bearer authentication, you need to configure the authentication scheme and provide the necessary options, such as the token validation parameters and the issuer signing key. Here’s an example of configuring JWT bearer authentication: services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) .AddJwtBearer(options => { options.TokenValidationParameters = new TokenValidationParameters { ValidateIssuer = true, ValidateAudience = true, ValidateIssuerSigningKey = true, ValidIssuer = "YOUR_ISSUER", ValidAudience = "YOUR_AUDIENCE", IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("YOUR_SIGNING_KEY")) }; }); In this example, the AddJwtBearer extension method is used to configure JWT bearer authentication. The TokenValidationParameters object is set with the necessary validation rules, such as validating the issuer, audience, and the issuer's signing key. You need to replace the placeholder values with your own values specific to your JWT setup. With JWT bearer authentication enabled, API endpoints can be protected by applying the [Authorize] attribute to the corresponding controller or action. This ensures that only requests with valid and authenticated JWTs are allowed access to the protected resources. Maintain secure Authorization Authorization in NET Core is primarily controlled through the use of the [Authorize] attribute. This attribute can be applied at the controller or action level to restrict access to specific components of your application. By default, the [Authorize] attribute allows only authenticated users to access the protected resource. The Role of Authorize Attribute : For example, you can use the [Authorize(Roles = "Admin")] attribute to restrict access to administrators only. This ensures that only users with the "Admin" role can access the protected resource. Restricting Access with Policies : While the [Authorize] attribute provides a simple way to restrict access, ASP.NET Core also supports more advanced authorization policies. Authorization policies allow you to define fine-grained rules for determining whether a user is authorized to perform a specific action. To use authorization policies, you need to define them in your application’s startup class using the AddAuthorization method. Here's an example: services.AddAuthorization(options => { options.AddPolicy("AdminOnly", policy => { policy.RequireRole("Admin"); }); }); Rrole-based authorization can be implemented using the built-in role-based authentication system or by integrating with an external identity provider, such as Active Directory or Azure AD. Implementing Two-Factor Authentication Two-factor authentication (2FA) adds an extra layer of security to the authentication process by requiring users to provide additional verification, typically in the form of a one-time password or a biometric factor. Implementing 2FA can significantly reduce the risk of unauthorized access, especially for sensitive applications or those handling confidential information. To implement two-factor authentication, you need to configure the desired authentication providers, such as SMS, email, or authenticator apps, and register them in your application’s startup class. You also need to configure the necessary options, such as the message templates or the issuer signing key. By enabling two-factor authentication, you provide an additional layer of security that can help protect user accounts from unauthorized access, even if their credentials are compromised. Protecting Against Common Security Vulnerabilities When implementing authentication and authorization in your application, it’s crucial to be aware of common security vulnerabilities and take appropriate measures to prevent them. By understanding these vulnerabilities and following security best practices, you can ensure the integrity and confidentiality of user data. Some common security vulnerabilities to consider when implementing authentication and authorization include: Cross-Site Scripting (XSS): Protect against XSS attacks by properly encoding user input and validating data before rendering it in HTML or JavaScript. Cross-Site Request Forgery (CSRF): Implement CSRF protection mechanisms, such as anti-forgery tokens, to prevent attackers from executing unauthorized actions on behalf of authenticated users. Brute-Force Attacks: Implement account lockout policies and rate limiting to protect against brute-force attacks that attempt to guess user credentials. Session Management: Use secure session management techniques, such as session timeouts, secure cookie attributes, and session regeneration, to prevent session hijacking or session fixation attacks. Password Storage: Store passwords securely by using strong hashing algorithms, salting, and iteration counts to protect against password cracking attempts. By addressing these vulnerabilities and following security best practices, you can minimize the risk of unauthorized access, data breaches, and other security incidents. Conclusion: Authentication and authorization are critical components of building secure and robust web applications in .Net Core. By understanding the concepts and leveraging the powerful features provided by. NET Core, developers can implement robust security measures to protect their applications and ensure that users access resources securely and efficiently.
As .NET 6.0 approaches its end-of-support date, it’s time for developers and businesses to consider upgrading to stay on the cutting edge and ensure that applications remain secure, efficient, and compliant. With the upcoming .NET 8 offering new features and performance boosts, an upgrade promises more than just continued support—it’s an opportunity to leverage a new generation of improvements. In this guide, we’ll walk you through the upgrade process, highlighting the critical changes you’ll need to make to ensure a smooth transition from .NET 6.0. Why Does upgrade is needed from .Net6.0? End of Support and Security Risks .NET 6.0, as a Long-Term Support (LTS) version, provided stability and support, but its support period is ending. Staying on an unsupported version exposes applications to security vulnerabilities and compliance risks, making an upgrade essential for data protection and system integrity. Access to Enhanced Features and Improvements Newer .NET versions bring valuable features like better performance optimizations, productivity tools, and cloud-native support. Upgrading unlocks these advancements, helping applications run faster and utilize fewer resources. Improved Developer Productivity .NET 7 and .NET 8 include new language features, such as enhanced pattern matching and streamlined lambda expressions in C#, which simplify code and reduce boilerplate. These additions help developers write code more quickly and with fewer errors. Reduced Operational Costs Performance improvements in .NET 7 and .NET 8 mean that applications can often perform better with fewer resources. This reduction in memory and CPU usage can translate to lower costs, especially for cloud-hosted applications. Compatibility with Modern Tools and Libraries Many popular third-party libraries and tools adopt newer .NET versions quickly, ensuring compatibility and stability. Staying up-to-date with .NET versions helps maintain compatibility with these tools, avoiding potential issues with outdated dependencies. Preparing for Future Technology As Microsoft continues to evolve .NET, each version brings it closer to the needs of modern workloads, such as machine learning, cloud computing, and IoT. Upgrading ensures that applications remain ready for future tech innovations and integrate easily with emerging solutions. These improvements make upgrading to .NET 8 essential for any business looking to stay competitive and secure in today’s fast-paced digital world. Action Plan for .NET 6 Users: Steps to Upgrade to .NET 8 Upgrading from .NET 6 to .NET 8 requires a structured approach to ensure application stability and compatibility. Follow this action plan to make your migration process smooth and efficient. 1. Prioritize Upgrading to .NET 8 Since .NET 8 is the newest LTS release, it’s vital to prioritize upgrading business-critical applications first. Applications managing sensitive data, high user traffic, or core operations will benefit most from .NET 8’s security patches and performance improvements. 2. Evaluate Your Applications for Compatibility Conduct a thorough audit of your applications to identify any potential compatibility issues. Here’s what to focus on: Dependency Audit: Ensure that third-party libraries, plugins, and tools are compatible with .NET 8. Update or replace any that are not supported. Database and ORM Compatibility: If you’re using ORMs like Entity Framework, verify their compatibility with .NET 8 and prepare for any required schema migrations. Code Review for Deprecated APIs: Review your code for deprecated APIs and replace or refactor any incompatible code. Microsoft’s .NET 8 upgrade documentation highlights specific API changes and deprecations to consider. 3. Use the .NET Upgrade Assistant Tool Microsoft’s .NET Upgrade Assistant is designed to streamline the migration process, especially for complex or large projects. It helps automate and identify critical changes needed for a successful upgrade: Flags deprecated APIs and unsupported code. Automates refactoring for .NET 8 compatibility. Provides guidance on manual changes necessary to complete the transition. This tool saves significant time, particularly for enterprise applications with complex dependencies and workflows. 4. Thoroughly Test Your Upgraded Application Testing is essential to ensure that your application performs correctly after the upgrade. Here’s a recommended testing approach: Automated Unit Testing: Run unit tests on your upgraded code to verify core functionality. Add or update tests to cover modified areas. Integration Testing: Validate that services or components work correctly together in .NET 8. Load and Performance Testing: Test under real-world conditions to validate .NET 8’s performance benefits and catch any potential bottlenecks. User Acceptance Testing (UAT): Conduct UAT to confirm that your end-users experience expected functionality, especially if significant code or API changes have been made. Common Troubleshooting for .NET 8 Migration Here are some common issues developers encounter during migration and how to resolve them. 1. Continuous Integration Challenges with Azure DevOps Upgrading applications within CI/CD environments like Azure DevOps can present challenges. Here’s how to address some common issues: Pipeline Configuration: Update Azure DevOps pipelines to reference .NET 8 SDKs. Modify YAML files or pipeline configurations to install .NET 8 before the build, ensuring dependencies are correctly aligned. NuGet Feed Compatibility: Verify that NuGet feeds are compatible with .NET 8 packages. Update outdated or incompatible packages to avoid build errors. Validate CI Tests: Re-run automated tests in Azure DevOps pipelines to catch compatibility issues before deploying to production. 2. Problem Management on Azure App Service Deploying upgraded applications on Azure App Service may lead to configuration or compatibility issues. Here’s how to manage these effectively: Set Runtime Stack to .NET 8: In the Azure Portal, navigate to App Service Settings > Configuration > Stack Settings and select .NET 8 as the runtime stack. Diagnostic Log Analysis: Check the App Service diagnostic logs for code incompatibility, runtime errors, or dependency conflicts. Enable detailed error messages to troubleshoot effectively. Leverage Azure Application Insights: Use Application Insights to monitor performance, track errors, and get real-time insights into application health, which helps identify optimization areas post-upgrade. Need Help with Your Upgrade? Connect with Magnusminds If you need assistance with your migration or encounter complex issues, Magnusminds offers expert support for .NET upgrades. out team provides tailored solutions for migration, implementation of new features, and troubleshooting specific to your application needs.
Before diving into optimization techniques, it’s important to identify the areas of your code that require improvement. By measuring and profiling your application’s performance, you can pinpoint the exact bottlenecks and focus your optimization efforts where they matter the most (Measure and Identify Bottlenecks). In this blog, I’ll explain effective strategies for handling memory and reducing garbage collection overhead in your C# applications. Memory management and garbage collection are essential aspects of performance tuning in C#, so these best practices will help you optimize your code for maximum efficiency. Here are 8 tips that will help with performance optimization. 1. Use the IDisposable interface : Utilizing the IDisposable interface is a crucial C# performance tip. It helps you properly manage unmanaged resources and ensures that your application’s memory usage is efficient. Bad way: public class ResourceHolder { private Stream _stream; public ResourceHolder(string filePath) { _stream = File.OpenRead(filePath); } // Missing: IDisposable implementation } Good way: public class ResourceHolder : IDisposable { private Stream _stream; public ResourceHolder(string filePath) { _stream = File.OpenRead(filePath); } public void Dispose() { _stream?.Dispose(); // Properly disposing the unmanaged resource. } } By implementing the IDisposable interface, you ensure that unmanaged resources will be released when no longer needed, preventing memory leaks and reducing pressure on the garbage collector. This is a fundamental code optimization technique in C# that developers should utilize. 2. Asynchronous Programming with async/await Asynchronous programming is a powerful technique for improving C# performance in I/O-bound operations, allowing you to enhance your app’s responsiveness and efficiency. Here, we’ll explore some best practices for async/await in C#. Limit the number of concurrent operations Bad way: public async Task ProcessManyItems(List<string> items) { var tasks = items.Select(async item => await ProcessItem(item)); await Task.WhenAll(tasks); } Good way: public async Task ProcessManyItems(List<string> items, int maxConcurrency = 10) { using (var semaphore = new SemaphoreSlim(maxConcurrency)) { var tasks = items.Select(async item => { await semaphore.WaitAsync(); // Limit concurrency by waiting for the semaphore. try { await ProcessItem(item); } finally { semaphore.Release(); // Release the semaphore to allow other operations. } }); await Task.WhenAll(tasks); } } Without limiting concurrency, many tasks will run simultaneously, which can lead to heavy load and degraded overall performance. Instead, use a SemaphoreSlim to control the number of concurrent operations. 3. UseConfigureAwait(false) when possible ConfigureAwait(false) is a valuable C# performance trick that can help prevent deadlocks in your async code and improve efficiency by not forcing continuations to run on the original synchronization context. public async Task<string> DataAsync() { var data = await ReadDataAsync().ConfigureAwait(false); // Use ConfigureAwait(false) to avoid potential deadlocks. return ProcessData(data); } 4. Parallel Computing and Task Parallel Library This will help the power of multicore processors and speed up CPU-bound operations Bad way: private void Data(List<int> data) { for (int i = 0; i < data.Count; i++) { PerformExpensiveOperation(data[i]); } } Good way: private void Data(List<int> data) { Parallel.ForEach(data, item => PerformExpensiveOperation(item)); } Parallel loops can considerably accelerate processing of large collections by distributing the workload among multiple CPU cores. Switch from regular for and foreach loops to their parallel counterparts whenever it’s feasible and safe. 5. Importance of Caching Data Utilizing in-memory caching can drastically reduce time-consuming database fetches and speed up your application. The good way demonstrates the use of in-memory caching to store product data and reduce time-consuming database fetches. 6. Optimizing LINQ Performance Force immediate execution using ToList() or ToArray() when needed. Use the AsParallel() extension method to ensure safety and parallelism. Selecting a HashSet instead of a List offers faster look-up times and greater performance 7. Task and ValueTask for reusing asynchronous code Use ValueTask to reduce heap allocations public async ValueTask<string> DataAsync() { var data = await ReadFromStreamAsync(_stream); return ProcessData(data); } By switching from Task<TResult> to ValueTask<TResult>, you can reduce heap allocations and ultimately improve your C# performance 8. Use HttpClientFactory to manage HttpClient instances private readonly HttpClient _httpClient; public MyClass(HttpClient httpClient) { _httpClient = httpClient; } public async Task GetDataAsync() { var response = await _httpClient.GetAsync("http://himashu.com/data"); } This approach manages the lifetimes of your HttpClient instances more efficiently, preventing socket exhaustion. - Use null-coalescing operators (??, ??=) string datInput = NullableString() ?? "default"; - Using Span and Memory for efficient buffer management // Using Span<T> avoids additional memory allocation and copying byte[] data = GetData(); Span<byte> dataSpan = data.AsSpan(); ProcessData(dataSpan); - Use StringComparison options for efficient string comparison bool equal = string.Equals(string1, string2, StringComparison.OrdinalIgnoreCase); - Use StringBuilder over string concatenation in loops StringBuilder sb = new StringBuilder(); for (int i = 0; i < 1000; i++) { sb.AppendFormat("Iteration: {0}", i); } string result = sb.ToString(); This has been a collection of just a few things I’ve found useful for enhancing the performance of my C# .NET code. Remember that the key to successful development is a balance between code quality and performance optimizations. By employing these techniques, you’ll be able to build high-performing C# applications that deliver a seamless user experience.
Introduction In today's data-driven world, having efficient search capabilities within your application is crucial. Elasticsearch, an open-source, distributed search and analytics engine, is designed for this purpose. Coupled with Kibana, a powerful visualization tool, you can not only search through large datasets quickly but also visualize and analyze your data in real-time. This blog post will guide you through integrating Elasticsearch and Kibana into your .NET Core application, focusing on setting up efficient search capabilities. What is Elasticsearch? Elasticsearch is a search engine based on the Lucene library. It provides a distributed, multitenant-capable full-text search engine with an HTTP web interface and schema-free JSON documents. Key features include: Distributed: Elasticsearch distributes data and processing across multiple nodes, ensuring high availability and scalability. Full-text search: It offers powerful full-text search capabilities, including complex search queries. Real-time indexing and searching: Elasticsearch provides near real-time search capabilities, making it ideal for applications that require up-to-date search results. RESTful API: Elasticsearch's API is RESTful, making it easy to interact with using HTTP requests. What is Kibana? Kibana is an open-source data visualization and exploration tool designed to work with Elasticsearch. It provides a web interface for: Visualizing Elasticsearch data: Create charts, graphs, and maps to visualize your data. Exploring data: Use the Discover feature to explore your indexed data and perform searches. Creating dashboards: Combine multiple visualizations into interactive dashboards for monitoring and analysis. Real-time monitoring: Monitor your data and set up alerts for specific events or conditions. Prerequisites Before we start, ensure you have the following: Elasticsearch: Installed and running. Download from the official Elasticsearch website. Kibana: Installed and running. Download from the official Kibana website. .NET Core 6 or higher: Installed and ready for development. Lower versions of .NET Core are supported, but .NET Core 6 is the latest LTS version, supported until November 2024. .NET Core 8 is expected to be the next LTS release in November 2023, with support through November 2026. Setting Up Elasticsearch in .NET Core Step 1: Create a New .NET Core Project WebApp or API Step 2: Add Elasticsearch NuGet Packages dotnet add package Elasticsearch.Net dotnet add package NEST Step 3: Configure Elasticsearch Add Configuration: In appsettings.json, add your Elasticsearch URL: { "Elasticsearch": { "Url": "http://localhost:9200" } } Create Elasticsearch Service: Create a service to handle Elasticsearch interactions. using Elasticsearch.Net; using Microsoft.Extensions.Configuration; using Nest; using System; public class ElasticsearchService { private readonly IElasticClient _elasticClient; public ElasticsearchService(IConfiguration configuration) { var settings = new ConnectionSettings(new Uri(configuration["Elasticsearch:Url"])) .DefaultIndex("default-index"); _elasticClient = new ElasticClient(settings); } public async Task IndexDocumentAsync<T>(T document) where T : class { await _elasticClient.IndexDocumentAsync(document); } public async Task<ISearchResponse<T>> SearchAsync<T>(Func<SearchDescriptor<T>, ISearchRequest> searchSelector) where T : class { return await _elasticClient.SearchAsync(searchSelector); } } Register Elasticsearch Service: Register the service in Startup.cs or Program.cs. public class Startup { public void ConfigureServices(IServiceCollection services) { services.AddControllers(); services.AddSingleton<ElasticsearchService>(); } public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } app.UseRouting(); app.UseEndpoints(endpoints => { endpoints.MapControllers(); }); } } Use Elasticsearch in Controllers: Create a controller to interact with Elasticsearch. using Microsoft.AspNetCore.Mvc; using System.Threading.Tasks; [ApiController] [Route("[controller]")] public class SearchController : ControllerBase { private readonly ElasticsearchService _elasticsearchService; public SearchController(ElasticsearchService elasticsearchService) { _elasticsearchService = elasticsearchService; } [HttpPost("index")] public async Task<IActionResult> IndexDocument([FromBody] object document) { await _elasticsearchService.IndexDocumentAsync(document); return Ok(); } [HttpGet("search")] public async Task<IActionResult> Search(string query) { var response = await _elasticsearchService.SearchAsync<object>(s => s .Query(q => q .QueryString(d => d .Query(query) ) ) ); return Ok(response.Documents); } } Step 4: Index Existing Data If you have existing data in your database, you'll need to index it into Elasticsearch. Create a Data Indexing Service: using Microsoft.Extensions.Configuration; using Nest; using System; using System.Collections.Generic; using System.Threading.Tasks; public class DataIndexingService { private readonly IElasticClient _elasticClient; public DataIndexingService(IConfiguration configuration) { var settings = new ConnectionSettings(new Uri(configuration["Elasticsearch:Url"])) .DefaultIndex("your-index-name"); _elasticClient = new ElasticClient(settings); } public async Task IndexDataAsync<T>(IEnumerable<T> data) where T : class { var bulkDescriptor = new BulkDescriptor(); foreach (var item in data) { bulkDescriptor.Index<T>(op => op .Document(item) ); } var response = await _elasticClient.BulkAsync(bulkDescriptor); if (response.Errors) { throw new Exception("Failed to index some documents"); } } } Load Existing Data: Fetch data from your database. using System.Collections.Generic; using System.Threading.Tasks; using Dapper; using Microsoft.Data.SqlClient; public class DatabaseService { private readonly string _connectionString; public DatabaseService(string connectionString) { _connectionString = connectionString; } public async Task<IEnumerable<YourDataType>> GetExistingDataAsync() { using (var connection = new SqlConnection(_connectionString)) { var query = "SELECT * FROM YourTable"; var data = await connection.QueryAsync<YourDataType>(query); return data; } } } Index Existing Data: In Startup.cs or Program.cs, index your existing data at startup. public class Startup { public void ConfigureServices(IServiceCollection services) { services.AddSingleton<DatabaseService>(sp => new DatabaseService("YourConnectionString")); services.AddSingleton<DataIndexingService>(); services.AddControllers(); } public void Configure(IApplicationBuilder app, IWebHostEnvironment env, DatabaseService databaseService, DataIndexingService dataIndexingService) { // Index existing data at startup Task.Run(async () => { var existingData = await databaseService.GetExistingDataAsync(); await dataIndexingService.IndexDataAsync(existingData); }).GetAwaiter().GetResult(); if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } app.UseRouting(); app.UseEndpoints(endpoints => { endpoints.MapControllers(); }); } } Step 1: Navigate to kibana.yml and Update Configurations Open Command Prompt (cmd): Press Win + R, type cmd, and press Enter. Navigate to the Kibana Directory: Use the cd command to navigate to the directory where Kibana is installed. For example: cd C:\path\to\kibana\config Edit kibana.yml: Open kibana.yml in a text editor. You can use notepad from the command line: notepad kibana.yml Update the Configuration: In the kibana.yml file, set the elasticsearch.hosts property to point to your Elasticsearch instance: elasticsearch.hosts: ["http://localhost:9200"] Save and close kibana.yml. Step 2: Run elasticsearch.bat and kibana.bat Using Command Prompt Open a New Command Prompt (cmd) Window for Elasticsearch: Press Win + R, type cmd, and press Enter. Navigate to the Elasticsearch bin Directory: Use the cd command to navigate to the directory where Elasticsearch is installed. For example: cd C:\path\to\elasticsearch\bin Run elasticsearch.bat: Start Elasticsearch by running: elasticsearch.bat Open Another Command Prompt (cmd) Window for Kibana: Press Win + R, type cmd, and press Enter. Navigate to the Kibana bin Directory: Use the cd command to navigate to the directory where Kibana is installed. For example: cd C:\path\to\kibana\bin Run kibana.bat: Start Kibana by running: kibana.bat Step 3: Set the Password for Default User elastic Open a New Command Prompt (cmd) Window: Press Win + R, type cmd, and press Enter. Navigate to the Elasticsearch bin Directory: Use the cd command to navigate to the directory where Elasticsearch is installed. For example: cd C:\path\to\elasticsearch\bin Set the Password for the elastic User: Use the elasticsearch-users tool to set the password. Run the following command: elasticsearch-users userpasswd elastic You will be prompted to enter a new password for the elastic user. Verification Verify Elasticsearch and Kibana: Open your browser and navigate to http://localhost:9200 to check if Elasticsearch is running. Navigate to http://localhost:5601 to check if Kibana is running. Log in to Kibana: Use the elastic user and the password you set to log in to Kibana. Exploring Data with Kibana Kibana provides a web interface to visualize and explore your Elasticsearch data. After indexing your data, follow these steps: Step 1: Access Kibana Open your browser and navigate to http://localhost:5601. Step 2: Configure Index Pattern Go to Management > Kibana > Index Patterns. Create a new index pattern matching your indices, e.g., your-index-name-*. Step 3: Visualize Data Use the Discover tab to explore your indexed data and perform searches. Create visualizations using the Visualize tab: Choose a visualization type (e.g., bar chart, pie chart, line graph). Configure the data source and settings. Save the visualization. Step 4: Create Dashboards Combine multiple visualizations into interactive dashboards: Go to the Dashboard tab. Create a new dashboard. Add saved visualizations and arrange them as needed. Save the dashboard. Step 5: Real-Time Monitoring Set up real-time monitoring and alerts: Use the Monitoring feature to track the health and performance of your Elasticsearch cluster. Set up Watchers in Kibana to trigger alerts based on specific conditions. Refer to the image below, which show the amount of data in the table Conclusion Integrating Elasticsearch and Kibana with your .NET Core application provides powerful search and visualization capabilities. With Elasticsearch, you can efficiently search through large datasets, and Kibana allows you to visualize and explore this data in real-time. By following the steps outlined in this blog post, you can enhance your application's search functionality and gain valuable insights from your data.