EF Core 11 & ASP.NET Core 11 Interview Questions (.NET 11)

Ace your .NET 11 technical interview: 22 senior EF Core 11 & ASP.NET Core 11 questions, real C# code, and production breaking-change fixes.

If you're preparing for a .NET 11 technical interview right now, expect hiring managers to skip textbook trivia and go straight for real upgrade traps. Nobody at a Senior or Staff level cares if you can recite a release-notes bullet list. Interviewers want to know if you can catch the migration that silently drops fields in Cosmos DB, the missing NuGet package that breaks Managed Identity in staging, or the source-generator rule that leaves Minimal API endpoints unvalidated. That's what these EF Core 11 interview questions and ASP.NET Core 11 interview questions are built around.

EF Core 11 and ASP.NET Core 11 Interview Questions and Answers for Senior .NET 11 Developers
22 real-world EF Core 11 and ASP.NET Core 11 (.NET 11) technical interview questions, C# code fixes, and production upgrade traps.

Every question, code sample, and edge case below is verified against the official Microsoft Learn documentation for EF Core 11 and ASP.NET Core 11 (.NET 11 Release Candidate 2 shipped in October 2026 with a go-live license ahead of November 2026 General Availability). For each question, you get a production scenario, a crisp answer you can deliver out loud, runnable C# 15 / net11.0 code, and the practical gotcha that separates senior engineers from everyone else. Need a full feature walkthrough first? Read our companion pillar guide: What's New in EF Core 11 and ASP.NET Core 11 (.NET 11).

Quick Reference: All 22 .NET 11 Technical Interview Questions

Use this roadmap table to jump straight to the EF Core 11 or ASP.NET Core 11 topic you're reviewing before your interview loop:

# Interview Question & Production Scenario Stack Target Level
Q1 Why does SqlVector<T> return null in EF Core 11? EF Core 11 Mid / Senior
Q2 Why does SqlClient 7.0 Managed Identity fail in Azure staging? EF Core 11 Senior
Q3 Why does GREATEST fail on SQL Server after upgrading? EF Core 11 Mid / Senior
Q4 How does Cosmos DB unmapped JSON data loss happen on save? EF Core 11 Senior / Staff
Q5 What happens to synchronous Cosmos DB calls in EF Core 11? EF Core 11 Mid
Q6 Can you combine complex types and JSON columns with TPT or TPC? EF Core 11 Senior
Q7 How do you configure and index a property inside a complex type? EF Core 11 Mid / Senior
Q8 What triggers DbQueryConcurrencyException in split queries? EF Core 11 Senior
Q9 How do you build RRF hybrid search in SQL with FullJoin? EF Core 11 Senior / Staff
Q10 Why did your generated SQL snapshot baselines change? EF Core 11 Mid / Senior
Q11 Why did CI break on Migrate(), Design, and EFOptimizeContext? EF Core 11 Mid
Q12 How do you implement Minimal API async validation in .NET 11? ASP.NET Core 11 Senior
Q13 Why is Minimal API validation skipped for endpoints in a class library? ASP.NET Core 11 Senior / Staff
Q14 How does convention-based validation localization resolve keys? ASP.NET Core 11 Senior
Q15 What changed with OpenAPI 3.2 in .NET 11 and binary file schemas? ASP.NET Core 11 Mid / Senior
Q16 How are multiple ProducesResponseType attributes emitted per status? ASP.NET Core 11 Senior
Q17 What is the ConcurrencyLimiter removed replacement in .NET 11? ASP.NET Core 11 Senior
Q18 Why do distributed traces show duplicate HTTP tags and changed routes? ASP.NET Core 11 Senior
Q19 Is a Blazor SSR app still protected if you remove UseAntiforgery()? ASP.NET Core 11 Senior / Staff
Q20 Why do requests fail behind a reverse proxy after upgrading Kestrel? ASP.NET Core 11 Staff
Q21 How do endpoint filters customize Minimal API binding errors? ASP.NET Core 11 Senior
Q22 How does QuickGrid store paging and sorting in the URL? ASP.NET Core 11 Mid / Senior

Part 1: EF Core 11 Interview Questions & Breaking Changes (Q1–Q11)

Most EF Core 11 breaking changes questions in senior interviews test whether you understand how EF translates LINQ to SQL, manages network payload sizes, and serializes documents under the hood.

SDK & Runtime Requirement: EF Core 11 requires the .NET 11 SDK to build and the .NET 11 runtime to run. It does not run on .NET 10, earlier .NET releases, or .NET Framework.

Q1: Why Is My SqlVector Property Null in EF Core 11, and How Do You Fix It?

Level: Mid / Senior — Focus: SqlVector null EF Core 11, default SELECT column exclusion, and explicit projections.

Scenario: Your RAG service loads documents from SQL Server 2025 and re-ranks them in C# using their vector embeddings. Right after upgrading to EF Core 11, the re-ranker throws because every SqlVector<float> property comes back null, even though no query code changed.

Direct Answer: EF Core 11 excludes SqlVector<T> columns from default entity SELECT statements. Vector embeddings often hold 1,536 or more floats, and most queries only use them inside SQL for similarity filtering or sorting—skipping them ran roughly 9x faster locally and 22x faster against remote Azure SQL in Microsoft's benchmarks. Database-side vector search still works normally. Whenever you actually need the float values in C# memory, project the vector property explicitly with .Select(...).

using System.ComponentModel.DataAnnotations.Schema;
using Microsoft.Data.SqlTypes;
using Microsoft.EntityFrameworkCore;

public class Document
{
    public int Id { get; set; }
    public required string Title { get; set; }

    [Column(TypeName = "vector(1536)")]
    public SqlVector<float> Embedding { get; set; }
}

// EF Core 11: Embedding column is omitted from SELECT, so doc.Embedding is null!
var doc = await db.Documents.FirstAsync(d => d.Id == id);

// Similarity search still works: the vector stays inside SQL ORDER BY
var closest = await db.Documents
    .OrderBy(d => EF.Functions.VectorDistance("cosine", d.Embedding, queryVector))
    .Take(5)
    .ToListAsync();

// Need the vector floats in C#? Project the column explicitly:
var withVector = await db.Documents
    .Where(d => d.Id == id)
    .Select(d => new { d.Id, d.Title, d.Embedding })
    .SingleAsync();

