Services & Helpers

Put code in another file — a service or a static helper — and call it from anywhere, the C# way.

~3 min read updated Jul 19, 2026 Csharp
  • #csharp
  • #dotnet
  • #services
  • #architecture

You already write services in Laravel — the C# version is nearly the same shape. The two things to learn are how another file becomes visible (namespaces + using) and when to make it a static helper vs an instance service.

A service in its own file

Say you have a login service. It lives in its own file, in a namespace:

Services/LoginService.cs
using MyApp.Models;

namespace MyApp.Services;

public class LoginService
{
    private readonly List<User> _users;

    public LoginService(List<User> users)
    {
        _users = users;
    }

    // Return a RESULT — let the caller decide how to present it.
    public User? Login(string username, string password)
    {
        return _users.FirstOrDefault(
            u => u.Username == username && u.Password == password
        );
    }
}

Use it from Program.csusing makes the namespace visible:

Program.cs
using MyApp.Models;
using MyApp.Services;

var users = new List<User>
{
    new User { Username = "ada", Password = "secret" }
};

var loginService = new LoginService(users);

var user = loginService.Login("ada", "secret");

// The CALLER handles presentation, not the service:
if (user is not null)
    Console.WriteLine($"Welcome, {user.Username}!");
else
    Console.WriteLine("Invalid credentials.");
Don't put Console.WriteLineinside the service. A service that returns a User? (or a success/failure result) can be reused from a console app, a web API, or a test. A service that prints to the console can only ever be a console app. Same rule as Laravel: the service returns data, the controller renders it. See Services return, callers present.

Static helper (utility functions)

A helper is stateless — a bag of pure functions, like a Laravel helper file. Make the class static so you call it directly without new:

Helpers/TextHelper.cs
namespace MyApp.Helpers;

public static class TextHelper
{
    public static string Slugify(string input)
    {
        return input.Trim().ToLower().Replace(" ", "-");
    }
}
Program.cs
using MyApp.Helpers;

var slug = TextHelper.Slugify("Hello World");   // "hello-world"

Service vs helper — which one?

Use a service (instance)Use a static helper
Holds state or dependencies (a user list, a DB, config)Pure input → output, no state
You want to swap/mock it in testsNever needs mocking
new LoginService(users)TextHelper.Slugify(...)
Laravel: an injected service classLaravel: a helpers.php function

The grown-up version: dependency injection

Creating services with new by hand is fine for a small console app. Real .NET apps register services in a container and let it hand them to you — exactly like Laravel's service container binding:

// In a full app's startup:
builder.Services.AddScoped<LoginService>();

// Then any class can just ask for it in its constructor:
public class LoginController(LoginService loginService) { /* ... */ }
You don't need DI yet for a terminal app — new is honest and simple. But recognise it when you see it: AddScoped / AddSingleton / AddTransient is .NET doing what $this->app->bind() does in Laravel. Reach for it once you have more than a handful of services wiring each other up.

Next

See how namespaces, folders and the dotnet CLI tie all these files together → Project structure.

Related notes