dotnet-framework
# .NET Framework Skill - Quick Reference
What this skill does
# .NET Framework Skill - Quick Reference
**Framework**: .NET 8+ with ASP.NET Core
**For Agent**: backend-developer
**Purpose**: Fast lookup of common .NET patterns and conventions
---
## 1. ASP.NET Core Web APIs
### Controller-Based API
```csharp
[ApiController]
[Route("api/[controller]")]
public class OrdersController : ControllerBase
{
private readonly IMessageBus _bus;
private readonly IQuerySession _session;
public OrdersController(IMessageBus bus, IQuerySession session)
{
_bus = bus;
_session = session;
}
[HttpGet("{id}")]
public async Task<ActionResult<OrderDto>> GetOrder(Guid id)
{
var order = await _session.LoadAsync<Order>(id);
return order is not null
? Ok(OrderDto.FromEntity(order))
: NotFound();
}
[HttpPost]
public async Task<ActionResult<Guid>> CreateOrder(CreateOrderCommand command)
{
var orderId = await _bus.InvokeAsync<Guid>(command);
return CreatedAtAction(nameof(GetOrder), new { id = orderId }, orderId);
}
[HttpPut("{id}")]
public async Task<ActionResult> UpdateOrder(Guid id, UpdateOrderCommand command)
{
if (id != command.OrderId)
return BadRequest("ID mismatch");
await _bus.InvokeAsync(command);
return NoContent();
}
[HttpDelete("{id}")]
public async Task<ActionResult> DeleteOrder(Guid id)
{
await _bus.InvokeAsync(new DeleteOrderCommand(id));
return NoContent();
}
}
```
### Minimal API (.NET 8+)
```csharp
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
var orders = app.MapGroup("/api/orders")
.WithTags("Orders")
.WithOpenApi();
orders.MapGet("/{id}", async (Guid id, IQuerySession session) =>
{
var order = await session.LoadAsync<Order>(id);
return order is not null ? Results.Ok(order) : Results.NotFound();
})
.WithName("GetOrder")
.Produces<Order>(StatusCodes.Status200OK)
.Produces(StatusCodes.Status404NotFound);
orders.MapPost("/", async (CreateOrderCommand cmd, IMessageBus bus) =>
{
var orderId = await bus.InvokeAsync<Guid>(cmd);
return Results.Created($"/api/orders/{orderId}", orderId);
})
.WithName("CreateOrder")
.Produces<Guid>(StatusCodes.Status201Created);
app.Run();
```
### Program.cs Setup
```csharp
var builder = WebApplication.CreateBuilder(args);
// Add services
builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
// Marten configuration
builder.Services.AddMarten(opts =>
{
opts.Connection(builder.Configuration.GetConnectionString("Postgres")!);
opts.AutoCreateSchemaObjects = AutoCreate.CreateOrUpdate;
// Document schema
opts.Schema.For<Order>()
.Index(x => x.CustomerId)
.Index(x => x.Status);
});
// Wolverine message bus
builder.Host.UseWolverine();
var app = builder.Build();
// Middleware pipeline
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();
app.Run();
```
---
## 2. Wolverine Message Handling
### Command Handlers
```csharp
// Command
public record CreateOrderCommand(Guid CustomerId, List<OrderItem> Items);
// Handler (static method)
public static class CreateOrderHandler
{
public static async Task<Guid> Handle(
CreateOrderCommand command,
IDocumentSession session,
CancellationToken ct)
{
var order = new Order
{
Id = Guid.NewGuid(),
CustomerId = command.CustomerId,
Items = command.Items,
Status = OrderStatus.Pending,
CreatedAt = DateTimeOffset.UtcNow
};
session.Store(order);
await session.SaveChangesAsync(ct);
// Publish event
await session.Events.Append(order.Id, new OrderCreated(order.Id, order.CustomerId));
return order.Id;
}
}
```
### Query Handlers
```csharp
// Query
public record GetOrderQuery(Guid OrderId);
// Handler
public static class GetOrderQueryHandler
{
public static async Task<OrderDto?> Handle(
GetOrderQuery query,
IQuerySession session)
{
var order = await session.LoadAsync<Order>(query.OrderId);
return order is not null ? OrderDto.FromEntity(order) : null;
}
}
// Query with pagination
public record GetCustomerOrdersQuery(Guid CustomerId, int Page = 1, int PageSize = 20);
public static class GetCustomerOrdersHandler
{
public static async Task<PagedResult<OrderDto>> Handle(
GetCustomerOrdersQuery query,
IQuerySession session)
{
var orders = await session.Query<Order>()
.Where(o => o.CustomerId == query.CustomerId)
.OrderByDescending(o => o.CreatedAt)
.Skip((query.Page - 1) * query.PageSize)
.Take(query.PageSize)
.ToListAsync();
var total = await session.Query<Order>()
.CountAsync(o => o.CustomerId == query.CustomerId);
return new PagedResult<OrderDto>(
orders.Select(OrderDto.FromEntity),
total,
query.Page,
query.PageSize
);
}
}
```
### Event Handlers
```csharp
// Event
public record OrderCreated(Guid OrderId, Guid CustomerId);
public record OrderShipped(Guid OrderId, string TrackingNumber);
// Event handler
public static class OrderCreatedHandler
{
public static async Task Handle(
OrderCreated evt,
IDocumentSession session,
ILogger<OrderCreatedHandler> logger)
{
logger.LogInformation("Order {OrderId} created for customer {CustomerId}",
evt.OrderId, evt.CustomerId);
// Trigger follow-up actions
// Events are automatically cascaded if returned
}
}
```
---
## 3. MartenDB Document Storage
### Basic Document Operations
```csharp
// Store document
public async Task<Order> CreateOrder(Order order)
{
using var session = _store.LightweightSession();
session.Store(order);
await session.SaveChangesAsync();
return order;
}
// Load document
public async Task<Order?> GetOrder(Guid id)
{
using var session = _store.QuerySession();
return await session.LoadAsync<Order>(id);
}
// Update document
public async Task UpdateOrder(Order order)
{
using var session = _store.LightweightSession();
session.Update(order);
await session.SaveChangesAsync();
}
// Delete document
public async Task DeleteOrder(Guid id)
{
using var session = _store.LightweightSession();
session.Delete<Order>(id);
await session.SaveChangesAsync();
}
```
### Querying with LINQ
```csharp
// Simple queries
var orders = await session.Query<Order>()
.Where(o => o.CustomerId == customerId)
.ToListAsync();
// Complex queries
var recentOrders = await session.Query<Order>()
.Where(o => o.Status == OrderStatus.Pending)
.Where(o => o.CreatedAt > DateTimeOffset.UtcNow.AddDays(-30))
.OrderByDescending(o => o.CreatedAt)
.Take(10)
.ToListAsync();
// Aggregations
var totalAmount = await session.Query<Order>()
.Where(o => o.CustomerId == customerId)
.SumAsync(o => o.TotalAmount);
var orderCount = await session.Query<Order>()
.CountAsync(o => o.Status == OrderStatus.Completed);
```
### Compiled Queries (Performance)
```csharp
public class OrdersByCustomer : ICompiledQuery<Order, IReadOnlyList<Order>>
{
public Guid CustomerId { get; init; }
public Expression<Func<IMartenQueryable<Order>, IReadOnlyList<Order>>> QueryIs()
{
return q => q.Where(x => x.CustomerId == CustomerId)
.OrderByDescending(x => x.CreatedAt)
.ToList();
}
}
// Usage
var query = new OrdersByCustomer { CustomerId = customerId };
var orders = await session.QueryAsync(query);
```
---
## 4. Event Sourcing
### Event Stream Operations
```csharp
// Start new event stream
public async TasRelated in General
modeling-omnistudio-epc-catalog
IncludedSalesforce Industries CME EPC product-modeling skill for Product2-based catalog creation. Use when creating EPC products, configuring product attributes, building offer bundles with Product Child Items, or reviewing EPC DataPack JSON metadata for product catalog changes. TRIGGER when: user creates or updates Product2 EPC records, AttributeAssignment payloads, AttributeMetadata/AttributeDefaultValues, Offer bundles, or ProductChildItem relationships. DO NOT TRIGGER when: designing OmniScripts/FlexCards/Integration Procedures (use building-omnistudio-omniscript, building-omnistudio-flexcard, or building-omnistudio-integration-procedure), implementing Apex business logic (use generating-apex), or troubleshooting deployment pipelines (use deploying-metadata).
relationship-science-coach
IncludedUse this skill for direct, practical adult relationship coaching: couples conflict, repair, trust, marriage, dating, flirting, attachment patterns, emotional connection, sex, desire differences, eroticism, kink negotiation, affection, love languages, breakups, and long-term passion. Draw on Gottman, EFT and Hold Me Tight, attachment science, modern sex research, Perel, Nagoski, Kerner, Schnarch, Love and Stosny, and flexible love-language tools. Be concrete and low-hedge. Redirect only for imminent danger, abuse, coercive control, minors, non-consent, self-harm, stalking, or medical/legal/psychiatric decisions.
building-sf-integrations
IncludedSalesforce integration architecture and runtime plumbing with 120-point scoring. Use this skill to set up Named Credentials, External Credentials, External Services, REST/SOAP callout patterns, Platform Events, and Change Data Capture. TRIGGER when: user sets up Named Credentials, External Services, REST/SOAP callouts, Platform Events, CDC, or touches .namedCredential-meta.xml files. DO NOT TRIGGER when: Connected App/OAuth config (use configuring-connected-apps), Apex-only logic (use generating-apex), or data import/export (use handling-sf-data).
venue-templates
IncludedAccess comprehensive LaTeX templates, formatting requirements, and submission guidelines for major scientific publication venues (Nature, Science, PLOS, IEEE, ACM), academic conferences (NeurIPS, ICML, CVPR, CHI), research posters, and grant proposals (NSF, NIH, DOE, DARPA). This skill should be used when preparing manuscripts for journal submission, conference papers, research posters, or grant proposals and need venue-specific formatting requirements and templates.
let-fate-decide
IncludedDraws the 12 Houses of the Zodiac Tarot spread to inject entropy into planning when prompts are vague, ambiguous, or casually delegated. Interprets the spread to guide next steps. Use when the user says 'let fate decide', 'YOLO', 'whatever', 'idk', or other nonchalant phrases, makes Yu-Gi-Oh references, or when you are about to arbitrarily pick between multiple reasonable approaches. Prefer over ask-questions-if-underspecified when the user's tone is casual or playful rather than precision-seeking.
net-ops
IncludedCross-platform network troubleshooting (Windows, macOS, Linux) via local or remote shell. Use for: DNS broken, can't resolve hostnames, nslookup/dig works but apps fail, NRPT, WFP, scutil, /etc/resolver, systemd-resolved, /etc/resolv.conf, NetworkManager, VPN DNS leak residue (ProtonVPN/Mullvad/WireGuard/AnyConnect), AV/firewall blocking DNS or DoH, Tailscale DNS interaction, intermittent connectivity, remote diagnostics over SSH.