Production Gotcha:
SqlVector<float> is usually declared without a nullable ? annotation, so the C# compiler gives you zero warnings. Grep your solution for every read of your embedding property (re-rankers, exports, vector sync jobs) and convert them to explicit projections. Calling .Include() won't work either, because Include is strictly for navigation properties.

Q2: Why Does SqlClient 7.0 Managed Identity Fail in Azure Staging When Local Tests Pass?

Level: Senior — Focus: SqlClient 7.0 Managed Identity, decoupled Entra ID dependencies, and cloud deployment checks.

Scenario: Your order API connects to Azure SQL using Authentication=Active Directory Managed Identity. Local integration tests pass against a Docker SQL Server container with SQL password auth. In Azure staging, startup fails immediately when opening the first database connection.

Direct Answer: EF Core 11 upgraded its SQL Server provider to Microsoft.Data.SqlClient 7.0. Version 7.0 stripped out the transitive dependencies on Azure.Core, Azure.Identity, and Microsoft.Identity.Client so apps using standard SQL auth don't carry heavy identity libraries. Any app using Entra ID (Azure AD) authentication must now install the Microsoft.Data.SqlClient.Extensions.Azure NuGet package explicitly.

<ItemGroup>
  <PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="11.0.0" />
  <!-- Required in EF Core 11 for any Entra ID / Managed Identity auth mode -->
  <PackageReference Include="Microsoft.Data.SqlClient.Extensions.Azure" Version="7.0.0" />
</ItemGroup>
// appsettings.Staging.json:
// "Orders": "Server=tcp:contoso-sql.database.windows.net;Database=Orders;Authentication=Active Directory Managed Identity;"

builder.Services.AddDbContext<OrdersDb>(options =>
    options.UseSqlServer(builder.Configuration.GetConnectionString("Orders")));

Production Gotcha:
Local Docker containers using SQL passwords will never catch this missing package. Always verify Managed Identity connections in a cloud staging slot before production cutover. This applies to ActiveDirectoryDefault, ActiveDirectoryInteractive, ActiveDirectoryManagedIdentity, and ActiveDirectoryServicePrincipal. Also note that ActiveDirectoryPassword is marked obsolete in SqlClient 7.0, so don't switch to it as a shortcut.

Q3: Why Does a LINQ Query Using Math.Max Suddenly Fail with "'GREATEST' Is Not a Recognized Built-In Function Name"?

Level: Mid / Senior — Focus: SQL Server default compatibility level 160 (SQL Server 2022) and level 170 (SQL Server 2025).

Scenario: A pricing endpoint calls Math.Max(o.Discount, o.MinimumDiscount) inside a LINQ query. It ran cleanly on EF Core 10, passes locally on EF Core 11, and crashes immediately in production.

Direct Answer: EF Core 11 raised the default SQL Server compatibility level from 150 (SQL Server 2019) to 160 (SQL Server 2022). At level 160, EF translates Math.Max and Math.Min into T-SQL GREATEST and LEAST instead of verbose CASE WHEN blocks. If your production database is still on compatibility level 150, SQL Server rejects the query. Pin UseCompatibilityLevel(150) in UseSqlServer until your DBAs upgrade the database compatibility level.

// Immediate stopgap for databases running below compatibility level 160:
builder.Services.AddDbContext<ShopDb>(options =>
    options.UseSqlServer(
        connectionString,
        sql => sql.UseCompatibilityLevel(150)));

// Or opt in to SQL Server 2025 features (such as JSON_CONTAINS) at level 170:
// sql => sql.UseCompatibilityLevel(170)
-- Always verify the database's actual compatibility level before deploying:
SELECT name, compatibility_level FROM sys.databases;

Production Gotcha:
The SQL Server engine version and a database's compatibility_level are independent! A database restored onto SQL Server 2022 from a SQL Server 2019 backup stays at compatibility level 150 until a DBA alters it explicitly.

Q4: How Can Upgrading to EF Core 11 Cause Silent Data Loss in Azure Cosmos DB?

Level: Senior / Staff (High-Impact Data Loss Risk) — Focus: Cosmos DB unmapped JSON data loss, System.Text.Json migration, and removal of __jObject.

Scenario: Two microservices share an Azure Cosmos DB container. The Billing service writes a taxRegion JSON field onto order documents. The Orders service uses EF Core and doesn't have taxRegion on its C# Order entity. After upgrading Orders to EF Core 11, Billing reports that taxRegion keeps getting wiped from production documents.

Direct Answer: This is the single highest-impact breaking change in EF Core 11. The Cosmos DB provider migrated from Newtonsoft.Json to System.Text.Json and removed the hidden __jObject shadow property. In EF Core 10, unmapped JSON properties were preserved inside __jObject and written back intact on SaveChangesAsync(). In EF Core 11, unmapped properties are ignored during deserialization and permanently lost when EF saves that document back. You must either map every shared field on your C# entity or use the Azure CosmosClient SDK directly for shared documents.

public class Order
{
    public required string Id { get; set; }
    public required string CustomerId { get; set; }
    public string Status { get; set; } = "Open";

    // Written by the Billing service — mapping it is now required to preserve it on save!
    public string? TaxRegion { get; set; }
}

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Order>(b =>
    {
        b.HasPartitionKey(o => o.CustomerId);
        b.Property(o => o.TaxRegion).ToJsonProperty("taxRegion");
    });
}

var order = await db.Orders.SingleAsync(o => o.Id == orderId);
order.Status = "Shipped";
await db.SaveChangesAsync(); // taxRegion survives only because it's mapped

Production Gotcha:
No exception or warning is logged—extra fields simply disappear the first time EF updates an entity. Audit every Cosmos container shared across microservices or schema versions before upgrading. If your service doesn't own the full document schema, use CosmosClient Patch operations instead of EF entity replacement.

Q5: What Happens to Synchronous Cosmos DB Calls Like ToList() and SaveChanges() in EF Core 11?

Level: Mid — Focus: Complete removal of synchronous Cosmos I/O and thread-pool starvation prevention.

Scenario: A legacy background worker and several xUnit test fixtures still call synchronous EF methods against Cosmos DB, relying on the warning suppression flag introduced back in EF Core 9.

Direct Answer: Every synchronous Cosmos DB I/O call now throws unconditionally with no opt-in switch. Because the underlying Azure Cosmos DB SDK is strictly asynchronous, sync-over-async blocking risked thread-pool starvation and deadlocks under load, so EF Core 11 removed the suppression mechanism completely.

