---
title: Getting Started
---

This guide walks you through building your first Arc.Core application from scratch. You'll learn how to set up the application, define commands and queries, and run your service.

## Prerequisites

- .NET 9 SDK or later
- Basic understanding of C# and .NET concepts

## Installation

Add the Arc.Core package to your project:

```bash
dotnet add package Cratis.Arc
```

## Basic Setup

Create a new console application and configure Arc.Core:

```csharp
using Cratis.Arc;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;

var builder = ArcApplication.CreateBuilder(args);

// Add Arc services
builder.AddCratisArc(options => options.Hosting.ApplicationUrl = "http://localhost:5000/");

// Configure logging
builder.Services.AddLogging(logging =>
{
    logging.AddConsole();
    logging.SetMinimumLevel(LogLevel.Information);
});

// Build and run the application
var app = builder.Build();

// Wire up the Arc middleware and endpoints
app.UseCratisArc();

Console.WriteLine("Application started on http://localhost:5000/");
Console.WriteLine("Press Ctrl+C to stop...");

await app.RunAsync();
```

## ArcApplicationBuilder API

The `ArcApplicationBuilder` provides a familiar builder pattern for configuring your application:

### Creating a Builder

```csharp
// Create with command-line arguments
var builder = ArcApplication.CreateBuilder(args);

// Or without arguments
var builder = ArcApplication.CreateBuilder();
```

### Available Properties

The builder exposes several properties for configuration:

```csharp
// Configuration system
IConfigurationManager Configuration = builder.Configuration;

// Host environment information
IHostEnvironment Environment = builder.Environment;

// Logging configuration
ILoggingBuilder Logging = builder.Logging;

// Service collection for dependency injection
IServiceCollection Services = builder.Services;

// Metrics configuration
IMetricsBuilder Metrics = builder.Metrics;
```

### Adding Arc Services

```csharp
builder.AddCratisArc(
    configureOptions: options =>
    {
        // Configure Arc-specific options (ArcOptions)
    },
    configureBuilder: arcBuilder =>
    {
        // Add extensions like Chronicle, MongoDB, etc.
    });
```

## ArcApplication API

### Starting the Application

The `UseCratisArc` method wires up the Arc middleware and endpoints. It takes no arguments:

```csharp
// UseCratisArc takes no arguments — it wires up the middleware and endpoints.
app.UseCratisArc();
```

The listen URL is **not** passed here — it comes from configuration via `ArcOptions.Hosting.ApplicationUrl` (default `http://+:5001/`). Set it through the options callback when adding Arc services, or in `appsettings.json` under `Cratis:Arc:Hosting:ApplicationUrl`.

### Running the Application

```csharp
// Run and block until shutdown (Ctrl+C)
await app.RunAsync();

// Or control start/stop manually
await app.StartAsync();
// ... do work ...
await app.StopAsync();
```

## Working with Commands

Commands represent actions or operations in your application. They're automatically exposed as HTTP POST endpoints.

### Defining a Command

```csharp
using Cratis.Arc.Commands;

[Command]
public record CreateUser(string Name, string Email)
{
    public Task Handle(ILogger<CreateUser> logger)
    {
        logger.LogInformation("Creating user: {Name}", Name);
        // Your business logic here
        return Task.CompletedTask;
    }
}
```

### Accessing Command Endpoints

Commands are exposed as POST endpoints:

```bash
curl -X POST http://localhost:5000/api/your-app/create-user \
  -H "Content-Type: application/json" \
  -d '{"name":"John Doe","email":"john@example.com"}'
```

## Working with Queries

Queries represent data retrieval operations. They're automatically exposed as HTTP GET endpoints.

### Defining a Query

```csharp
using Cratis.Arc.Queries;

[ReadModel]
public record User(Guid Id, string Name)
{
    // Exposed as GET; the method's parameters become query arguments.
    public static User GetUser(Guid id) => new(id, "John Doe");
}
```

### Accessing Query Endpoints

Queries are exposed as GET endpoints:

```bash
curl http://localhost:5000/api/your-app/get-user?id=123e4567-e89b-12d3-a456-426614174000
```

## Configuration

### Using appsettings.json

Arc.Core supports standard .NET configuration:

```json
{
  "Cratis": {
    "Arc": {
      "GeneratedApis": {
        "RoutePrefix": "api"
      },
      "CorrelationId": {
        "HttpHeader": "X-Correlation-ID"
      },
      "Tenancy": {
        "HttpHeader": "X-Tenant-ID"
      }
    }
  },
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning"
    }
  }
}
```

### Environment-Specific Configuration

Use environment-specific files following .NET conventions:

- `appsettings.json` - Base configuration
- `appsettings.Development.json` - Development overrides
- `appsettings.Production.json` - Production overrides

```csharp
var builder = ArcApplication.CreateBuilder(args);

// Configuration is automatically loaded based on environment
var environment = builder.Environment.EnvironmentName;
Console.WriteLine($"Running in {environment} environment");
```

