К основному содержанию
правило

asp-net — правило для Cursor: что делает и как установить

Правило задаёт рекомендации для ASP.NET Core: как организовать код, проектировать API и работать с асинхронными операциями. Пригодится при разработке и проверке бэкенда.

Установить в Cursor · Вручную: положить файлы Все способы и платформы ↓
.cursor/rules/asp-net.mdc
Открыть на GitHub

Что делает asp-net

Правило охватывает структуру проекта, API, производительность, внедрение зависимостей и безопасность. Оно советует группировать код по функциям, предпочитать Minimal APIs для новых эндпоинтов и использовать контроллеры, когда нужны расширенная привязка модели, атрибуты валидации или сложная маршрутизация.

Для операций с базой данных, сетью и файлами рекомендуется async/await; большие коллекции следует отдавать постранично, чтобы не получить OutOfMemoryException и медленные ответы. Внедрение зависимостей строится на встроенном контейнере ASP.NET Core, а для API описаны JWT Bearer и политики авторизации. Большие объекты от 85KB в часто выполняемом коде повышают нагрузку на сборщик мусора — правило предлагает использовать для крупных массивов ArrayPool<T>.

Файл Cursor — .cursor/rules/asp-net.mdc, маска **/* распространяет правило на все файлы. Рекомендации рассчитаны на ASP.NET Core 9+; для крупных массивов в примерах предлагается ArrayPool<T>.

Какие задачи решает

  • разложить код проекта по функциям, а не техническим слоям
  • выбрать между Minimal APIs и API Controllers
  • заменить блокирующие операции с базой данных асинхронными
  • разбить выдачу больших коллекций на страницы
  • настроить сроки жизни сервисов и политики авторизации

Примеры запросов агенту

  • Проверь структуру проекта ASP.NET Core и предложи группировку по функциям.
  • Посмотри, где в API блокируется ввод-вывод, и предложи вариант с async/await.
  • Проверь эндпоинты с большими коллекциями и предложи постраничную выдачу.

Как установить asp-net

Вручную: положить файлы

.cursor/rules/asp-net.mdc

Во frontmatter: description, globs, alwaysApply

По шагам, с командами для каждой платформы: Cursor rules: файлы .mdc, четыре режима и замена .cursorrules

Вопросы о asp-net

Как установить asp-net в Cursor?

Добавьте файл правила по пути .cursor/rules/asp-net.mdc.

Что делает правило asp-net?

Оно задаёт рекомендации по структуре ASP.NET Core-проекта, API, асинхронному вводу-выводу, внедрению зависимостей и авторизации.

Для какой версии ASP.NET Core предназначено правило?

Рекомендации рассчитаны на ASP.NET Core 9+.

Исходный текст

asp-net.mdc · CC0-1.0
---
description: This guide provides opinionated, actionable best practices for building high-performance, maintainable, and secure ASP.NET Core 9+ applications, focusing on modern C# patterns and common pitfalls.
globs: **/*
---
# asp-net Best Practices

This document outlines the definitive best practices for developing ASP.NET Core applications within our team. Adhere to these guidelines to ensure consistent, performant, and maintainable backend services.

## 1. Code Organization and Structure

Organize your projects by feature or bounded context, not by technical layer. This improves cohesion and reduces coupling.

### ✅ GOOD: Feature-First Organization

```csharp
// Project structure for a "Product" feature
src/
├── MyProject.Api/
│   ├── Program.cs
│   ├── Features/
│   │   ├── Products/
│   │   │   ├── ProductEndpoints.cs // Minimal API definitions
│   │   │   ├── ProductController.cs // API Controller (if used)
│   │   │   ├── GetProduct.cs      // Request/Response DTOs, Handler (e.g., MediatR)
│   │   │   ├── CreateProduct.cs
│   │   │   └── ProductService.cs  // Feature-specific business logic
│   ├── Common/                  // Shared infrastructure, middleware, extensions
│   │   ├── Filters/
│   │   ├── Middleware/
│   │   └── Extensions/
├── MyProject.Application/       // Application-specific services, interfaces, DTOs
│   ├── Interfaces/
│   ├── Services/
│   └── DTOs/
├── MyProject.Domain/            // Core domain entities, value objects, interfaces
├── MyProject.Infrastructure/    // Data access (EF Core), external services
│   ├── Data/
│   ├── Repositories/
│   └── ExternalServices/
└── MyProject.Tests/             // Unit and Integration tests
```

### ❌ BAD: Layer-First Organization