// Always throws in EF Core 11 (zero opt-in switches exist):
var open = db.Orders.Where(o => o.Status == "Open").ToList();
db.SaveChanges();
db.Database.EnsureCreated();

// Required in EF Core 11:
var openAsync = await db.Orders.Where(o => o.Status == "Open").ToListAsync();
await db.SaveChangesAsync();
await db.Database.EnsureCreatedAsync();

Production Takeaway:
Production controller and Minimal API code is usually async already—test setup methods calling synchronous EnsureCreated(), SaveChanges(), or Count() are what typically break CI builds during the upgrade.

Q6: Can You Use Complex Types and JSON Columns on TPT or TPC Inheritance Hierarchies?

Level: Senior — Focus: Domain-Driven Design value objects, UseTptMappingStrategy(), UseTpcMappingStrategy(), and .ToJson().

Scenario: Your fleet domain uses Table-per-Type (TPT) inheritance on an abstract Vehicle entity. You want to model RegistrationInfo as a keyless value object stored as a single JSON column on the base table.

Direct Answer: Yes—EF Core 11 lifts the EF Core 10 limitation and supports both column-mapped complex types and .ToJson() complex types across TPT and TPC hierarchies. Your entity inheritance strategy (TPH, TPT, TPC) and your value-object storage layout (flat columns vs. JSON) are now independent architectural decisions.

using System.ComponentModel.DataAnnotations.Schema;

public abstract class Vehicle
{
    public int Id { get; set; }
    public required RegistrationInfo Registration { get; set; }
}

public class Car : Vehicle { public int Doors { get; set; } }
public class Truck : Vehicle { public decimal PayloadTons { get; set; } }

[ComplexType]
public class RegistrationInfo
{
    public required string Plate { get; set; }
    public DateOnly? FirstRegistered { get; set; }
}

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    // Option 1: flat columns on the base Vehicle table (Registration_Plate, etc.)
    // modelBuilder.Entity<Vehicle>().UseTptMappingStrategy();

    // Option 2: single JSON column on the base Vehicle table
    modelBuilder.Entity<Vehicle>()
        .UseTptMappingStrategy()
        .ComplexProperty(v => v.Registration, b => b.ToJson());
}

Production Takeaway:
Under TPC (Table-per-Concrete-Type), complex type columns are duplicated into each concrete table (Cars, Trucks) because no shared base table exists. Prefer [ComplexType] over OwnsOne for true value objects—complex types carry value semantics and no hidden primary key.

Q7: How Do You Configure and Index a Scalar Property Nested Inside a Complex Type?

Level: Mid / Senior — Focus: Chained member lambdas in Property(...), relational HasIndex(...), and JSON index paths.

Scenario: Lookups filtering by Customer.Address.PostalCode are triggering full table scans. Address is a complex type, and you want to enforce HasMaxLength(12) and create a database index on PostalCode.

Direct Answer: EF Core 11 lets you pass a chained member lambda straight into Property(c => c.Address.PostalCode) without stepping through ComplexProperty(...) first, and both keys and database indexes (HasIndex) can now target scalar properties nested inside non-collection complex types.

public class Customer
{
    public int Id { get; set; }
    public required Address Address { get; set; }
}

[ComplexType]
public class Address
{
    public required string Street { get; set; }
    public required string PostalCode { get; set; }
}

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    // EF Core 11: chain member access directly inside Property()
    modelBuilder.Entity<Customer>()
        .Property(c => c.Address.PostalCode)
        .HasMaxLength(12);

    // New in EF Core 11: create a database index on a complex type member
    modelBuilder.Entity<Customer>().HasIndex(c => c.Address.PostalCode);
}

Production Gotcha:
Relational providers in EF Core 11 can also index paths inside JSON-mapped complex collections, such as HasIndex("Items[].Sku"). Because native SQL Server CREATE JSON INDEX statements require SQL Server 2025+, always test migrations against your real target SQL Server engine version.

Q8: What Is DbQueryConcurrencyException in Split Queries, and How Should You Handle It?

Level: Senior — Focus: AsSplitQuery() data consistency, concurrent row modifications, and snapshot transactions.

Scenario: A reporting dashboard loads blogs and posts with AsSplitQuery() while background workers insert and delete posts. After upgrading to EF Core 11, logs show intermittent DbQueryConcurrencyException errors under peak write traffic.

Direct Answer: AsSplitQuery() runs separate SQL SELECT statements—one for parents and one per child collection—without wrapping them in a repeatable transaction by default. If another writer modifies or deletes parent rows between those SELECT calls, parent and child results fall out of sync. EF Core 10 silently returned empty child collections; EF Core 11 throws DbQueryConcurrencyException to prevent corrupt in-memory state. Fix it with a retry loop, a Snapshot/Serializable transaction, or AsSingleQuery().

using System.Data;

// Option 1: bounded retry loop for transient concurrent writes
const int maxRetries = 3;
List<Blog> blogs = [];

for (var attempt = 0; attempt < maxRetries; attempt++)
{
    try
    {
        blogs = await db.Blogs
            .Include(b => b.Posts)
            .AsSplitQuery()
            .ToListAsync();
        break;
    }
    catch (DbQueryConcurrencyException) when (attempt < maxRetries - 1)
    {
        // Concurrent write modified rows between split SELECTs; retry cleanly.
    }
}

// Option 2: read all split SELECTs against a single consistent DB snapshot
await using var tx = await db.Database.BeginTransactionAsync(IsolationLevel.Snapshot);
var consistentBlogs = await db.Blogs.Include(b => b.Posts).AsSplitQuery().ToListAsync();
await tx.CommitAsync();

Production Gotcha:
Don't confuse this with a thread-safety bug on DbContext (which throws InvalidOperationException). EF Core 11 is surfacing a real race condition your app previously ignored. Note that IsolationLevel.Snapshot requires ALLOW_SNAPSHOT_ISOLATION ON in SQL Server.

Q9: How Do You Build Hybrid Search (Full-Text + Vector RRF) in EF Core 11 Without Raw SQL?

Level: Senior / Staff — Focus: .NET 11 FullJoin LINQ operator, FULL OUTER JOIN translation, and Reciprocal Rank Fusion.

