C# and .NET Developer
Jeffallan/claude-skills
Guides C# work on .NET 8+: ASP.NET Core APIs, Entity Framework Core data access, Blazor apps and CQRS with MediatR, following a five-step build workflow.
A skill your agent uses when building .NET 8/9 applications, ASP.NET Core APIs, Entity Framework Core, MediatR CQRS, modular monolith architecture, FluentValidation, Result pattern, JWT…
$ npx skills add LeoYeAI/openclaw-master-skills --skill dotnet-expert -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install LeoYeAI/openclaw-master-skills dotnet-expert --agent claude-codeProject scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).
$ git clone --depth 1 https://github.com/LeoYeAI/openclaw-master-skills.git skills-src && mkdir -p .claude/skills && cp -r skills-src/skills/dotnet-expert .claude/skills/dotnet-expert && rm -rf skills-srcUse ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.
Claude Code skills documentation · loads skills from .claude/skills/
Install the "dotnet-expert" agent skill from https://github.com/LeoYeAI/openclaw-master-skills/tree/main/skills/dotnet-expert into .claude/skills/dotnet-expert/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "dotnet-expert", then confirm the skill loads.Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$skill-installer install https://github.com/LeoYeAI/openclaw-master-skills/tree/main/skills/dotnet-expertType this inside Codex. $skill-installer <name> installs a curated skill from openai/skills. The installer writes to $CODEX_HOME/skills (default ~/.codex/skills). Restart Codex if the skill does not show up.
$ npx skills add LeoYeAI/openclaw-master-skills --skill dotnet-expert -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install LeoYeAI/openclaw-master-skills dotnet-expert --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/LeoYeAI/openclaw-master-skills.git skills-src && mkdir -p .agents/skills && cp -r skills-src/skills/dotnet-expert .agents/skills/dotnet-expert && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "dotnet-expert" agent skill from https://github.com/LeoYeAI/openclaw-master-skills/tree/main/skills/dotnet-expert into .agents/skills/dotnet-expert/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "dotnet-expert", then confirm the skill loads.Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add LeoYeAI/openclaw-master-skills --skill dotnet-expert -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install LeoYeAI/openclaw-master-skills dotnet-expert --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/LeoYeAI/openclaw-master-skills.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/skills/dotnet-expert .cursor/skills/dotnet-expert && rm -rf skills-srcUse ~/.cursor/skills/ instead of .cursor/skills for a personal install.
Cursor skills documentation · loads skills from .cursor/skills/, .agents/skills/, .claude/skills/, .codex/skills/
Install the "dotnet-expert" agent skill from https://github.com/LeoYeAI/openclaw-master-skills/tree/main/skills/dotnet-expert into .cursor/skills/dotnet-expert/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "dotnet-expert", then confirm the skill loads.Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gemini skills install https://github.com/LeoYeAI/openclaw-master-skills.git --path skills/dotnet-expert--scope user (default) or --scope workspace; --path is the subfolder of the repo that holds the skill; --consent skips the security confirmation prompt.
$ npx skills add LeoYeAI/openclaw-master-skills --skill dotnet-expert -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install LeoYeAI/openclaw-master-skills dotnet-expert --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/LeoYeAI/openclaw-master-skills.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/skills/dotnet-expert .gemini/skills/dotnet-expert && rm -rf skills-srcUse ~/.gemini/skills/ instead of .gemini/skills for a personal install, then run /skills reload.
Gemini CLI skills documentation · loads skills from .gemini/skills/, .agents/skills/
Install the "dotnet-expert" agent skill from https://github.com/LeoYeAI/openclaw-master-skills/tree/main/skills/dotnet-expert into .gemini/skills/dotnet-expert/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "dotnet-expert", then confirm the skill loads.Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gh skill install LeoYeAI/openclaw-master-skills dotnet-expertInstalls for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
$ npx skills add LeoYeAI/openclaw-master-skills --skill dotnet-expert -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/LeoYeAI/openclaw-master-skills.git skills-src && mkdir -p .github/skills && cp -r skills-src/skills/dotnet-expert .github/skills/dotnet-expert && rm -rf skills-srcUse ~/.copilot/skills/ instead of .github/skills for a personal install. Commit .github/skills so cloud agent and code review can use it.
GitHub Copilot skills documentation · loads skills from .github/skills/, .claude/skills/, .agents/skills/
Install the "dotnet-expert" agent skill from https://github.com/LeoYeAI/openclaw-master-skills/tree/main/skills/dotnet-expert into .github/skills/dotnet-expert/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "dotnet-expert", then confirm the skill loads.GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add LeoYeAI/openclaw-master-skills --skill dotnet-expert -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install LeoYeAI/openclaw-master-skills dotnet-expert --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/LeoYeAI/openclaw-master-skills.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/skills/dotnet-expert .opencode/skills/dotnet-expert && rm -rf skills-srcUse ~/.config/opencode/skills/ instead of .opencode/skills for a personal install.
OpenCode skills documentation · loads skills from .opencode/skills/, .claude/skills/, .agents/skills/
Install the "dotnet-expert" agent skill from https://github.com/LeoYeAI/openclaw-master-skills/tree/main/skills/dotnet-expert into .opencode/skills/dotnet-expert/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "dotnet-expert", then confirm the skill loads.OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
dotnet-expertA skill your agent uses when building .NET 8/9 applications, ASP.NET Core APIs, Entity Framework Core, MediatR CQRS, modular monolith architecture, FluentValidation, Result pattern, JWT…
Dotnet Expert is an agent skill from LeoYeAI/openclaw-master-skills. Use when building .NET 8/9 applications, ASP.NET Core APIs, Entity Framework Core, MediatR CQRS, modular monolith architecture, FluentValidation, Result pattern, JWT authentication, or any C backend development question.
Its SKILL.md is about 4.7k tokens, which your agent loads only when the skill is triggered. The skill folder holds 1 other file (for example `_meta.json`).
It sits in Backend & APIs, covering Authentication, Event-driven systems and ORMs and data access. It works with .NET, ASP.NET Core and C#. The repository describes itself as: 🧠 Curated collection of 1209+ best OpenClaw skills — weekly updated by MyClaw.ai. The licence is MIT.
6 steps, taken from the first numbered list in SKILL.md.
Read from SKILL.md and the folder at commit e5199b5. It shows what the files ask for, not the result of running them.
Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.
From allowed-tools in the SKILL.md frontmatter.
Shell commands in SKILL.md call:
dotnetFrom the folder's file list and the shell code blocks in SKILL.md.
No URLs in SKILL.md.
From URLs in SKILL.md, links to its own repository left out.
Names no API keys, tokens, secrets or passwords.
From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
Dotnet Expert loads about 4.7k tokens when it runs. Until then it costs about 59 tokens; SKILL.md has 260 words of instructions outside code blocks.
Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.
The automated check found no risky patterns in SKILL.md.
Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.
The full file from LeoYeAI/openclaw-master-skills at commit e5199b5, republished under its MIT licence (© LeoYeAI). 260 words, ~4,740 tokens.
.claude/skills/dotnet-expert/SKILL.md (or your agent's skills folder). This skill also uses 1 other file; get the full folder from GitHub.Senior .NET 9 / ASP.NET Core specialist with expertise in clean architecture, CQRS, and modular monolith patterns.
You are a senior .NET engineer building production-grade APIs with ASP.NET Core, Entity Framework Core 9, MediatR, and FluentValidation. You follow clean architecture principles with a pragmatic approach.
.Result or .Wait()src/
├── Api/ # ASP.NET Core host
│ ├── Program.cs
│ ├── appsettings.json
│ └── Endpoints/ # Minimal API endpoint definitions
├── Modules/
│ ├── Users/
│ │ ├── Users.Core/ # Domain entities, interfaces
│ │ ├── Users.Application/ # Commands, queries, handlers
│ │ └── Users.Infrastructure/ # EF Core, external services
│ ├── Orders/
│ │ ├── Orders.Core/
│ │ ├── Orders.Application/
│ │ └── Orders.Infrastructure/
│ └── Shared/
│ ├── Shared.Core/ # Common abstractions
│ └── Shared.Infrastructure/# Cross-cutting concerns
└── Tests/
├── Users.Tests/
└── Orders.Tests/// Api/Endpoints/UserEndpoints.cs
public static class UserEndpoints
{
public static void MapUserEndpoints(this IEndpointRouteBuilder app)
{
var group = app.MapGroup("/api/users")
.WithTags("Users")
.RequireAuthorization();
group.MapGet("/", GetUsers);
group.MapGet("/{id:guid}", GetUserById);
group.MapPost("/", CreateUser);
group.MapPut("/{id:guid}", UpdateUser);
group.MapDelete("/{id:guid}", DeleteUser);
}
private static async Task<IResult> GetUsers(
[AsParameters] GetUsersQuery query,
ISender mediator,
CancellationToken ct)
{
var result = await mediator.Send(query, ct);
return result.Match(
success => Results.Ok(success),
error => Results.Problem(error.ToProblemDetails()));
}
private static async Task<IResult> GetUserById(
Guid id,
ISender mediator,
CancellationToken ct)
{
var result = await mediator.Send(new GetUserByIdQuery(id), ct);
return result.Match(
success => Results.Ok(success),
error => error.Type == ErrorType.NotFound
? Results.NotFound()
: Results.Problem(error.ToProblemDetails()));
}
private static async Task<IResult> CreateUser(
CreateUserCommand command,
ISender mediator,
CancellationToken ct)
{
var result = await mediator.Send(command, ct);
return result.Match(
success => Results.Created($"/api/users/{success.Id}", success),
error => Results.Problem(error.ToProblemDetails()));
}
}var builder = WebApplication.CreateBuilder(args);
// Add modules
builder.Services.AddUsersModule(builder.Configuration);
builder.Services.AddOrdersModule(builder.Configuration);
// Add shared infrastructure
builder.Services.AddMediatR(cfg =>
cfg.RegisterServicesFromAssemblies(
typeof(UsersModule).Assembly,
typeof(OrdersModule).Assembly));
builder.Services.AddValidatorsFromAssemblies(new[]
{
typeof(UsersModule).Assembly,
typeof(OrdersModule).Assembly,
});
// Add validation pipeline behavior
builder.Services.AddTransient(typeof(IPipelineBehavior<,>), typeof(ValidationBehavior<,>));
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidateAudience = true,
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
ValidIssuer = builder.Configuration["Jwt:Issuer"],
ValidAudience = builder.Configuration["Jwt:Audience"],
IssuerSigningKey = new SymmetricSecurityKey(
Encoding.UTF8.GetBytes(builder.Configuration["Jwt:Key"]!)),
};
});
builder.Services.AddAuthorization();
var app = builder.Build();
app.UseAuthentication();
app.UseAuthorization();
app.MapUserEndpoints();
app.MapOrderEndpoints();
app.Run();// Shared.Core/Result.cs
public sealed class Result<T>
{
public T? Value { get; }
public Error? Error { get; }
public bool IsSuccess { get; }
private Result(T value) { Value = value; IsSuccess = true; }
private Result(Error error) { Error = error; IsSuccess = false; }
public static Result<T> Success(T value) => new(value);
public static Result<T> Failure(Error error) => new(error);
public TResult Match<TResult>(
Func<T, TResult> onSuccess,
Func<Error, TResult> onFailure) =>
IsSuccess ? onSuccess(Value!) : onFailure(Error!);
}
public sealed record Error(string Code, string Message, ErrorType Type = ErrorType.Failure)
{
public static Error NotFound(string code, string message) => new(code, message, ErrorType.NotFound);
public static Error Validation(string code, string message) => new(code, message, ErrorType.Validation);
public static Error Conflict(string code, string message) => new(code, message, ErrorType.Conflict);
public static Error Forbidden(string code, string message) => new(code, message, ErrorType.Forbidden);
public ProblemDetails ToProblemDetails() => new()
{
Title = Code,
Detail = Message,
Status = Type switch
{
ErrorType.NotFound => StatusCodes.Status404NotFound,
ErrorType.Validation => StatusCodes.Status400BadRequest,
ErrorType.Conflict => StatusCodes.Status409Conflict,
ErrorType.Forbidden => StatusCodes.Status403Forbidden,
_ => StatusCodes.Status500InternalServerError,
},
};
}
public enum ErrorType { Failure, NotFound, Validation, Conflict, Forbidden }// No exceptions for business logic!
public sealed class CreateUserHandler : IRequestHandler<CreateUserCommand, Result<UserResponse>>
{
private readonly AppDbContext _db;
public CreateUserHandler(AppDbContext db) => _db = db;
public async Task<Result<UserResponse>> Handle(
CreateUserCommand command, CancellationToken ct)
{
// Business rule validation returns errors, not exceptions
var existingUser = await _db.Users
.AnyAsync(u => u.Email == command.Email, ct);
if (existingUser)
return Result<UserResponse>.Failure(
Error.Conflict("User.DuplicateEmail", "A user with this email already exists"));
var user = new User
{
Id = Guid.NewGuid(),
Email = command.Email,
Name = command.Name,
CreatedAt = DateTime.UtcNow,
};
_db.Users.Add(user);
await _db.SaveChangesAsync(ct);
return Result<UserResponse>.Success(user.ToResponse());
}
}// Users.Application/Commands/CreateUserCommand.cs
public sealed record CreateUserCommand(
string Email,
string Name,
string Password) : IRequest<Result<UserResponse>>;// Users.Application/Queries/GetUsersQuery.cs
public sealed record GetUsersQuery(
int Page = 1,
int PageSize = 20,
string? Search = null) : IRequest<Result<PagedResult<UserResponse>>>;
public sealed class GetUsersHandler : IRequestHandler<GetUsersQuery, Result<PagedResult<UserResponse>>>
{
private readonly AppDbContext _db;
public GetUsersHandler(AppDbContext db) => _db = db;
public async Task<Result<PagedResult<UserResponse>>> Handle(
GetUsersQuery query, CancellationToken ct)
{
var dbQuery = _db.Users.AsNoTracking();
if (!string.IsNullOrWhiteSpace(query.Search))
dbQuery = dbQuery.Where(u =>
u.Name.Contains(query.Search) || u.Email.Contains(query.Search));
var total = await dbQuery.CountAsync(ct);
var users = await dbQuery
.OrderBy(u => u.Name)
.Skip((query.Page - 1) * query.PageSize)
.Take(query.PageSize)
.Select(u => u.ToResponse())
.ToListAsync(ct);
return Result<PagedResult<UserResponse>>.Success(
new PagedResult<UserResponse>(users, total, query.Page, query.PageSize));
}
}public sealed class ValidationBehavior<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse>
where TRequest : IRequest<TResponse>
{
private readonly IEnumerable<IValidator<TRequest>> _validators;
public ValidationBehavior(IEnumerable<IValidator<TRequest>> validators)
=> _validators = validators;
public async Task<TResponse> Handle(
TRequest request,
RequestHandlerDelegate<TResponse> next,
CancellationToken ct)
{
if (!_validators.Any()) return await next();
var context = new ValidationContext<TRequest>(request);
var results = await Task.WhenAll(
_validators.Select(v => v.ValidateAsync(context, ct)));
var failures = results
.SelectMany(r => r.Errors)
.Where(f => f != null)
.ToList();
if (failures.Count > 0)
throw new ValidationException(failures);
return await next();
}
}public sealed class CreateUserValidator : AbstractValidator<CreateUserCommand>
{
public CreateUserValidator()
{
RuleFor(x => x.Email)
.NotEmpty().WithMessage("Email is required")
.EmailAddress().WithMessage("Invalid email format")
.MaximumLength(255);
RuleFor(x => x.Name)
.NotEmpty().WithMessage("Name is required")
.MinimumLength(2)
.MaximumLength(100)
.Matches(@"^[a-zA-Z\s'-]+$").WithMessage("Name contains invalid characters");
RuleFor(x => x.Password)
.NotEmpty()
.MinimumLength(8)
.Matches("[A-Z]").WithMessage("Password must contain uppercase letter")
.Matches("[a-z]").WithMessage("Password must contain lowercase letter")
.Matches("[0-9]").WithMessage("Password must contain a number")
.Matches("[^a-zA-Z0-9]").WithMessage("Password must contain a special character");
}
}public sealed class AppDbContext : DbContext
{
public DbSet<User> Users => Set<User>();
public DbSet<Order> Orders => Set<Order>();
public DbSet<OrderItem> OrderItems => Set<OrderItem>();
public AppDbContext(DbContextOptions<AppDbContext> options) : base(options) { }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.ApplyConfigurationsFromAssembly(typeof(AppDbContext).Assembly);
}
public override async Task<int> SaveChangesAsync(CancellationToken ct = default)
{
// Auto-set audit fields
foreach (var entry in ChangeTracker.Entries<IAuditable>())
{
if (entry.State == EntityState.Added)
entry.Entity.CreatedAt = DateTime.UtcNow;
if (entry.State == EntityState.Modified)
entry.Entity.UpdatedAt = DateTime.UtcNow;
}
return await base.SaveChangesAsync(ct);
}
}public sealed class UserConfiguration : IEntityTypeConfiguration<User>
{
public void Configure(EntityTypeBuilder<User> builder)
{
builder.ToTable("users");
builder.HasKey(u => u.Id);
builder.Property(u => u.Email)
.HasMaxLength(255)
.IsRequired();
builder.HasIndex(u => u.Email).IsUnique();
builder.Property(u => u.Name)
.HasMaxLength(100)
.IsRequired();
builder.Property(u => u.PasswordHash)
.HasMaxLength(255)
.IsRequired();
builder.HasMany(u => u.Orders)
.WithOne(o => o.User)
.HasForeignKey(o => o.UserId)
.OnDelete(DeleteBehavior.Cascade);
// Query filter for soft delete
builder.HasQueryFilter(u => u.DeletedAt == null);
}
}# Create migration
dotnet ef migrations add AddUserTable -p src/Users.Infrastructure -s src/Api
# Apply migration
dotnet ef database update -p src/Users.Infrastructure -s src/Api
# Generate SQL script (for production)
dotnet ef migrations script -p src/Users.Infrastructure -s src/Api -o migrations.sql --idempotent// ❌ BAD: N+1 queries
var users = await _db.Users.ToListAsync(ct);
foreach (var user in users)
{
var orders = await _db.Orders.Where(o => o.UserId == user.Id).ToListAsync(ct);
}
// ✅ GOOD: Eager loading
var users = await _db.Users
.Include(u => u.Orders)
.ToListAsync(ct);
// ✅ BEST: Projection (only load what you need)
var users = await _db.Users
.AsNoTracking()
.Select(u => new UserResponse
{
Id = u.Id,
Name = u.Name,
Email = u.Email,
OrderCount = u.Orders.Count,
})
.ToListAsync(ct);builder.Services.AddIdentity<ApplicationUser, IdentityRole<Guid>>(options =>
{
options.Password.RequireDigit = true;
options.Password.RequiredLength = 8;
options.Password.RequireUppercase = true;
options.Password.RequireNonAlphanumeric = true;
options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(15);
options.Lockout.MaxFailedAccessAttempts = 5;
})
.AddEntityFrameworkStores<AppDbContext>()
.AddDefaultTokenProviders();public sealed class TokenService : ITokenService
{
private readonly IConfiguration _config;
public TokenService(IConfiguration config) => _config = config;
public string GenerateAccessToken(ApplicationUser user, IList<string> roles)
{
var claims = new List<Claim>
{
new(ClaimTypes.NameIdentifier, user.Id.ToString()),
new(ClaimTypes.Email, user.Email!),
new(ClaimTypes.Name, user.UserName!),
};
claims.AddRange(roles.Select(role => new Claim(ClaimTypes.Role, role)));
var key = new SymmetricSecurityKey(
Encoding.UTF8.GetBytes(_config["Jwt:Key"]!));
var token = new JwtSecurityToken(
issuer: _config["Jwt:Issuer"],
audience: _config["Jwt:Audience"],
claims: claims,
expires: DateTime.UtcNow.AddMinutes(15),
signingCredentials: new SigningCredentials(key, SecurityAlgorithms.HmacSha256));
return new JwtSecurityTokenHandler().WriteToken(token);
}
public string GenerateRefreshToken()
{
var randomBytes = new byte[64];
using var rng = RandomNumberGenerator.Create();
rng.GetBytes(randomBytes);
return Convert.ToBase64String(randomBytes);
}
}public sealed class Order : IAuditable
{
public Guid Id { get; private set; }
public Guid UserId { get; private set; }
public OrderStatus Status { get; private set; }
public decimal Total { get; private set; }
public DateTime CreatedAt { get; set; }
public DateTime? UpdatedAt { get; set; }
private readonly List<OrderItem> _items = [];
public IReadOnlyCollection<OrderItem> Items => _items.AsReadOnly();
private Order() { } // EF Core
public static Order Create(Guid userId)
{
return new Order
{
Id = Guid.NewGuid(),
UserId = userId,
Status = OrderStatus.Pending,
Total = 0,
};
}
public Result<OrderItem> AddItem(Guid productId, int quantity, decimal unitPrice)
{
if (Status != OrderStatus.Pending)
return Result<OrderItem>.Failure(
Error.Validation("Order.NotPending", "Cannot add items to a non-pending order"));
if (quantity <= 0)
return Result<OrderItem>.Failure(
Error.Validation("Order.InvalidQuantity", "Quantity must be positive"));
var item = new OrderItem(Guid.NewGuid(), Id, productId, quantity, unitPrice);
_items.Add(item);
RecalculateTotal();
return Result<OrderItem>.Success(item);
}
public Result<bool> Submit()
{
if (_items.Count == 0)
return Result<bool>.Failure(
Error.Validation("Order.Empty", "Cannot submit an empty order"));
Status = OrderStatus.Submitted;
return Result<bool>.Success(true);
}
private void RecalculateTotal()
{
Total = _items.Sum(i => i.Quantity * i.UnitPrice);
}
}
public enum OrderStatus { Pending, Submitted, Processing, Shipped, Delivered, Cancelled }.Result or .Wait() on async calls — async all the wayIQueryable from repositories — materialize queries in the handlerAutoMapper for simple mappings — manual mapping or extension methodsException broadly — catch specific exceptions at infrastructure boundariesIConfiguration and environment variablesCancellationToken — pass it through the entire call chainDbContext without AsNoTracking() for read queries© LeoYeAI, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file
SKILL.md and 1 other file in skills/dotnet-expert of LeoYeAI/openclaw-master-skills.
Open the folder on GitHubat commit e5199b5
Dotnet Expert next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.
| Skill | Stars | Used in | Tokens | Auto-check | Licence | Repo updated |
|---|---|---|---|---|---|---|
| Dotnet Expert this skillLeoYeAI/openclaw-master-skills | 2.2k | — | ~4.7k | Automated safety check: Pass | MIT | |
| C# and .NET DeveloperJeffallan/claude-skills | 12k | — | ~1.3k | Automated safety check: Pass | MIT | |
| .NET Core ExpertJeffallan/claude-skills | 12k | — | ~1.3k | Automated safety check: Pass | MIT | |
| Dotnet Backend Patternswshobson/agents | 40k | 8 repos | ~6.6k | Automated safety check: Pass | MIT | |
| Dotnet Architectaiskillstore/marketplace | 430 | 7 repos | ~1.9k | Automated safety check: Pass | None | |
| Writing Csharp Codemicrosoft-foundry/foundry-agent-webapp | 127 | — | ~3.2k | Automated safety check: Notes | MIT |
Jeffallan/claude-skills
Guides C# work on .NET 8+: ASP.NET Core APIs, Entity Framework Core data access, Blazor apps and CQRS with MediatR, following a five-step build workflow.
Jeffallan/claude-skills
Guides building .NET 8 services with minimal APIs, clean architecture, Entity Framework Core, MediatR CQRS and JWT authentication, with build and test checks.
wshobson/agents
Master C/.NET backend development patterns for building robust APIs, MCP servers, and enterprise applications.
aiskillstore/marketplace
Expert .NET backend architect specializing in C, ASP.NET Core, Entity Framework, Dapper, and enterprise application patterns.
microsoft-foundry/foundry-agent-webapp
Provides C and ASP.NET Core coding standards for this repository.
ericrisco/rsc-harness
A skill your agent uses when writing, reviewing, testing, or shipping C / .NET code — ASP.NET Core APIs (minimal APIs vs controllers), EF Core data access, async correctness, solution layout in…
LeoYeAI/openclaw-master-skills
Manages pipelines on a DevOps quality and efficiency platform through its OpenAPI: list workspaces and templates, create, update, run and cancel pipelines, and read run records.
LeoYeAI/openclaw-master-skills
Patches OpenClaw's Feishu extension so an edited document triggers an isolated agent session that reads the doc and replies inline, turning it into a live chat space.
LeoYeAI/openclaw-master-skills
Multi-context memory management system for OpenClaw agents with group-isolated storage, global shared memory, workspace organization, and group-specific skills isolation.
LeoYeAI/openclaw-master-skills
Runs a brand's AI-search visibility work end to end: diagnosing how AI platforms represent it, repositioning it, producing AI-optimized content and monitoring ongoing mentions.
LeoYeAI/openclaw-master-skills
Installs and authenticates the gws CLI, then automates Gmail, Drive, Sheets, Calendar, Docs, Chat and Tasks with ready-made recipes, persona bundles and security audits.
LeoYeAI/openclaw-master-skills
Runs four advisor roles, a fitness coach, nutritionist, data analyst and TCM practitioner, to build a health profile and track workouts, diet and wellness over time.
Works with
Categories
A skill your agent uses when building .NET 8/9 applications, ASP.NET Core APIs, Entity Framework Core, MediatR CQRS, modular monolith architecture, FluentValidation, Result pattern, JWT…. Dotnet Expert is an agent skill from LeoYeAI/openclaw-master-skills.NET Core APIs, Entity Framework Core, MediatR CQRS, modular monolith architecture, FluentValidation, Result pattern, JWT authentication, or any C backend development question.
Dotnet Expert fits situations like: building .NET 8/9 applications; ASP.NET Core APIs; entity Framework Core; modular monolith architecture.
Run `npx skills add LeoYeAI/openclaw-master-skills --skill dotnet-expert -a claude-code`. Or copy the skill folder (skills/dotnet-expert in LeoYeAI/openclaw-master-skills) into .claude/skills/dotnet-expert in your project. Claude Code loads it when a task matches its description.
Run `npx skills add LeoYeAI/openclaw-master-skills --skill dotnet-expert -a codex`. Or copy the skill folder (skills/dotnet-expert in LeoYeAI/openclaw-master-skills) into .agents/skills/dotnet-expert in your project. Codex loads it when a task matches its description.
Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add LeoYeAI/openclaw-master-skills --skill dotnet-expert -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/dotnet-expert, .gemini/skills/dotnet-expert, .github/skills/dotnet-expert and .opencode/skills/dotnet-expert in your project.
Going by SKILL.md and its folder, Dotnet Expert needs the command-line tools its instructions call (dotnet).
SKILL.md contains no URLs. Any network use would come from the scripts or tools the agent runs. This is read from the text; nothing was executed.
Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.
Dotnet Expert is published under the MIT licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.
About 4.7k tokens (SKILL.md is roughly 19k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.
Skills that share tags, products or a category with Dotnet Expert: C# and .NET Developer (Jeffallan/claude-skills, 12k stars), .NET Core Expert (Jeffallan/claude-skills, 12k stars), Dotnet Backend Patterns (wshobson/agents, 40k stars) and Dotnet Architect (aiskillstore/marketplace, 430 stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
LeoYeAI (a GitHub user) maintains it in LeoYeAI/openclaw-master-skills, which has 2,160 GitHub stars. The repository holds 1,235 skills in this directory. The repository was last updated on July 20, 2026.
Source: LeoYeAI/openclaw-master-skills on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.