```csharp
// Avoid this structure for larger applications
src/
├── MyProject.Api/
│   ├── Controllers/ // All controllers here
│   ├── Services/    // All services here
│   ├── Repositories/ // All repositories here
│   └── DTOs/        // All DTOs here
```

## 2. API Design: Minimal APIs vs. API Controllers

**Always prefer Minimal APIs** for new endpoints due to their simplicity and directness. Use API Controllers only when you require advanced features like automatic model binding from multiple sources, built-in validation attributes, or complex attribute routing that Minimal APIs don't easily provide.

### ✅ GOOD: Minimal API for Simplicity

```csharp
// Program.cs or dedicated endpoint file
app.MapGet("/products/{id}", async (Guid id, IProductService service) =>
{
    var product = await service.GetProductByIdAsync(id);
    return product is not null ? Results.Ok(product) : Results.NotFound();
})
.WithName("GetProductById")
.Produces<ProductDto>(StatusCodes.Status200OK)
.Produces(StatusCodes.Status404NotFound);
```

### ✅ GOOD: API Controller for Complex Scenarios

```csharp
[ApiController]
[Route("api/[controller]")]
public class OrdersController : ControllerBase
{
    private readonly IOrderService _orderService;

    public OrdersController(IOrderService orderService) => _orderService = orderService;

    [HttpPost]
    [ProducesResponseType(StatusCodes.Status201Created)]
    [ProducesResponseType(StatusCodes.Status400BadRequest)]
    public async Task<IActionResult> CreateOrder([FromBody] CreateOrderRequest request)
    {
        if (!ModelState.IsValid) return BadRequest(ModelState);
        var order = await _orderService.CreateOrderAsync(request);
        return CreatedAtAction(nameof(GetOrderById), new { id = order.Id }, order);
    }
}
```

## 3. Performance Considerations

### 3.1. Avoid Blocking Calls

**Always use `async/await`** for I/O-bound operations (database, network, file system). Never block the thread pool.

### ❌ BAD: Blocking Calls

```csharp
// Synchronous I/O in an async context
public Product GetProduct(Guid id)
{
    // This blocks the calling thread while waiting for the DB
    return _dbContext.Products.Find(id);
}

// Blocking on an async task
var result = SomeAsyncTask().Result; // Blocks!
SomeAsyncTask().Wait();             // Blocks!
```

### ✅ GOOD: Asynchronous I/O

```csharp
public async Task<Product?> GetProductAsync(Guid id)
{
    return await _dbContext.Products.FindAsync(id);
}

// Correctly awaiting an async task
var result = await SomeAsyncTask();
```

### 3.2. Return Paged Collections

**Always paginate large collections** to prevent `OutOfMemoryException` and slow responses.

### ❌ BAD: Returning Large Collections Unpaged

```csharp
app.MapGet("/products", async (IProductService service) =>
{
    var allProducts = await service.GetAllProductsAsync(); // Potentially huge
    return Results.Ok(allProducts);
});
```

### ✅ GOOD: Paging Collections

```csharp
app.MapGet("/products", async (int page = 1, int pageSize = 20, IProductService service) =>
{
    var pagedProducts = await service.GetPagedProductsAsync(page, pageSize);
    return Results.Ok(pagedProducts);
});
```

### 3.3. Minimize Large Object Allocations

Cache frequently used large objects. Avoid creating large objects (>= 85KB) in hot code paths to reduce GC pressure. Use `ArrayPool<T>` for large arrays.

## 4. Dependency Injection (DI)

**Always use ASP.NET Core's built-in DI container.** Register services with the correct lifetime.

*   **Singleton**: For stateless services, configuration objects, or services that manage shared state.
*   **Scoped**: For services tied to a single HTTP request (e.g., `DbContext`, `IUnitOfWork`).
*   **Transient**: For lightweight services that should be new for every injection (rarely needed for typical backend services).

### ✅ GOOD: Correct Service Lifetimes

```csharp
public void ConfigureServices(IServiceCollection services)
{
    // Caching service can be shared across the app
    services.AddSingleton<ICacheService, RedisCacheService>();

    // Database context is scoped to the request
    services.AddDbContext<AppDbContext>(options => /* ... */, ServiceLifetime.Scoped);
    services.AddScoped<IProductRepository, ProductRepository>();

    // Business logic service, typically scoped
    services.AddScoped<IProductService, ProductService>();
}
```

## 5. Security Best Practices

### 5.1. Authentication and Authorization