Scenario: You're implementing Reciprocal Rank Fusion (RRF) combining full-text keyword matches and vector similarity matches. A document must appear in the final top-10 list even if it matched only one of the two searches, with score fusion calculated inside SQL Server.

Direct Answer: Use the new .NET 11 FullJoin LINQ operator, which EF Core 11 translates directly to SQL FULL OUTER JOIN. An inner Join drops single-side hits, and LeftJoin drops vector-only semantic hits. FullJoin preserves every candidate from both sides (passing null for the unmatched side) so SQL computes the combined RRF score in one database round-trip.

public class RankedHit
{
    public int DocumentId { get; set; }
    public int Rank { get; set; }
}

IQueryable<RankedHit> textHits = /* top N from FreeTextTable(...) */;
IQueryable<RankedHit> vectorHits = /* top N from VectorSearch(...) */;

const int k = 60; // Standard RRF smoothing constant

var topResults = await textHits
    .FullJoin(
        vectorHits,
        t => t.DocumentId,
        v => v.DocumentId,
        (t, v) => new
        {
            DocumentId = t != null ? t.DocumentId : v!.DocumentId,
            RrfScore = (t != null ? 1.0 / (k + t.Rank) : 0.0)
                     + (v != null ? 1.0 / (k + v.Rank) : 0.0)
        })
    .OrderByDescending(x => x.RrfScore)
    .Take(10)
    .ToListAsync();

Production Takeaway:
Always guard both t and v against null inside the result selector, and apply Take(N) (e.g., top 50) to both subqueries before calling FullJoin so SQL Server only joins bounded candidate sets.

Q10: Your SQL Snapshot Tests Changed After Upgrading to EF Core 11. Is That a Regression?

Level: Mid / Senior — Focus: No-op SQL CAST stripping, split-query join pruning, and ORDER BY cleanup.

Scenario: Your integration tests assert against generated SQL baselines. After upgrading to EF Core 11, a CAST([c].[Email] AS nvarchar(max)) wrapper disappears from a WHERE predicate, and an AsSplitQuery() call stops joining a parent lookup table inside its secondary collection query.

Direct Answer: Those are intentional EF Core 11 SQL optimizations, not regressions. First, EF strips redundant no-op CAST operations (common on value-converted columns) during SQL post-processing so indexes aren't blocked. Second, split queries prune unneeded reference-navigation joins from child collection SQL and trim redundant keys from ORDER BY. Update your SQL baselines and inspect execution plans on hot paths.

var matches = await db.Customers
    .Where(c => c.Email.StartsWith("ana"))
    .ToListAsync();
-- EF Core 10 (when redundant cast was emitted on value-converted columns):
WHERE CAST([c].[Email] AS nvarchar(max)) LIKE N'ana%'

-- EF Core 11 (clean index-seekable predicate):
WHERE [c].[Email] LIKE N'ana%'

Production Takeaway:
In Microsoft's benchmarks, these query cleanups measured roughly 29% faster on a simple split-query workload and 22% faster on a single-query workload.

Q11: Why Did Your CI Pipeline Break on Migrate(), EF Tooling, and EFOptimizeContext?

Level: Mid — Focus: Zero-migration guardrails, transitive Design package removal, and MSBuild AOT stages.

Scenario: Bumping NuGet packages to EF Core 11 breaks three CI steps: a test host calling db.Database.Migrate() throws an exception, dotnet ef fails to locate design-time services, and your MSBuild <EFOptimizeContext> property stops generating compiled models.

Direct Answer: You hit three tooling breaking changes at once: (1) Migrate() now throws when an assembly contains zero migrations instead of succeeding silently; (2) EF tools packages dropped their transitive dependency on Microsoft.EntityFrameworkCore.Design, so you must reference it directly; and (3) EFOptimizeContext was replaced by EFScaffoldModelStage and EFPrecompileQueriesStage.

// If calling Migrate() with zero migrations is intentional in a test host, suppress the warning:
builder.Services.AddDbContext<AppDb>(options =>
    options.UseSqlServer(connectionString)
           .ConfigureWarnings(w => w.Ignore(RelationalEventId.MigrationsNotFound)));
<ItemGroup>
  <PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="11.0.0" PrivateAssets="all" />
</ItemGroup>

<PropertyGroup>
  <!-- Replaces the removed EFOptimizeContext MSBuild property -->
  <EFScaffoldModelStage>publish</EFScaffoldModelStage>
  <EFPrecompileQueriesStage>publish</EFPrecompileQueriesStage>
</PropertyGroup>

Production Gotcha:
Setting <PublishAot>true</PublishAot> enables both stages automatically at publish time, but Microsoft's documentation still marks full EF Core NativeAOT and precompiled queries as Experimental—don't pitch full EF NativeAOT as production-ready in a senior interview.

Part 2: ASP.NET Core 11 Interview Questions & Breaking Changes (Q12–Q22)

In ASP.NET Core 11 interview questions, hiring teams focus heavily on compile-time validation source generators, OpenAPI 3.2 contract stability, rate limiting, built-in OpenTelemetry spans, Blazor CSRF changes, and Kestrel security hardening.

Q12: How Do You Implement Minimal API Async Validation in .NET 11?

Level: Senior — Focus: Minimal API async validation, AsyncValidationAttribute, IAsyncValidatableObject, and CancellationToken propagation.

Scenario: Your Minimal API /signup endpoint needs to verify against SQL Server that a username isn't already taken, without blocking thread-pool threads or cluttering route handlers with manual checks.

Direct Answer: ASP.NET Core 11 adds native asynchronous validation through AsyncValidationAttribute and IAsyncValidatableObject inside Microsoft.Extensions.Validation. Register builder.Services.AddValidation(), subclass AsyncValidationAttribute, resolve scoped services via validationContext.GetRequiredService<T>() inside IsValidAsync, and throw from synchronous IsValid because Minimal APIs always execute the async pipeline.

using System.ComponentModel.DataAnnotations;

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddScoped<IUserDirectory, SqlUserDirectory>();
builder.Services.AddValidation();

var app = builder.Build();

app.MapPost("/signup", (SignupRequest request) =>
    TypedResults.Created($"/users/{request.Username}", request));

app.Run();

public sealed class SignupRequest
{
    [Required, UniqueUsername]
    public string? Username { get; set; }
}

