Category: C# and .NET

  • Dependency Injection in ASP.NET Core Explained

    Dependency Injection in ASP.NET Core Explained

    The first time I see a class creating five or six services with new, I know maintaining that code will become harder than necessary. Dependency injection in ASP.NET Core explained simply means letting the framework supply the objects a class needs instead of forcing that class to create them itself.

    ASP.NET Core includes a dependency injection container by default. I do not need a third-party library for normal DI scenarios. Once services are registered, the framework can create them, manage their lifetimes, and inject them where needed.

    That sounds simple. The part developers usually need to understand is how registration, resolution, and service lifetimes work together.

    What Dependency Injection Actually Does

    What Dependency Injection Actually Does

    Suppose a controller needs an email service.

    Without DI, the controller might contain this:

    var emailService = new EmailService();

    Now the controller knows exactly which implementation it uses. Replacing EmailService, mocking it during testing, or changing its dependencies becomes harder.

    With dependency injection, I depend on an abstraction instead:

    public HomeController(IMessageService messageService)

    {

        _messageService = messageService;

    }

    ASP.NET Core determines which implementation should satisfy IMessageService based on registrations configured when the application starts.

    Microsoft describes dependency injection as a technique for achieving Inversion of Control between classes and their dependencies. The official ASP.NET Core dependency injection documentation covers the built-in container in detail.

    The result is lower coupling. Classes focus on their own responsibilities rather than constructing the entire object graph beneath them.

    How the ASP.NET Core DI Container Works

    How the ASP.NET Core DI Container Works

    I find DI much easier to reason about when I separate it into three pieces.

    A dependency is something another class needs. An email service, repository, logger, or database context can all be dependencies.

    The container is the service provider that knows which services are available and how they should be created.

    Injection is the process of supplying one of those registered services to the class that requests it.

    Registration normally happens through builder.Services in Program.cs.

    For example:

    builder.Services.AddScoped<IMessageService, EmailService>();

    This tells the container that requests for IMessageService should receive an EmailService.

    The AddScoped part matters just as much as the interface and implementation. It controls the lifetime of that object.

    Understanding Transient, Scoped, and Singleton Lifetimes

    Understanding Transient, Scoped, and Singleton Lifetimes

    Service lifetimes are where Dependency injection in ASP.NET Core explained becomes more practical than theoretical.

    ASP.NET Core provides three common lifetime choices.

    Lifetime Instance behavior Typical use
    Transient Created each time requested Lightweight stateless services
    Scoped Created once per request scope DbContext, repositories, request-level services
    Singleton One instance for the application’s lifetime Shared thread-safe services, caches

    Here is the mental model I use.

    Imagine three users send three separate HTTP requests. During every request, the application needs the same service twice.

    A Transient registration can produce six objects because each resolution may create another instance.

    A Scoped registration normally produces three objects because each HTTP request receives one shared instance.

    A Singleton registration produces one object shared across all three requests.

    That simple request-by-request comparison makes lifetime selection much easier.

    Transient Services

    Register a transient service with:

    builder.Services.AddTransient<IMessageService, EmailService>();

    I use Transient when the service is lightweight, stateless, and safe to recreate frequently.

    The main cost is object creation. If a transient service has an expensive dependency graph, creating it repeatedly can become unnecessary overhead.

    Scoped Services

    Register a scoped service with:

    builder.Services.AddScoped<IMessageService, EmailService>();

    In a typical ASP.NET Core web application, a Scoped service lives for one request.

    Entity Framework Core DbContext is a classic example because related operations within one request can share the same context.

    Scoped services also help keep request-specific state isolated between users.

    Singleton Services

    A Singleton is registered with:

    builder.Services.AddSingleton<IMessageService, EmailService>();

    The same instance can then serve requests throughout the application lifetime.

    That makes Singleton useful for services designed to hold shared application-level state. However, the implementation must be safe when many requests use it concurrently.

    How to Implement Dependency Injection in ASP.NET Core

    How to Implement Dependency Injection in ASP.NET Core

    The cleanest implementation follows four small steps.

    Step 1: Define an Interface

    Start with the contract:

    public interface IMessageService

    {

        string SendMessage(string message);

    }

    The consuming class now depends on behavior rather than a concrete implementation.

    Step 2: Create the Implementation

    Next, implement that contract:

    public class EmailService : IMessageService

    {

        public string SendMessage(string message)

        {

            return $”Email sent: {message}”;

        }

    }

    I can later replace EmailService without rewriting every controller using IMessageService.

    Step 3: Register the Service

    Add the registration in Program.cs:

    var builder = WebApplication.CreateBuilder(args);

    builder.Services.AddScoped<IMessageService, EmailService>();

    var app = builder.Build();

    Registration connects the abstraction, implementation, and lifetime.

    Step 4: Inject the Dependency

    Now the controller requests the abstraction:

    public class HomeController : Controller

    {

        private readonly IMessageService _messageService;

        public HomeController(IMessageService messageService)

        {

            _messageService = messageService;

        }

        public IActionResult Index()

        {

            var result = _messageService.SendMessage(“Hello!”);

            return View((object)result);

        }

    }

    The controller never constructs EmailService. ASP.NET Core resolves it automatically.

    The same pattern becomes especially useful when learning how to build a REST API in ASP.NET Core, because controllers, repositories, database contexts, validation services, and business logic often depend on DI.

    Constructor Injection and Other DI Options

    Constructor injection is my default choice because dependencies remain explicit. Anyone reading the constructor can immediately see what the class requires.

    ASP.NET Core also supports dependency injection directly into Minimal API handlers:

    app.MapGet(“/send”, (IMessageService messageService) =>

    {

        return Results.Ok(messageService.SendMessage(“Hello”));

    });

    MVC controllers can use [FromServices] when a dependency is required by only one action rather than the entire controller.

    public IActionResult Send(

        [FromServices] IMessageService messageService)

    {

        return Ok(messageService.SendMessage(“Hello”));

    }

    I reserve action injection for narrow cases. If several actions require the same dependency, constructor injection usually produces cleaner code.

    Microsoft documents controller-specific options in its dependency injection into controllers documentation.

    Dependency Injection Mistakes I Avoid

    The most dangerous lifetime mistake is allowing a long-lived Singleton to capture a shorter-lived Scoped service.

    For example:

    Singleton Service

           ↓

    Scoped Repository

           ↓

    DbContext

    The Singleton may keep using an object that was designed to exist only within a request scope. This pattern is often called a captive dependency.

    Rather than thinking “Singleton is faster,” I choose lifetimes based on ownership and state.

    I also avoid injecting large numbers of unrelated services into one constructor. A controller needing eight or ten dependencies often signals that the class has too many responsibilities.

    Another mistake is creating registered services manually with new. Doing that bypasses the container and can defeat lifetime management.

    When Dependency Injection Becomes Especially Useful

    Small projects may make DI feel like additional structure. Its value grows rapidly as applications expand.

    Testing becomes easier because I can replace a real implementation with a fake or mock implementation. Business logic becomes less tied to databases, APIs, email providers, or storage systems.

    Configuration also becomes cleaner. I can replace one implementation centrally rather than editing every class that creates it.

    Most importantly, dependencies become visible. A constructor effectively documents what a class needs before it can work.

    That visibility is one reason I consider dependency injection an architectural tool rather than just an ASP.NET Core feature.

    FAQs

    1. What is dependency injection in ASP.NET Core?

    Dependency injection lets ASP.NET Core create registered services and supply them to classes that depend on them.

    2. What are the three dependency injection lifetimes in ASP.NET Core?

    The three standard lifetimes are Transient, Scoped, and Singleton, which control how long service instances remain available.

    3. Why is constructor injection recommended in ASP.NET Core?

    Constructor injection makes required dependencies explicit, supports testing, reduces coupling, and prevents classes from constructing their own dependencies.

    4. Can a Singleton depend on a Scoped service?

    Directly capturing a Scoped service inside a Singleton creates a lifetime mismatch and should generally be avoided.

    Stop Creating Everything With new

    Once Dependency injection in ASP.NET Core explained clicked for me, the feature stopped feeling like framework magic. It became a predictable system: register a service, choose the right lifetime, request the abstraction, and let the container resolve the implementation.

    The lifetime decision deserves the most attention. Transient means new instances, Scoped normally means one instance per web request, and Singleton means one shared instance.

    My next step on any project is simple: inspect classes that manually construct repositories, clients, or business services. Those are often the best candidates for DI. Keep dependencies explicit, keep lifetimes compatible, and the application becomes much easier to change without creating a chain reaction across the codebase.

  • How to Build a REST API in ASP.NET Core: 7 Easy Steps

    How to Build a REST API in ASP.NET Core: 7 Easy Steps

    The first time I had to figure out how to build a REST API in ASP.NET Core, the HTTP methods were not the difficult part. The real challenge was deciding how models, database access, dependency injection, routing, and responses should fit together.

    A good API should do more than return JSON. It should expose predictable URLs, use correct HTTP status codes, validate requests, handle failures cleanly, and remain easy to extend.

    I will use a simple product catalog to show the complete flow.

    Choose Controllers or Minimal APIs First

    Before writing an endpoint, I decide which ASP.NET Core API style suits the project.

    ASP.NET Core supports both Minimal APIs and controller-based APIs. Microsoft currently recommends Minimal APIs for many new projects because they need less configuration and provide a concise approach to HTTP endpoints. Controllers remain useful when I want traditional object-oriented organization, attributes, filters, and clearly separated controller classes.

    For this example, I use controllers because they make every part of the REST architecture easy to see.

    For a small microservice, I might choose Minimal APIs instead.

    Step 1: Create an ASP.NET Core Web API Project

    Step 1 Create an ASP.NET Core Web API Project

    The quickest way I create a controller-based project is with the .NET CLI:

    dotnet new webapi –use-controllers -o ProductApi

    cd ProductApi

    The –use-controllers option matters. Current ASP.NET Core tooling can create Minimal API projects by default, so this flag explicitly requests the controller architecture. Microsoft documents the same controller-based project approach in its Web API tutorial.

    Two files deserve immediate attention.

    Program.cs controls dependency injection, middleware, endpoint mapping, and application startup.

    appsettings.json provides a standard location for configuration such as connection strings and environment-specific settings.

    Understanding these files early makes how to build a REST API in ASP.NET Core much less confusing.

    Step 2: Create the Product Data Model

    Step 2 Create the Product Data Model

    I normally create a Models directory and add Product.cs.

    namespace ProductApi.Models

    {

        public class Product

        {

            public int Id { get; set; }

            public string Name { get; set; } = string.Empty;

            public decimal Price { get; set; }

            public string Description { get; set; } = string.Empty;

        }

    }

    This model represents the resource the API manages.

    A request such as:

    GET /api/products/5

    should return one representation of that product, normally as JSON.

    I keep beginner models simple. In a production application, I usually introduce request and response DTOs instead of exposing database entities directly.

    That separation becomes valuable when validation rules and public API contracts start changing.

    Step 3: Configure Entity Framework Core

    Step 3 Configure Entity Framework Core

    For a compact demonstration, install Microsoft’s EF Core InMemory provider:

    dotnet add package Microsoft.EntityFrameworkCore.InMemory

    Then create Data/ApiDbContext.cs:

    using Microsoft.EntityFrameworkCore;

    using ProductApi.Models;

    namespace ProductApi.Data

    {

        public class ApiDbContext : DbContext

        {

            public ApiDbContext(DbContextOptions<ApiDbContext> options)

                : base(options) { }

            public DbSet<Product> Products { get; set; }

        }

    }

    ApiDbContext gives Entity Framework Core access to the products collection while ASP.NET Core’s dependency injection system supplies the configured context.

    Why I Use InMemory Only for the Demo

    This distinction gets missed in many beginner tutorials.

    Microsoft explicitly states that its EF Core InMemory provider is not designed for production use. It is neither built for robustness nor production database performance.

    I use it here because it removes database setup from the learning exercise.

    For a real application, I would normally switch to SQL Server, PostgreSQL, or another supported database provider.

    Step 4: Register Services and OpenAPI

    Step 4 Register Services and OpenAPI

    Next, I configure Program.cs:

    using Microsoft.EntityFrameworkCore;

    using ProductApi.Data;

    var builder = WebApplication.CreateBuilder(args);

    builder.Services.AddControllers();

    builder.Services.AddDbContext<ApiDbContext>(options =>

        options.UseInMemoryDatabase(“ProductList”));

    builder.Services.AddOpenApi();

    var app = builder.Build();

    if (app.Environment.IsDevelopment())

    {

        app.MapOpenApi();

    }

    app.UseHttpsRedirection();

    app.UseAuthorization();

    app.MapControllers();

    app.Run();

    This is one of the most important stages when learning how to build a REST API in ASP.NET Core.

    AddControllers() registers controller support.

    AddDbContext() registers the database context through dependency injection.

    AddOpenApi() enables OpenAPI document generation. ASP.NET Core supports OpenAPI generation for controller-based and Minimal API applications.

    MapControllers() then connects incoming HTTP requests with controller routes.

    Step 5: Create RESTful CRUD Endpoints

    Create Controllers/ProductsController.cs.

    Start with the controller definition:

    [ApiController]

    [Route(“api/[controller]”)]

    public class ProductsController : ControllerBase

    {

        private readonly ApiDbContext _context;

        public ProductsController(ApiDbContext context)

        {

            _context = context;

        }

    }

    ProductsController produces the route /api/products.

    The [ApiController] attribute also enables API-focused behavior. Microsoft documents controller APIs as classes derived from ControllerBase.

    GET Endpoints

    To return every product:

    [HttpGet]

    public async Task<ActionResult<IEnumerable<Product>>> GetProducts()

    {

        return await _context.Products.ToListAsync();

    }

    To retrieve one product:

    [HttpGet(“{id}”)]

    public async Task<ActionResult<Product>> GetProduct(int id)

    {

        var product = await _context.Products.FindAsync(id);

        if (product == null)

            return NotFound();

        return product;

    }

    Notice the 404 Not Found response. REST API design is not only about performing operations. Clients also need meaningful HTTP responses.

    POST, PUT, and DELETE Endpoints

    A create endpoint can return 201 Created:

    [HttpPost]

    public async Task<ActionResult<Product>> PostProduct(Product product)

    {

        _context.Products.Add(product);

        await _context.SaveChangesAsync();

        return CreatedAtAction(

            nameof(GetProduct),

            new { id = product.Id },

            product);

    }

    I would then map PUT /api/products/{id} to updating an existing record and DELETE /api/products/{id} to removing one.

    That gives the API the core CRUD pattern:

    GET     /api/products

    GET     /api/products/{id}

    POST    /api/products

    PUT     /api/products/{id}

    DELETE  /api/products/{id}

    This predictable resource-based design is the part of how to build a REST API in ASP.NET Core that matters beyond ASP.NET itself.

    Step 6: Run and Test the ASP.NET Core API

    Run the application:

    dotnet run

    The terminal displays the local HTTP or HTTPS address.

    I test every endpoint independently rather than assuming CRUD works because the application compiled.

    For example:

    curl https://localhost:7123/api/products

    I also test invalid IDs, malformed requests, duplicate operations, and missing fields.

    Postman, Visual Studio .http files, curl, or another API client all work well.

    Testing failure paths early catches more useful problems than repeatedly testing a successful GET.

    Step 7: Prepare the REST API for Production

    A CRUD demo is only the foundation.

    When I move from a tutorial API toward production, I add input validation, DTOs, centralized error handling, authentication, authorization, logging, database migrations, pagination, rate controls, and automated tests.

    Security headers may also matter when the API is part of a browser-facing application. Understanding how to create a content security policy is particularly useful when an ASP.NET Core backend serves or supports web applications that load scripts, styles, images, and other browser resources.

    I also avoid leaking stack traces, connection details, or internal implementation information through API errors.

    For protected endpoints, there is another current ASP.NET Core behavior worth knowing. Starting with ASP.NET Core 10, known API endpoints using cookie authentication return 401 or 403 responses rather than redirecting clients to login pages.

    A Small Design Choice That Prevents Bigger Problems

    One lesson I learned while building APIs is to avoid binding every public endpoint directly to the persistence model.

    It feels convenient initially:

    HTTP request → Product entity → database

    But that creates tight coupling.

    I prefer:

    HTTP request → ProductRequest DTO → Product entity → ProductResponse DTO

    That extra boundary lets me change database fields without unexpectedly changing the API contract.

    It also prevents clients from submitting properties they should never control.

    This is one improvement I would make immediately after learning how to build a REST API in ASP.NET Core, even for a relatively small project.

    REST API Questions Developers Often Ask

    1. How do I build a CRUD REST API in ASP.NET Core?

    Create a Web API project, define models, configure storage, register services, create GET, POST, PUT, and DELETE endpoints, then test each response.

    2. Should I use Controllers or Minimal APIs in ASP.NET Core?

    Microsoft recommends Minimal APIs for many new projects, while controllers remain useful for structured applications that benefit from controller conventions and organization.

    3. Can ASP.NET Core REST APIs use SQL Server?

    Yes. Replace the InMemory provider with an EF Core SQL Server provider, configure the connection string, and manage schema changes through migrations.

    4. Is Swagger the same as OpenAPI in ASP.NET Core?

    Not exactly. OpenAPI is the API description specification, while Swagger commonly refers to tooling used to visualize or interact with OpenAPI-described APIs.

    Your API Works. Now Make It Production-Worthy

    Learning how to build a REST API in ASP.NET Core becomes much easier once I stop treating the project as one large coding task. I separate it into resources, persistence, services, routes, HTTP responses, and testing.

    The product example gives you a working foundation, but I would not stop at CRUD.

    My next step would be replacing the temporary InMemory database, adding DTO validation, standardizing error responses, securing endpoints, and writing integration tests. That is where a tutorial API starts becoming an API I would trust in a real application.

  • How to Create Custom Middleware in Laravel: A Modern Guide

    How to Create Custom Middleware in Laravel: A Modern Guide

    A Laravel route without the right protection can feel like an office with every door unlocked. Anyone may reach pages, actions, or resources that should remain restricted. That is why I use middleware as a smart checkpoint between an incoming request and the application logic behind it.

    In this guide, I’ll show you how to create custom middleware in Laravel to protect admin routes, verify user roles, control subscriptions, and filter requests without cluttering controllers. I’ll also explain the modern setup for Laravel 11, 12, and 13, along with the key difference for older Laravel versions.

    What Does Custom Middleware Do in Laravel?

    Middleware acts as a filter in Laravel’s HTTP request lifecycle. When a request enters the application, middleware can inspect it before allowing it to continue to a route or controller.

    Laravel includes built-in middleware for common requirements such as authentication and CSRF protection. Custom middleware extends that idea to application-specific requirements.

    For example, a US-based SaaS platform might use middleware to restrict account-management pages to administrators, verify an active subscription before displaying premium features, check user roles, log requests, or enforce additional API requirements.

    The major advantage is separation of concerns. Instead of repeating permission checks inside several controllers, I can define the rule once and reuse it. This same approach is useful when troubleshooting How to Fix CORS Error in React and Node.js, where keeping frontend and backend configuration rules organized makes it easier to identify and resolve cross-origin issues.

    How Do I Generate Custom Middleware in Laravel? 

    Laravel’s Artisan command-line tool creates the basic middleware class for me. From the project’s root directory, I run:

    php artisan make:middleware EnsureUserIsAdmin

    Laravel generates:

    app/Http/Middleware/EnsureUserIsAdmin.php

    Using a descriptive name such as EnsureUserIsAdmin also makes the purpose immediately understandable when another developer reviews the project.

    How Do I Add Custom Logic to the handle() Method?

    How Do I Add Custom Logic to the handle() Method

    Next, I open the generated class and add my filtering logic to its handle() method:

    <?php

    namespace App\Http\Middleware;

    use Closure;

    use Illuminate\Http\Request;

    use Symfony\Component\HttpFoundation\Response;

    class EnsureUserIsAdmin

    {

        public function handle(Request $request, Closure $next): Response

        {

            if (!$request->user() || !$request->user()->is_admin) {

                return redirect()

                    ->route(‘home’)

                    ->with(‘error’, ‘Unauthorized access.’);

            }

            return $next($request);

        }

    }

    The $request->user() check confirms that an authenticated user exists, while is_admin represents an application-specific field used to determine administrative access.

    When the condition passes, $next($request) sends the request deeper into Laravel’s application pipeline.

    Should I Redirect the User or Return 403?

    The right response depends on the application.

    For a traditional website, I may redirect the visitor to a safe page and display an error. If an authenticated user is attempting to access something they do not have permission to use, I often prefer:

    abort(403, ‘Unauthorized access.’);

    For an API, a JSON response is usually more appropriate:

    return response()->json([

        ‘message’ => ‘You do not have permission to access this resource.’

    ], 403);

    Choosing the appropriate response makes the behavior clearer for users, front-end applications, and API consumers.

    How Do I Register Middleware in Laravel 11, 12, and 13?

    This is where many older tutorials can cause confusion. Modern Laravel applications configure middleware through bootstrap/app.php rather than the legacy HTTP kernel.

    After learning how to create custom middleware in Laravel, I register an alias so I can easily reuse the middleware across routes.

    A modern bootstrap/app.php configuration can look like this:

    <?php

    use App\Http\Middleware\EnsureUserIsAdmin;

    use Illuminate\Foundation\Application;

    use Illuminate\Foundation\Configuration\Middleware;

    return Application::configure(basePath: dirname(__DIR__))

        ->withRouting(

            web: __DIR__.’/../routes/web.php’,

            commands: __DIR__.’/../routes/console.php’,

            health: ‘/up’,

        )

        ->withMiddleware(function (Middleware $middleware) {

            $middleware->alias([

                ‘admin’ => EnsureUserIsAdmin::class,

            ]);

        })

        ->create();

    The admin alias now gives me a short, readable way to assign EnsureUserIsAdmin to routes.

    What About Laravel 10 and Earlier?

    What About Laravel 10 and Earlier

    Laravel 10 and earlier applications commonly register route middleware in:

    app/Http/Kernel.php

    Always verify your Laravel version before changing middleware configuration. Copying an old Kernel.php tutorial into a modern Laravel project is a common source of unnecessary errors.

    How Do I Protect Laravel Routes With Custom Middleware?

    Once the alias exists, I can protect a single route in routes/web.php:

    use App\Http\Controllers\AdminController;

    Route::get(‘/admin/dashboard’, [AdminController::class, ‘index’])

        ->middleware(‘admin’);

    For several admin routes, a middleware group keeps the routing file cleaner:

    Route::middleware([‘auth’, ‘admin’])->group(function () {

        Route::get(‘/admin/settings’, [AdminController::class, ‘settings’]);

        Route::get(‘/admin/users’, [AdminController::class, ‘users’]);

    });

    Adding auth before admin allows Laravel’s authentication middleware to handle guests before my custom authorization check runs.

    Can I Use the Middleware Class Without an Alias?

    Yes. I can assign the class directly:

    use App\Http\Middleware\EnsureUserIsAdmin;

    Route::get(‘/admin/dashboard’, [AdminController::class, ‘index’])

        ->middleware(EnsureUserIsAdmin::class);

    I usually prefer aliases when middleware appears repeatedly because they make route definitions shorter.

    How Do Global and Web Middleware Registration Work?

    Laravel also allows middleware to run globally. Inside the middleware configuration, I can append a class with:

    $middleware->append(EnsureUserIsAdmin::class);

    That makes it run on every HTTP request, so I would not normally make an admin-only authorization check global.

    Middleware can also be added to Laravel’s web middleware group:

    $middleware->web(append: [

        EnsureUserIsAdmin::class,

    ]);

    I use these approaches only when a middleware rule genuinely applies to every request or every route within that middleware stack. Route-level aliases are safer for narrowly targeted authorization rules.

    How Do I Pass Parameters to Laravel Middleware?

    Parameterized middleware lets one class support several roles.

    For example:

    public function handle(

        Request $request,

        Closure $next,

        string $role

    ): Response {

        if (!$request->user() || $request->user()->role !== $role) {

            abort(403);

        }

        return $next($request);

    }

    I can then apply a role through an alias:

    Route::get(‘/editor’, [EditorController::class, ‘index’])

        ->middleware(‘role:editor’);

    This approach can be cleaner than creating separate middleware classes for administrators, editors, managers, and other roles.

    How Do I Test Custom Middleware?

    How Do I Test Custom Middleware

    I test both authorized and unauthorized scenarios. Laravel feature tests make that straightforward:

    $response = $this->actingAs($regularUser)

        ->get(‘/admin/dashboard’);

    $response->assertForbidden();

    I would also test an administrator and verify that the protected route succeeds. Testing both paths prevents future application changes from silently breaking access controls.

    Why Is My Laravel Middleware Not Working?

    If Laravel does not recognize my middleware alias, I first confirm that the alias in bootstrap/app.php exactly matches the route definition.

    I can also clear cached application data:

    php artisan optimize:clear

    If $request->user() returns null, I verify that authentication runs before the custom middleware by using [‘auth’, ‘admin’].

    For a Target class does not exist error, I check the namespace, filename, class name, imports, and alias. After changing namespaces or classes, regenerating Composer’s autoloader may help:

    composer dump-autoload

    These checks solve many of the common middleware configuration problems I encounter.

    What Are the Best Practices for Laravel Custom Middleware?

    I keep middleware focused on request filtering and avoid placing large business workflows inside the handle() method. Complex authorization may belong in Laravel policies, while broader business operations generally belong in dedicated application or service layers.

    Clear names such as EnsureUserIsAdmin, CheckSubscription, and VerifyAccountStatus also make larger applications easier to understand.

    Most importantly, I check the Laravel version before following registration instructions. The move from app/Http/Kernel.php to configuration in bootstrap/app.php makes version-aware guidance essential.

    Frequently Asked Questions (FAQs)

    1. Where is custom middleware stored in Laravel?

    Laravel normally creates custom middleware classes inside the app/Http/Middleware directory.

    2. Can Laravel routes use multiple middleware?

    Yes. A route or route group can use multiple middleware, such as auth followed by custom role or permission middleware.

    3. Do I have to create an alias for custom middleware?

    No. Laravel allows you to assign the middleware class directly to a route. Aliases are mainly useful for shorter, reusable route definitions.

    4. How to create custom middleware in Laravel for role-based access?

    Generate a middleware class with Artisan, check the authenticated user’s role inside handle(), optionally create an alias in bootstrap/app.php, and attach it to the routes or route groups that require that role.

    Make Middleware Work for You, Not Against You

    I find custom middleware most valuable when I treat it as a focused request filter rather than a place to store every authorization or business rule. A well-designed middleware class can protect routes, verify roles, enforce subscriptions, and keep repetitive request checks out of controllers.

    For current Laravel projects, the greatest detail to remember is where registration happens. Laravel 11, 12, and 13 use bootstrap/app.php, while older projects may still rely on app/Http/Kernel.php. Once I combine the correct registration method with clear aliases, targeted route groups, parameters, and feature tests, middleware becomes a simple and maintainable part of the application architecture.

  • How to Fix CORS Error in React and Node JS Without Losing Your Mind

    How to Fix CORS Error in React and Node JS Without Losing Your Mind

    A CORS warning can stop a perfectly functional React application from communicating with its Node.js API. Your endpoint may work in Postman, your server may return valid JSON, and the browser may still block the response. 

    When I troubleshoot how to fix cors error in react and node js, I begin with the backend because the server must give the browser permission to share its response with the frontend.

    CORS, or Cross-Origin Resource Sharing, is a browser security mechanism. It considers the protocol, hostname, and port when identifying an origin. Therefore, http://localhost:3000, http://localhost:5173, and http://localhost:5000 are three different origins.

    The most reliable solution is to configure CORS in Express. A React proxy can also help during local development, but it does not replace a secure production configuration.

    Why Does CORS Work in Postman but Fail in React?

    Postman, curl, mobile applications, and server-side tools do not enforce browser CORS rules. That is why a Node.js endpoint can work in Postman but fail when React sends the same request.

    The error usually means the browser did not receive an appropriate Access-Control-Allow-Origin header. It can also appear when an OPTIONS preflight request fails, the requested method is not allowed, or cookie settings do not match.

    Before changing your code, open your browser’s Developer Tools and select the Network tab. Find the failed request and check whether an OPTIONS request appears immediately before it. Review the response status, request origin, allowed methods, and returned CORS headers.

    How Do You Enable CORS in Node.js and Express?

    How Do You Enable CORS in Node.js and Express

    The recommended approach is to use the official cors middleware package. Open your backend directory and install it:

    npm install cors

    For a CommonJS Express project, configure the package before defining your routes:

    const express = require(“express”);

    const cors = require(“cors”);

    const app = express();

    const corsOptions = {

      origin: “http://localhost:3000”,

      optionsSuccessStatus: 200

    };

    app.use(cors(corsOptions));

    app.use(express.json());

    app.get(“/api/data”, (req, res) => {

      res.json({ message: “CORS error resolved!” });

    });

    app.listen(5000, () => {

      console.log(“Server running on port 5000”);

    });

    Replace http://localhost:3000 with your actual React URL. Vite commonly runs on port 5173, while older Create React App projects commonly use port 3000.

    For a quick local test, you can allow requests from every origin:

    app.use(cors());

    This configuration is convenient during development, but I would not use it for a private production API (An application programming interface). Production environments should allow only trusted frontend domains.

    How Do You Allow Local, Staging, and Production Domains?

    Many projects need more than one approved origin. You may have a local development address, a staging website, and a public production domain.

    Use an allowlist:

    const allowedOrigins = [

      “http://localhost:5173”,

      “https://staging.example.com”,

      “https://www.example.com”

    ];

    const corsOptions = {

      origin(origin, callback) {

        if (!origin || allowedOrigins.includes(origin)) {

          return callback(null, true);

        }

        return callback(new Error(“Origin not allowed by CORS”));

      },

      methods: [“GET”, “POST”, “PUT”, “PATCH”, “DELETE”],

      allowedHeaders: [“Content-Type”, “Authorization”]

    };

    app.use(cors(corsOptions));

    An allowlist gives you more control than reflecting every origin sent by a browser. It also prevents an accidental wildcard configuration from remaining active after deployment.

    How Do You Fix a CORS Preflight Request Failure?

    Browsers send a preflight OPTIONS request before certain cross-origin requests. This often happens when React sends an Authorization header, uses a custom header, or makes a PUT, PATCH, or DELETE request.

    The Express CORS middleware usually handles preflight requests automatically. However, middleware order matters. Authentication or routing middleware can reject the request before CORS has a chance to add its headers.

    Place CORS near the beginning of your server configuration:

    app.use(cors(corsOptions));

    app.use(express.json());

    app.use(authenticationMiddleware);

    app.use(“/api”, apiRoutes);

    When the browser says that a request header is not allowed, include that header in allowedHeaders. For most APIs, Content-Type and Authorization are the important starting points.

    A failed preflight can also hide another problem. The server may be returning a redirect, a 404 response, or a 500 error without CORS headers. Inspect the actual Network response instead of relying only on the console message.

    How Do You Fix CORS With Cookies, Sessions, or Axios?

    How Do You Fix CORS With Cookies, Sessions, or Axios

    Authenticated requests require coordinated frontend and backend settings. Configure Express to allow credentials and specify the exact frontend origin:

    app.use(

      cors({

        origin: “http://localhost:5173”,

        credentials: true

      })

    );

    With Fetch, include credentials:

    fetch(“http://localhost:5000/api/profile”, {

      credentials: “include”

    });

    With Axios, use:

    axios.get(“http://localhost:5000/api/profile”, {

      withCredentials: true

    });

    Do not combine credentialed requests with origin: “*”. Browsers require a specific origin when cookies or authentication credentials are involved.

    Cross-site production cookies may also require SameSite=None, Secure, and HTTPS. Even with correct CORS headers, browser privacy policies can restrict some third-party cookies.

    How Do You Configure a React Proxy With Create React App?

    A development proxy lets React call a relative path while the development server forwards that request to Node.js.

    For Create React App, add a proxy to package.json:

    {

      “name”: “my-react-app”,

      “version”: “0.1.0”,

      “proxy”: “http://localhost:5000”

    }

    Restart the React development server and change the request from a complete backend URL to a relative path:

    fetch(“/api/data”)

      .then((response) => response.json())

      .then((data) => console.log(data));

    The Create React App proxy only applies during development. It does not configure the production server.

    How Do You Configure a Vite Proxy?

    Vite does not use the Create React App package.json proxy setting. Update vite.config.js instead:

    import { defineConfig } from “vite”;

    import react from “@vitejs/plugin-react”;

    export default defineConfig({

      plugins: [react()],

      server: {

        proxy: {

          “/api”: {

            target: “http://localhost:5000”,

            changeOrigin: true

          }

        }

      }

    });

    You can then call:

    fetch(“/api/data”);

    Vite forwards the request to the Node.js server during local development. Your deployed API still needs correct CORS headers unless the frontend and backend are served through the same origin or reverse proxy.

    Why Does CORS Work Locally but Fail in Production?

    Why Does CORS Work Locally but Fail in Production

    Production failures usually occur because the deployed frontend domain is missing from the backend allowlist. Confirm the exact origin, including HTTPS and any www subdomain, especially when following the steps for How to Import a CSV File Into PostgreSQL pgAdmin.

    You should also check for HTTP-to-HTTPS redirects, incorrect environment variables, reverse-proxy rules, duplicate CORS headers, CDN behavior, and server errors. If Express, Nginx, and an API gateway all add CORS headers, conflicting values can cause the browser to reject the response.

    Avoid browser extensions and mode: “no-cors” as fixes. A browser extension only changes your local browser, while no-cors usually returns an opaque response that your React code cannot read.

    Frequently Asked Questions (FAQs)

    1. What is the fastest way to fix a CORS error in Express?

    Install the cors package, register it before your routes, and allow the exact URL used by your React frontend.

    2. Can React fix a CORS error from a third-party API?

    React cannot grant itself access to another company’s API. The API owner must allow your origin, or you must send the request through a backend you control.

    3. Why does an Authorization header trigger a CORS error?

    The browser may send a preflight request before a request containing an Authorization header. Your server must handle OPTIONS and permit that header.

    4. How to fix cors error in react and node js when using cookies?

    Enable credentials: true in Express, use the exact frontend origin, and enable credentials in Fetch or Axios. Production cookies may also need HTTPS, Secure, and SameSite=None.

    Get React and Node.js Communicating Again

    CORS errors are easier to solve when you identify which layer is failing. Start by checking the browser’s Network panel, configure Express before authentication and routes, and allow only the methods, headers, and origins your application needs.

    Use a Create React App or Vite proxy for convenient local development, but treat server-side CORS configuration as the real production solution. With a trusted-origin allowlist, working preflight responses, and matching credential settings, your React frontend can communicate with Node.js securely and consistently.