**Always secure your API endpoints.** Use JWT Bearer tokens for API authentication. Define and enforce authorization policies.

### ✅ GOOD: Policy-Based Authorization

```csharp
// Program.cs
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddJwtBearer(options => { /* ... configure JWT ... */ });
builder.Services.AddAuthorization(options =>
{
    options.AddPolicy("CanManageProducts", policy =>
        policy.RequireRole("Admin", "ProductManager"));
});

// Minimal API endpoint
app.MapPost("/products", async (CreateProductRequest request, IProductService service) =>
{
    // ...
}).RequireAuthorization("CanManageProducts");

// Controller action
[Authorize(Policy = "CanManageProducts")]
[HttpPost]
public async Task<IActionResult> CreateProduct([FromBody] CreateProductRequest request)
{ /* ... */ }
```

### 5.2. Input Validation

**Always validate all incoming request data.** Use Data Annotations or FluentValidation for robust validation.

### ✅ GOOD: DTO Validation

```csharp
public record CreateProductRequest(
    [Required] [StringLength(100)] string Name,
    [Range(0.01, 10000.00)] decimal Price,
    [Url] string? ImageUrl
);

// In Minimal API or Controller, validation is often automatic with [ApiController]
// For Minimal APIs, you might explicitly check if not using a framework that handles it:
app.MapPost("/products", (CreateProductRequest request) =>
{
    var validationContext = new ValidationContext(request);
    var validationResults = new List<ValidationResult>();
    if (!Validator.TryValidateObject(request, validationContext, validationResults, true))
    {
        return Results.ValidationProblem(validationResults.ToDictionary(r => r.MemberNames.First(), r => new[] { r.ErrorMessage }));
    }
    // ... process valid request
});
```

## 6. Error Handling

**Implement global exception handling middleware.** Provide consistent, developer-friendly error responses without exposing sensitive details.

### ✅ GOOD: Global Exception Handler

```csharp
// Program.cs
app.UseExceptionHandler(appBuilder =>
{
    appBuilder.Run(async context =>
    {
        var exceptionHandlerPathFeature = context.Features.Get<IExceptionHandlerPathFeature>();
        var exception = exceptionHandlerPathFeature?.Error;

        var problemDetails = new ProblemDetails
        {
            Status = StatusCodes.Status500InternalServerError,
            Title = "An error occurred while processing your request.",
            Detail = "Please try again later. If the problem persists, contact support.",
            Instance = context.Request.Path
        };

        // Log the exception details for internal monitoring
        var logger = context.RequestServices.GetRequiredService<ILogger<Program>>();
        logger.LogError(exception, "Unhandled exception for request {Path}", context.Request.Path);

        context.Response.StatusCode = problemDetails.Status.Value;
        context.Response.ContentType = "application/problem+json";
        await context.Response.WriteAsJsonAsync(problemDetails);
    });
});
```

## 7. Structured Logging

**Always use structured logging** to enable easy querying and analysis of logs. Prefer `ILogger<T>` for context-specific logging.

### ✅ GOOD: Structured Logging

```csharp
public class ProductService : IProductService
{
    private readonly ILogger<ProductService> _logger;

    public ProductService(ILogger<ProductService> logger) => _logger = logger;

    public async Task<ProductDto> CreateProductAsync(CreateProductRequest request)
    {
        _logger.LogInformation("Creating product {ProductName} with price {ProductPrice}", request.Name, request.Price);
        // ...
        _logger.LogInformation("Product {ProductId} created successfully.", newProduct.Id);
        return newProductDto;
    }
}
```

### ❌ BAD: Unstructured Logging

```csharp
_logger.LogInformation("Creating product with name: " + request.Name + " and price: " + request.Price);
```

## 8. Testing Approaches

**Prioritize unit and integration tests.**

*   **Unit Tests**: Focus on isolated business logic (services, domain models). Mock all external dependencies.
*   **Integration Tests**: Verify API endpoints, middleware, and database interactions. Use `WebApplicationFactory<TStartup>` for in-memory testing.

### ✅ GOOD: Unit Test Example

```csharp
public class ProductServiceTests
{
    [Fact]
    public async Task CreateProductAsync_ValidRequest_ReturnsProductDto()
    {
        // Arrange
        var mockRepo = new Mock<IProductRepository>();
        mockRepo.Setup(r => r.AddAsync(It.IsAny<Product>())).ReturnsAsync(new Product { Id = Guid.NewGuid(), Name = "Test", Price = 10m });
        var service = new ProductService(mockRepo.Object, Mock.Of<ILogger<ProductService>>());
        var request = new CreateProductRequest("Test Product", 10.00m, null);

        // Act
        var result = await service.CreateProductAsync(request);

        // Assert
        Assert.NotNull(result);
        Assert.Equal("Test Product", result.Name);
        mockRepo.Verify(r => r.AddAsync(It.IsAny<Product>()), Times.Once);
    }
}
```