public sealed class UniqueUsernameAttribute : AsyncValidationAttribute
{
    protected override ValidationResult? IsValid(object? value, ValidationContext context) =>
        throw new InvalidOperationException("Use the async validation pipeline.");

    protected override async Task<ValidationResult?> IsValidAsync(
        object? value,
        ValidationContext context,
        CancellationToken cancellationToken)
    {
        if (value is not string name || string.IsNullOrWhiteSpace(name))
            return ValidationResult.Success;

        var users = context.GetRequiredService<IUserDirectory>();

        return await users.ExistsAsync(name, cancellationToken)
            ? new ValidationResult("That username is already taken.", [nameof(SignupRequest.Username)])
            : ValidationResult.Success;
    }
}

Production Gotcha:
Async validation is a UX pre-check, not an atomic lock—two concurrent signups can both pass IsValidAsync milliseconds apart. Always enforce a database UNIQUE constraint as your real concurrency guarantee. Also note that [ValidatableType] and [SkipValidation] graduated to stable in .NET 11, so remove old ASP0029 warning suppressions.

Q13: Why Does a Minimal API Return 200 OK for Invalid Payloads When Endpoints Live in a Class Library?

Level: Senior / Staff — Focus: Cross-assembly Roslyn validation source-generator boundaries.

Scenario: Your host API project calls builder.Services.AddValidation() in Program.cs, while route groups and DTOs live in a referenced class library (Contoso.Orders.Endpoints.dll). Sending Quantity = 500 to an endpoint decorated with [Range(1, 100)] returns 200 OK instead of 400 Bad Request.

Direct Answer: Minimal API validation relies on a compile-time Roslyn source generator that only inspects the assembly where AddValidation() is invoked. Endpoints and DTOs compiled inside a separate class library are silently skipped unless the generator runs inside that library too. Expose an extension method inside the class library that calls services.AddValidation(), and invoke it from the host's Program.cs.

// Inside Contoso.Orders.Endpoints (referenced class library):
using Microsoft.Extensions.DependencyInjection;

namespace Contoso.Orders.Endpoints;

public static class OrdersServiceCollectionExtensions
{
    public static IServiceCollection AddOrdersValidation(this IServiceCollection services) =>
        services.AddValidation(); // Triggers the validation source generator for THIS assembly
}

public sealed class CreateOrderRequest
{
    [Required, Range(1, 100)]
    public int? Quantity { get; set; }
}
// Inside the host API Program.cs:
builder.Services.AddValidation();       // Discovers validatable types in the host project
builder.Services.AddOrdersValidation(); // Discovers validatable types in Contoso.Orders.Endpoints

Production Gotcha:
Nothing throws at compile time or startup when you forget this—invalid payloads just sail straight into your handlers! Always add at least one negative integration test per endpoint assembly asserting a 400 Bad Request. If the class library uses Microsoft.NET.Sdk instead of the Web SDK, add a package reference to Microsoft.Extensions.Validation.

Q14: How Do You Localize [Required] Messages Across 40 DTOs Without Editing Every Attribute?

Level: Senior — Focus: Convention-based validation localization key precedence and LocalizerProvider.

Scenario: You have 40 Minimal API request DTOs using [Required] without an explicit ErrorMessage property, and product requirements call for French and Arabic translations across the entire API.

Direct Answer: Registering AddLocalization() alongside AddValidation() enables automatic convention-based lookup. When an attribute omits ErrorMessage, ASP.NET Core 11 probes three resource keys from most specific to most general: {DeclaringType}_{MemberName}_{AttributeType}_Error, then {DeclaringType}_{AttributeType}_Error, and finally {AttributeType}_Error. Adding a single RequiredAttribute_Error entry localizes all 40 DTOs automatically.

builder.Services.AddLocalization();
builder.Services.AddValidation(options =>
{
    // Point all validation lookups to one shared resource class (ValidationMessages.fr.resx, etc.)
    options.LocalizerProvider = (_, factory) => factory.Create(typeof(ValidationMessages));
});

public sealed class SignupRequest
{
    [Required] // Probes SignupRequest_Email_RequiredAttribute_Error -> SignupRequest_RequiredAttribute_Error -> RequiredAttribute_Error
    public string? Email { get; set; }
}

Production Takeaway:
Notice that the convention uses the full class name RequiredAttribute_Error, not Required_Error. For custom validation attributes with constructor parameters (such as a factor or max file size), override ValidationAttribute.FormatMessage(string format, string name).

Q15: What Changed with OpenAPI 3.2 in .NET 11, and Why Did Your Client Generator Break?

Level: Mid / Senior — Focus: OpenAPI 3.2 .NET 11 default spec version, Microsoft.OpenApi 3.x, and binary file schemas.

Scenario: After retargeting an invoicing API to net11.0, an NSwag/Kiota codegen step in CI fails because the emitted JSON document now starts with "openapi": "3.2.0". You also want a PDF download route documented cleanly as a binary stream.

Direct Answer: ASP.NET Core 11 switched the default OpenApiOptions.OpenApiVersion to OpenApiSpecVersion.OpenApi3_2 and upgraded under the hood to Microsoft.OpenApi 3.x. Pin OpenApiSpecVersion.OpenApi3_1 (or OpenApi3_0) until downstream client generators support 3.2, and declare .Produces<FileContentResult>(contentType: "application/pdf") so binary endpoints emit type: string, format: binary.

using Microsoft.AspNetCore.Mvc;
using Microsoft.OpenApi;

builder.Services.AddOpenApi(options =>
{
    // .NET 11 defaults to OpenApi3_2; pin 3.1 when legacy client generators lag behind
    options.OpenApiVersion = OpenApiSpecVersion.OpenApi3_1;
});

var app = builder.Build();
app.MapOpenApi();

app.MapGet("/invoices/{id:int}/pdf", (int id) =>
        TypedResults.File(InvoiceRenderer.Render(id), "application/pdf"))
    .Produces<FileContentResult>(contentType: "application/pdf");

Production Gotcha:
Don't use .Produces<byte[]>() for raw file streams—OpenAPI models byte[] as a Base64-encoded string rather than raw binary bytes. Also check custom schema/document transformers: Microsoft.OpenApi 3.x replaces OpenApiAny types with JsonNode and moves concrete model classes behind interfaces like IOpenApiSchema.

Q16: What Happens When an Endpoint Declares Multiple ProducesResponseType Attributes for Status 200?