### Custom Configuration Section

Specify a custom configuration section path:

```csharp
builder.AddCratisArc(
    configSectionPath: "MyApp:ArcSettings"
);
```

## Adding Services

### Logging

```csharp
builder.Services.AddLogging(logging =>
{
    logging.AddConsole();
    logging.AddDebug();
    logging.SetMinimumLevel(LogLevel.Information);
});
```

### Custom Services

```csharp
// Singleton
builder.Services.AddSingleton<IMyService, MyService>();

// Scoped (per request)
builder.Services.AddScoped<IUserRepository, UserRepository>();

// Transient (per injection)
builder.Services.AddTransient<IEmailSender, EmailSender>();
```

### Using Arc Conventions

Arc supports automatic service registration using attributes:

```csharp
// Services with [Singleton], [Scoped], or [Transient] attributes
// are automatically registered
[Singleton]
public class MyService : IMyService
{
    // Implementation
}
```

## Complete Example

Here's a complete working example that demonstrates commands, queries, and services:

```csharp
using Cratis.Arc;
using Cratis.Arc.Commands;
using Cratis.Arc.Queries;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;

var builder = ArcApplication.CreateBuilder(args);

builder.AddCratisArc(options => options.Hosting.ApplicationUrl = "http://localhost:5000/");

builder.Services.AddLogging(logging =>
{
    logging.AddConsole();
    logging.SetMinimumLevel(LogLevel.Information);
});

var app = builder.Build();

app.UseCratisArc();

Console.WriteLine("Application started!");
Console.WriteLine("Available endpoints:");
Console.WriteLine("  POST   http://localhost:5000/api/my-app/greet");
Console.WriteLine("  GET    http://localhost:5000/api/my-app/get-greeting?name=World");
Console.WriteLine("  GET    http://localhost:5000/.cratis/me");
Console.WriteLine();
Console.WriteLine("Press Ctrl+C to stop...");

await app.RunAsync();

// Commands
[Command]
public record Greet(string Name)
{
    public Task Handle(ILogger<Greet> logger)
    {
        logger.LogInformation("Greeting {Name}", Name);
        return Task.CompletedTask;
    }
}

// Queries
[ReadModel]
public record Greeting(string Text)
{
    public static Greeting GetGreeting(string name) => new($"Hello, {name}!");
}
```

## Advanced Scenarios

### Background Services

Combine Arc.Core with `IHostedService` for background processing:

```csharp
public class BackgroundWorker(ILogger<BackgroundWorker> logger) : BackgroundService
{
    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        logger.LogInformation("Background worker started");
        
        while (!stoppingToken.IsCancellationRequested)
        {
            // Do background work
            await Task.Delay(TimeSpan.FromSeconds(30), stoppingToken);
        }
        
        logger.LogInformation("Background worker stopped");
    }
}

// Register it
builder.Services.AddHostedService<BackgroundWorker>();
```

### Integrating with Chronicle

Add event sourcing capabilities:

```csharp
builder.AddCratisArc(configureBuilder: arcBuilder =>
{
    arcBuilder.WithChronicle();
});
```

### Integrating with MongoDB

Add MongoDB support:

```csharp
builder.AddCratisArc(configureBuilder: arcBuilder =>
{
    arcBuilder.WithMongoDB();
});
```

## Troubleshooting

### Endpoints Not Found

Ensure you've called `app.UseCratisArc()` before `app.RunAsync()`:

```csharp
var app = builder.Build();
app.UseCratisArc();  // Must be called!
await app.RunAsync();
```

### HTTP Listener Errors

If you get HTTP listener errors, ensure:

1. The port is not already in use
2. You have permissions to bind to the port (on Windows, non-admin users can't bind to port 80)
3. Set the listen URL via `ArcOptions.Hosting.ApplicationUrl` (in the options callback or `appsettings.json` under `Cratis:Arc:Hosting:ApplicationUrl`) — it is not passed to `UseCratisArc`. Use `http://+:5001/` instead of `http://localhost:5001/` to listen on all interfaces

### Configuration Not Loading

Ensure `appsettings.json` is copied to output:

```xml
<ItemGroup>
  <None Update="appsettings*.json">
    <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
  </None>
</ItemGroup>
```

## Next Steps

Now that you have a basic Arc.Core application running, explore these topics:

- [Authentication](/arc/backend/core/authentication/) - Implement custom authentication handlers
- [Authorization](/arc/backend/core/authorization/) - Protect your endpoints with authorization attributes
- [Commands](/arc/backend/commands/) - Learn about advanced command patterns
- [Queries](/arc/backend/queries/) - Discover query features like filtering and pagination
- [Identity](/arc/backend/identity/) - Integrate the identity system
- [Tenancy](/arc/backend/tenancy/overview/) - Configure multi-tenant applications
- [Validation](/arc/backend/commands/validation/) - Add validation to commands and queries