### ✅ GOOD: Integration Test Example

```csharp
public class ProductsApiTests : IClassFixture<CustomWebApplicationFactory<Program>>
{
    private readonly HttpClient _client;

    public ProductsApiTests(CustomWebApplicationFactory<Program> factory)
    {
        _client = factory.CreateClient();
    }

    [Fact]
    public async Task GetProducts_ReturnsSuccessAndCorrectContentType()
    {
        // Act
        var response = await _client.GetAsync("/products");

        // Assert
        response.EnsureSuccessStatusCode(); // Status Code 200-299
        Assert.Equal("application/json; charset=utf-8", response.Content.Headers.ContentType?.ToString());
    }
}
```

© sanjeed5 · CC0-1.0 · sanjeed5/awesome-cursor-rules-mdc

Похожие правила IDE

Все правила IDE по теме «Бэкенд и API» →
dotnet-core-expert https://github.com/Jeffallan Скилл для Claude Code, который ведёт агента по сборке бэкенда на .NET 8: минимальные API, чистая архитектура, EF Core, CQRS и JWT, от требований до dotnet test. CX Codex +1 4 700установок ASP.NET Core Debugger — MCP Server for AI Agents magna-nz MCP-сервер даёт ИИ-агентам интерактивную отладку .NET и ASP.NET Core через netcoredbg и DAP. Позволяет ставить точки останова, менять переменные в памяти и находить дедлоки. CX Codex +1 ★ 15звёзд репо aspnet-core официальный openai Помогает проектировать, писать и обновлять приложения на ASP.NET Core по официальным гайдам Microsoft. Пригодится при работе с Blazor, Minimal API и gRPC. CX Codex +1 3 900установок minimal-api codewithmukesh Скилл для ИИ-агентов, который ведёт по минимальным API .NET 10: группы эндпоинтов, TypedResults, фильтры и OpenAPI. CX Codex +1 2 800установок csharp-developer https://github.com/Jeffallan Настраивает правила разработки на .NET 8 и C# 12 для создания API, Blazor-приложений и работы с EF Core. Пригодится при проектировании сервисов с CQRS и Result pattern. CX Codex +1 4 800установок dotnet-webapi dotnet Скилл для ИИ-кодинга ведёт агента при добавлении эндпоинтов ASP.NET Core Web API: HTTP-статусы, метаданные OpenAPI, обработка ошибок. CX Codex +1 4 300установок

Из того же набора240

Весь набор →
autogen Руководство по архитектуре мультиагентных систем на AutoGen: модульные агенты в Python, дисковое кэширование вызовов LLM и тесты на pytest. ★ 3 580звёзд репо auth0 Правило для проектов с Auth0: направляет агент к Universal Login и Authorization Code Flow с PKCE. Помогает не закладывать небезопасные схемы входа. ★ 3 580звёзд репо asyncio Правило для Cursor задаёт, как писать асинхронный код на Python: единая точка входа, задачи без утечек, никаких блокировок цикла событий. ★ 3 580звёзд репо astro Набор инструкций для Cursor по архитектуре Astro: островная гидратация, нулевой JavaScript по умолчанию, строгий TypeScript и структура файлов. ★ 3 580звёзд репо apollo-graphql Правило для Cursor задаёт порядок работы с Apollo GraphQL: сначала схема на SDL, потом резолверы. Пригодится, если в проекте JS или JSX. ★ 3 580звёзд репо apollo-client Задаёт стандарты Apollo Client 3.x для React: синглтон клиента, хуки вместо императивных вызовов и работу с InMemoryCache. ★ 3 580звёзд репо anyio Правило задаёт рекомендации для асинхронного Python-кода на AnyIO: использовать структурированную конкурентность и выбирать backend явно. Оно применяется к файлам *.py. ★ 3 580звёзд репо ant-design Правило задаёт агенту стандарты работы с Ant Design v6.x: тему через токены, сетку, доступность компонентов. Пригодится, если проект на React и Ant Design. ★ 3 580звёзд репо

Спонсоры проекта

Компании, которые помогают держать аналитику открытой