Level: Senior — Focus: Preservation of multiple response shapes per HTTP status code and anyOf schemas.

Scenario: A controller action carries both [ProducesResponseType<Order>(200)] and [ProducesResponseType<OrderSummary>(200)], while a Minimal API chains .Produces<Item>(200, "application/json") and .Produces<string>(200, "text/plain").

Direct Answer: In .NET 10, only one entry survived per status code ("last-in wins") and earlier declarations were silently dropped. In .NET 11, all response metadata entries are preserved: distinct media types are emitted side by side under 200, and multiple C# types sharing the same media type merge into an OpenAPI anyOf composite schema.

[HttpGet("{id:int}")]
[ProducesResponseType<Order>(StatusCodes.Status200OK)]
[ProducesResponseType<OrderSummary>(StatusCodes.Status200OK)] // Merged into anyOf in .NET 11!
public IActionResult GetOrder(int id) => Ok(_orders.Find(id));

app.MapGet("/items/{id:int}", (int id) => ItemStore.Find(id))
    .Produces<Item>(200, "application/json")
    .Produces<string>(200, "text/plain"); // Both content types preserved under 200

Production Takeaway:
Legacy controllers often have accidental duplicate [ProducesResponseType] attributes nobody noticed because .NET 10 overwrote them. Audit generated specs so typed client SDKs don't suddenly switch return types to wrapper union models.

Q17: Your Build Fails Because UseConcurrencyLimiter Was Removed. What Is the Exact Replacement?

Level: Senior — Focus: ConcurrencyLimiter removed replacement, GlobalLimiter vs. named rate-limit policies.

Scenario: A reporting service used AddQueuePolicy and app.UseConcurrencyLimiter() to cap concurrent in-flight requests across the entire pipeline. After retargeting to net11.0, the project fails to compile.

Direct Answer: The obsolete Microsoft.AspNetCore.ConcurrencyLimiter middleware (UseConcurrencyLimiter, AddQueuePolicy, AddStackPolicy) was completely removed in ASP.NET Core 11 with no 11.x NuGet package. Migrate to the built-in Microsoft.AspNetCore.RateLimiting middleware using o.GlobalLimiter with RateLimitPartition.GetConcurrencyLimiter(...) to preserve pipeline-wide throttling.

using System.Threading.RateLimiting;

builder.Services.AddRateLimiter(options =>
{
    options.RejectionStatusCode = StatusCodes.Status503ServiceUnavailable;

    // Replicates pipeline-wide throttling across all endpoints automatically:
    options.GlobalLimiter = PartitionedRateLimiter.Create<HttpContext, string>(_ =>
        RateLimitPartition.GetConcurrencyLimiter("global", _ => new ConcurrencyLimiterOptions
        {
            PermitLimit = 2,
            QueueLimit = 25,
            QueueProcessingOrder = QueueProcessingOrder.OldestFirst
        }));
});

var app = builder.Build();
app.UseRateLimiter();

Production Gotcha:
The #1 migration bug in code reviews is calling options.AddConcurrencyLimiter("heavy", ...) and app.UseRateLimiter() without attaching .RequireRateLimiting("heavy") to any endpoints—leaving the entire API unthrottled! Use GlobalLimiter when you want every request capped by default.

Q18: Why Do Distributed Traces Show Duplicate HTTP Tags and Broken Route Alerts After Upgrading?

Level: Senior — Focus: SuppressActivityOpenTelemetryData default flip and resolved conventional http.route tags.

Scenario: After deploying an ASP.NET Core 11 service, spans export duplicate http.request.method tags, and a Grafana alert matching the conventional MVC route string {controller}/{action}/{id?} stops firing.

Direct Answer: In .NET 11, Microsoft.AspNetCore.Hosting.SuppressActivityOpenTelemetryData flipped its default from true to false, so ASP.NET Core natively emits OpenTelemetry HTTP semantic-convention tags on request spans. Running an older version of OpenTelemetry.Instrumentation.AspNetCore attaches a second copy of those tags, and conventional routes now populate resolved controller/action names (such as Store/Checkout/{id?}) inside http.route.

// Option 1 (recommended): upgrade OpenTelemetry.Instrumentation.AspNetCore so it skips built-in tags,
// or subscribe directly to the built-in ASP.NET Core ActivitySource:
builder.Services.AddOpenTelemetry()
    .WithTracing(tracing => tracing
        .AddSource("Microsoft.AspNetCore")
        .AddOtlpExporter());

// Option 2 (temporary): suppress native HTTP tags early in Program.cs startup:
AppContext.SetSwitch("Microsoft.AspNetCore.Hosting.SuppressActivityOpenTelemetryData", true);

Production Gotcha:
Setting the AppContext switch only suppresses the built-in span tags—it does not revert the resolved http.route format, so you must update Grafana/Datadog queries grouping on legacy route templates. Also watch Prometheus/OTLP metric cardinality: http.server.request.duration now adds an error.type dimension on 5xx responses.

Q19: A Developer Removed app.UseAntiforgery() During Upgrade. Is Your Blazor SSR App Still Protected?

Level: Senior / Staff — Focus: Automatic Fetch Metadata CSRF (Sec-Fetch-Site / Origin) vs. hidden antiforgery form tokens.

Scenario: Seeing that fresh .NET 11 templates omit app.UseAntiforgery(), a teammate deletes it from an existing Blazor Web App. Security scanners immediately flag missing __RequestVerificationToken inputs for legacy browsers, while a partner portal submitting cross-origin POST forms starts getting 400 Bad Request.

Direct Answer: Partly. Apps created with WebApplication.CreateBuilder in .NET 11 automatically register header-based CSRF protection validating Sec-Fetch-Site and Origin headers across Blazor SSR, form-binding Minimal APIs, and MVC. However, Blazor SSR now defers antiforgery checks to middleware and stops generating hidden form tokens whenever app.UseAntiforgery() is absent. Restore app.UseAntiforgery() when you need token generation, and whitelist legitimate cross-origin form senders via CORS.

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorComponents();

var app = builder.Build();

// Keep this on existing Blazor apps that require hidden __RequestVerificationToken fields!
app.UseAntiforgery();

app.MapRazorComponents<App>();
app.Run();

Production Takeaway:
Never bundle removing app.UseAntiforgery() into a target-framework bump PR. Upgrade with token middleware intact first, then evaluate header-only CSRF protection in a dedicated security review.

Q20: Why Are Requests Failing Behind a Reverse Proxy After Upgrading Kestrel to .NET 11?

Level: Staff — Focus: Kestrel RFC 9112 / 9113 / 9114 HTTP protocol hardening and request-smuggling defenses.

Scenario: Right after rolling out .NET 11 behind an older edge proxy, HTTP/2 streams begin resetting when the proxy forwards a Keep-Alive header, and an internal HTTP/1.1 client sending both Content-Length and Transfer-Encoding: chunked sees its TCP connections closed after every single response.

Direct Answer: Kestrel tightened HTTP protocol compliance in .NET 11 to eliminate request-smuggling vectors. On HTTP/2 and HTTP/3, any connection-specific header (Connection, Proxy-Connection, Keep-Alive, Transfer-Encoding, Upgrade, or non-trailers TE) causes Kestrel to reject the request immediately. On HTTP/1.1, requests carrying both Content-Length and Transfer-Encoding still execute as chunked, but Kestrel now closes the connection immediately after sending the response.

using System.Net.Sockets;
using System.Text;

// Integration probe verifying HTTP/1.1 dual-header connection closure on .NET 11:
using var client = new TcpClient("localhost", 5000);
await using var stream = client.GetStream();

const string rawRequest =
    "POST /orders HTTP/1.1\r\n" +
    "Host: localhost\r\n" +
    "Content-Length: 5\r\n" +
    "Transfer-Encoding: chunked\r\n\r\n" +
    "0\r\n\r\n";

await stream.WriteAsync(Encoding.ASCII.GetBytes(rawRequest));

var buffer = new byte[4096];
int bytesRead = await stream.ReadAsync(buffer);
Console.WriteLine(Encoding.ASCII.GetString(buffer, 0, bytesRead));
// Kestrel processes the chunked request and closes the socket immediately afterward.

Production Gotcha:
You can't (and shouldn't) "configure Kestrel to ignore invalid headers" in C#. The fix belongs at your reverse proxy (NGINX, HAProxy, Envoy, legacy API gateways) by stripping hop-by-hop headers before forwarding upstream over HTTP/2.

Q21: How Do You Customize Minimal API Parameter-Binding Errors Using Endpoint Filters?

Level: Senior — Focus: Binding-failure filter invocation and RouteHandlerOptions.ThrowOnBadRequest.

Scenario: You attach an endpoint filter so requests like /orders?page=abc return your team's custom ProblemDetails envelope on 400 Bad Request. It works in Production, yet local Development throws an unhandled BadHttpRequestException before the filter ever runs.

Direct Answer: When ThrowOnBadRequest is false (the Production default), Minimal API parameter-binding failures set Response.StatusCode = 400, run the endpoint filter pipeline, and skip the route handler so a filter can return a custom body. In Development, ThrowOnBadRequest defaults to true, throwing BadHttpRequestException early. Set RouteHandlerOptions.ThrowOnBadRequest = false to test the exact same filter behavior locally.

builder.Services.Configure<RouteHandlerOptions>(o => o.ThrowOnBadRequest = false);

var app = builder.Build();

app.MapGet("/orders", (int page) => OrderStore.GetPage(page))
    .AddEndpointFilter(async (context, next) =>
    {
        if (context.HttpContext.Response.StatusCode >= StatusCodes.Status400BadRequest)
        {
            return TypedResults.Problem(
                title: "Invalid query or route parameter.",
                statusCode: context.HttpContext.Response.StatusCode);
        }

        return await next(context);
    });

Production Gotcha:
Check >= StatusCodes.Status400BadRequest rather than == 400, never inspect context.Arguments before checking the status code (arguments may be uninitialized), and remember that malformed JSON body-reading errors still short-circuit before endpoint filters run.

Q22: How Does Blazor QuickGrid Persist Paging and Sorting in the URL, and What Breaks Multi-Grid Pages?

Level: Mid / Senior — Focus: Query-string state in static SSR, QueryParameterNameOptions, and OnRowClick.

Scenario: A static SSR Blazor page displays two QuickGrid tables—Orders and Returns. Clicking page 2 on Returns also jumps Orders to page 2, custom CSS targeting button.col-title stopped applying, and renaming a column's Title broke customers' bookmarked sort URLs.

Direct Answer: In .NET 11, QuickGrid persists pagination and sorting in URL query parameters (such as ?page=2&sort=Total&direction=asc) and renders <a> links instead of <button> elements so static SSR, bookmarks, and browser Back/Forward buttons work natively. Multiple grids on one page collide on query parameter names unless scoped via QueryParameterNameOptions, and sort URLs key off the column Title.

<QuickGrid Items="@orders"
           Pagination="@ordersPaging"
           OnRowClick="@((Order o) => OpenOrder(o.Id))">
    <PropertyColumn Property="@(o => o.Number)" Sortable="true" />
    <PropertyColumn Property="@(o => o.Total)" Title="Total" Sortable="true" />
</QuickGrid>
<Paginator State="@ordersPaging" />

@* Scope the second grid's query parameters so paging/sorting won't collide: *@
<QuickGrid Items="@returns"
           Pagination="@returnsPaging"
           QueryParameterNameOptions="@(new QueryParameterNameOptions("returns_"))">
    <PropertyColumn Property="@(r => r.Number)" Sortable="true" />
</QuickGrid>
<Paginator State="@returnsPaging" />

Production Takeaway:
Update custom grid stylesheets from button selectors to a selectors, treat column Title values on public grids as part of your URL contract, or set Microsoft.AspNetCore.Components.QuickGrid.EnableUrlBasedQuickGridNavigationAndSorting to false if you must revert to legacy markup.

Rapid-Fire Round: Quick .NET 11 Technical Interview Answers

Hiring managers often wrap up a technical screen with quick-fire verification questions. Keep these one-liners sharp:

Rapid-Fire Question Concise Senior Answer
Default SQL Server compatibility level in EF Core 11? 160 (SQL Server 2022), raised from 150 in EF Core 10.
Which compatibility level unlocks JSON_CONTAINS? 170 (SQL Server 2025), opt-in via UseCompatibilityLevel(170).
Package required for Entra ID auth with SqlClient 7.0? Microsoft.Data.SqlClient.Extensions.Azure.
Can EF Core 11 run on .NET 10 LTS? No—EF Core 11 requires both the .NET 11 SDK and .NET 11 runtime.
Default OpenAPI spec version in ASP.NET Core 11? OpenAPI 3.2 (OpenApiSpecVersion.OpenApi3_2).
Are [ValidatableType] and [SkipValidation] experimental? No—both graduated to stable APIs in .NET 11 (ASP0029 removed).
What replaced UseConcurrencyLimiter()? AddRateLimiter() + UseRateLimiter() with a GlobalLimiter concurrency partition.
Default HTTP status code when RateLimiter rejects a request? 503 Service Unavailable (commonly customized to 429 Too Many Requests).
Does EF Core Cosmos DB still use Newtonsoft.Json? No—it switched to System.Text.Json and removed the __jObject shadow property.
Is full EF Core NativeAOT ready for production? Still marked Experimental in official Microsoft Learn docs.

.NET 11 Production Upgrade Plan (How Senior Candidates Structure Rollouts)

When an interviewer asks, "How would you roll out a .NET 10 to .NET 11 upgrade across production microservices?", walk through this ordered sequence:

  1. Audit shared Cosmos DB containers first: Identify any document fields written by external services that aren't mapped on your EF entities—this is the one upgrade change that silently destroys production data on save.
  2. Add Entra ID SQL authentication packages: Install Microsoft.Data.SqlClient.Extensions.Azure wherever connection strings use Managed Identity or Azure AD, and verify connectivity in a cloud staging slot.
  3. Verify SQL Server compatibility levels: Query sys.databases across staging and production; pin UseCompatibilityLevel(150) on databases not yet upgraded to SQL Server 2022 compatibility.
  4. Project SqlVector<T> properties explicitly: Search for in-memory C# reads of vector columns and convert them to explicit .Select(...) projections so re-rankers don't hit null.
  5. Convert remaining Cosmos sync calls to async: Refactor legacy EnsureCreated(), ToList(), and SaveChanges() calls in test fixtures and background workers.
  6. Harden busy split queries: Add bounded retries or snapshot transactions around AsSplitQuery() queries that run alongside heavy concurrent writes.
  7. Wire up cross-assembly Minimal API validation: Call services.AddValidation() inside every class library hosting Minimal API endpoints and add negative 400 integration tests.
  8. Validate your OpenAPI 3.2 pipeline: Test Swagger UI, Scalar, gateways, and NSwag/Kiota client generators against 3.2—or pin OpenApiSpecVersion.OpenApi3_1 while tooling catches up.
  9. Migrate ConcurrencyLimiter to GlobalLimiter: Replace removed middleware calls with AddRateLimiter() and load-test your rejection status codes.
  10. Align OpenTelemetry & dashboards: Upgrade OpenTelemetry.Instrumentation.AspNetCore to prevent duplicate HTTP tags and update Grafana/Datadog queries for resolved http.route values.
  11. Preserve UseAntiforgery() & check edge proxies: Keep antiforgery token middleware intact during the framework upgrade, and verify reverse proxies don't forward hop-by-hop headers to Kestrel over HTTP/2.

Hiring Manager Takeaway: Compiler errors like the deleted ConcurrencyLimiter package take ten minutes to fix. Candidates who earn Staff and Senior offers are the ones who proactively test for silent runtime shifts—Cosmos DB dropping unmapped JSON, SqlVector<T> returning null, and cross-assembly Minimal API endpoints skipping validation.

Frequently Asked Questions: EF Core 11 & ASP.NET Core 11 Interviews

Quick answers to the top questions developers ask before a .NET 11 interview loop:

What are the most common EF Core 11 interview questions?

Interviewers focus heavily on five EF Core 11 topics: SqlVector<T> properties returning null unless projected with .Select(), Microsoft.Data.SqlClient 7.0 requiring Microsoft.Data.SqlClient.Extensions.Azure for Managed Identity, the default SQL Server compatibility level bump to 160, Cosmos DB unmapped JSON data loss after removing __jObject, and complex types with JSON columns on TPT/TPC hierarchies.

What are the most important ASP.NET Core 11 interview questions for senior developers?

Senior ASP.NET Core 11 interviews test Minimal API async validation (AsyncValidationAttribute) and the cross-assembly AddValidation() source-generator trap, OpenAPI 3.2 default document generation, replacing the removed ConcurrencyLimiter middleware with GlobalLimiter, built-in OpenTelemetry HTTP span tags, Blazor SSR antiforgery vs. automatic Sec-Fetch-Site CSRF protection, and Kestrel HTTP protocol hardening.

Why is my SqlVector property null in EF Core 11?

EF Core 11 omits SqlVector<T> columns from default entity SELECT queries so routine reads do not transfer large float arrays over the network. Vector distance filtering and ordering in SQL still work normally, and you can read the vector values in C# by projecting the column explicitly via .Select().

Why did Managed Identity stop working after upgrading to EF Core 11?

EF Core 11 upgrades to Microsoft.Data.SqlClient 7.0, which decoupled Azure and Entra ID authentication libraries from the core driver. Install the Microsoft.Data.SqlClient.Extensions.Azure NuGet package in any project using Managed Identity or Entra ID connection strings.

What replaced the ConcurrencyLimiter middleware in ASP.NET Core 11?

The legacy Microsoft.AspNetCore.ConcurrencyLimiter package was removed in ASP.NET Core 11. Replace it with the built-in rate-limiting middleware by configuring RateLimitPartition.GetConcurrencyLimiter(...) inside options.GlobalLimiter in AddRateLimiter(), followed by app.UseRateLimiter().

Test Yourself Under Real Exam Conditions

Reading interview explanations is step one—checking whether you can spot subtle runtime traps without hints is what locks the details into memory. Take our interactive 20-question assessment next:

Source:
Microsoft Learn — What's New in EF Core 11 | EF Core 11 Breaking Changes | SQL Server Vector Search in EF Core | What's New in ASP.NET Core 11 | ASP.NET Core 11 Breaking Changes | Validation in ASP.NET Core

About the author

MOHAMMED KADI
Software Engineer. Passionate about IT certifications, automation, and building scalable tech solutions.

Post a Comment

Welcome to Iwalen.com! If you have any questions or need assistance with any of our resources, feel free to ask. Please keep the discussion professional and avoid posting external links. All comments are moderated to ensure a high-quality community experience.