Nota:
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
En esta guía de inicio rápido, compilas una API mínima de ASP.NET Core con Microsoft.Data.SqlClient 7.1.1.
Empiezas con una carpeta vacía, el SDK .NET y una base de datos de SQL Server o Azure SQL a la que puedes acceder desde tu ordenador. Terminas con una API web que añade un mensaje a una tabla y lo lee por ID.
Durante el proceso:
- Lee su cadena de conexión desde la configuración de ASP.NET Core. Para el desarrollo local, el valor viene de los secretos de usuario, así que se mantiene fuera de la carpeta del proyecto.
- Registra una clase de datos con inyección de dependencias.
- Abre y cierra una conexión para cada solicitud, lo que permite que el conjunto de conexiones por defecto reutilice las conexiones físicas.
- Pasa el
CancellationTokende la solicitud a cada llamada a la base de datos.
La app utiliza la misma dbo.SqlClientQuickstart tabla que Quickstart: Conecta y consulta con Microsoft.Data.SqlClient. Puedes hacer primero cualquiera de los dos inicios rápidos.
Requisitos previos
- El SDK de .NET 10 o un SDK de .NET posterior compatible. El SDK funciona en Windows, Linux y macOS.
- Una base de datos a la que puedas conectarte. Para crear uno, consulta los requisitos previos en el inicio rápido de consola.
-
curlo PowerShell para enviar solicitudes a la API.
El ASP.NET Core actual funciona en .NET, no en .NET Framework. Para usar el controlador desde .NET Framework, véase proyectos de .NET Framework.
La identidad de la base de datos necesita permiso para conectarse y crear, insertar y seleccionar de una tabla.
Creación del proyecto
En una carpeta vacía, ejecuta estos comandos:
dotnet new web --framework net10.0 --name SqlClientWebQuickstart
cd SqlClientWebQuickstart
dotnet add package Microsoft.Data.SqlClient --version 7.1.1
dotnet add package Microsoft.Data.SqlClient.Extensions.Azure --version 7.1.1
dotnet user-secrets init
dotnet user-secrets init añade UserSecretsId al archivo del proyecto. ASP.NET Core carga secretos de usuario solo cuando la aplicación se ejecuta en el Development entorno, que es el valor predeterminado para dotnet run.
El paquete de extensión proporciona los modos de autenticación Microsoft Entra del controlador. Si tu app solo usa autenticación SQL, puedes omitir Microsoft.Data.SqlClient.Extensions.Azure. Cuando uses ambos paquetes, mantén sus versiones iguales.
Configurar la conexión
Guarda la cadena de conexión como ConnectionStrings:Quickstart en secretos de usuario. Los secretos de usuario se almacenan en tu perfil de usuario, no en la carpeta del proyecto, así que no se confirman en el control de versiones. No pongas contraseña ni cadena de conexión de producción en appsettings.json.
Elige uno de estos puntos de inicio y cambia los marcadores de posición. Los dotnet user-secrets set comandos usan comillas simples para PowerShell y Bash. En el Símbolo del sistema usa comillas dobles, porque el Símbolo del sistema almacena comillas simples como parte de la clave y el valor.
Azure SQL con Microsoft Entra ID
Inicia sesión con una identidad de Microsoft Entra que tenga acceso a la base de datos. Para el desarrollo local, utiliza una herramienta de desarrollo como la CLI de Azure:
az login
Luego guarda la cadena de conexión. Copia los nombres exactos del servidor y de la base de datos de Azure SQL. La misma cadena de conexión funciona para la base de datos SQL en Microsoft Fabric cuando usas los nombres del servidor y la base de datos del elemento de la base de datos SQL, como se describe en el inicio rápido de la consola.
dotnet user-secrets set 'ConnectionStrings:Quickstart' 'Server=tcp:<server>,1433;Database=<database>;Authentication=Active Directory Default;Encrypt=Strict;Connect Timeout=30'
Esta cadena de conexión no contiene ningún secreto.
Active Directory Default usa tu inicio de sesión de desarrollador localmente. Cuando despliegues en Azure App Service o Azure Container Apps, concede a la identidad gestionada de la app acceso a la base de datos, cambia el valor a Authentication=Active Directory Managed Identity, y configúralo en la configuración del host como ConnectionStrings__Quickstart. Para otras opciones, consulta la autenticación Microsoft Entra con Microsoft.Data.SqlClient.
SQL Server local con autenticación SQL
Almacena la cadena de conexión de una instancia de desarrollo local que no tenga un certificado de confianza. Usa comillas simples para evitar que PowerShell y Bash interpreten un carácter $ en la contraseña.
dotnet user-secrets set 'ConnectionStrings:Quickstart' 'Server=tcp:<server>,1433;Database=<database>;User ID=<user-id>;Password=<password>;Encrypt=true;TrustServerCertificate=true;Connect Timeout=30'
Caution
TrustServerCertificate=true Salta la validación del certificado del servidor. Úsalo solo con una instancia de desarrollo local. Para instancias compartidas o de producción de SQL Server, instala un certificado en el que el cliente confíe y elimina TrustServerCertificate=true. Para obtener más información, consulte Cifrado y validación de certificados en Microsoft.Data.SqlClient.
Agregar el código
Reemplace el contenido de Program.cs por el código siguiente:
using System.Data;
using Microsoft.Data.SqlClient;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddSingleton<MessageStore>();
var app = builder.Build();
await app.Services.GetRequiredService<MessageStore>()
.EnsureTableAsync(app.Lifetime.ApplicationStopping);
app.MapPost("/messages", async (
NewMessage input, MessageStore store, CancellationToken cancellationToken) =>
{
if (string.IsNullOrWhiteSpace(input.Text) || input.Text.Length > 200)
{
return Results.BadRequest("Text must be 1 to 200 characters.");
}
Message message = await store.AddAsync(input.Text, cancellationToken);
return Results.Created($"/messages/{message.Id}", message);
});
app.MapGet("/messages/{id:int}", async (
int id, MessageStore store, CancellationToken cancellationToken) =>
await store.GetAsync(id, cancellationToken) is Message message
? Results.Ok(message)
: Results.NotFound());
app.Run();
record NewMessage(string Text);
record Message(int Id, string Text, DateTimeOffset CreatedAt);
sealed class MessageStore(IConfiguration configuration)
{
private readonly string _connectionString =
configuration.GetConnectionString("Quickstart")
?? throw new InvalidOperationException(
"Set the ConnectionStrings:Quickstart configuration value.");
public async Task EnsureTableAsync(CancellationToken cancellationToken)
{
const string sql = """
IF OBJECT_ID(N'dbo.SqlClientQuickstart', N'U') IS NULL
BEGIN
CREATE TABLE dbo.SqlClientQuickstart
(
Id int IDENTITY(1, 1) PRIMARY KEY,
Message nvarchar(200) NOT NULL,
CreatedAt datetimeoffset NOT NULL
CONSTRAINT DF_SqlClientQuickstart_CreatedAt
DEFAULT sysdatetimeoffset()
);
END;
""";
await using var connection = new SqlConnection(_connectionString);
await connection.OpenAsync(cancellationToken);
await using var command =
new SqlCommand(sql, connection) { CommandTimeout = 30 };
await command.ExecuteNonQueryAsync(cancellationToken);
}
public async Task<Message> AddAsync(
string text, CancellationToken cancellationToken)
{
const string sql = """
INSERT INTO dbo.SqlClientQuickstart (Message)
OUTPUT INSERTED.Id, INSERTED.Message, INSERTED.CreatedAt
VALUES (@message);
""";
await using var connection = new SqlConnection(_connectionString);
await connection.OpenAsync(cancellationToken);
await using var command =
new SqlCommand(sql, connection) { CommandTimeout = 30 };
command.Parameters.Add("@message", SqlDbType.NVarChar, 200).Value = text;
await using SqlDataReader reader =
await command.ExecuteReaderAsync(cancellationToken);
await reader.ReadAsync(cancellationToken);
return new Message(
reader.GetInt32(0), reader.GetString(1), reader.GetDateTimeOffset(2));
}
public async Task<Message?> GetAsync(
int id, CancellationToken cancellationToken)
{
const string sql = """
SELECT Id, Message, CreatedAt
FROM dbo.SqlClientQuickstart
WHERE Id = @id;
""";
await using var connection = new SqlConnection(_connectionString);
await connection.OpenAsync(cancellationToken);
await using var command =
new SqlCommand(sql, connection) { CommandTimeout = 30 };
command.Parameters.Add("@id", SqlDbType.Int).Value = id;
await using SqlDataReader reader =
await command.ExecuteReaderAsync(cancellationToken);
return await reader.ReadAsync(cancellationToken)
? new Message(
reader.GetInt32(0), reader.GetString(1), reader.GetDateTimeOffset(2))
: null;
}
}
Ejecuta la aplicación
Inicia la app en un puerto fijo:
dotnet run --urls http://localhost:5000
Al iniciar, la app crea la tabla si no existe. Cuando la app está lista, la salida incluye estas líneas:
info: Microsoft.Hosting.Lifetime[14]
Now listening on: http://localhost:5000
info: Microsoft.Hosting.Lifetime[0]
Application started. Press Ctrl+C to shut down.
info: Microsoft.Hosting.Lifetime[0]
Hosting environment: Development
Si la app no puede acceder a la base de datos, se detiene al iniciar con un SqlException. Para conocer las causas comunes, consulta Solucionar problemas.
Llamada a la API
Deja la app abierta y abre otra terminal. Añade un mensaje con una solicitud POST y luego léelo por ID con una solicitud GET. Si la tabla ya tiene filas, por ejemplo, del inicio rápido de la consola, sustituye 1 en la petición GET por la id que devuelva tu petición POST.
Para PowerShell:
Invoke-RestMethod -Method Post -Uri http://localhost:5000/messages -ContentType application/json -Body (@{ text = 'Hello from ASP.NET Core' } | ConvertTo-Json)
Invoke-RestMethod http://localhost:5000/messages/1
PowerShell formatea cada respuesta JSON como una tabla. La primera fila es la 201 Created respuesta a la solicitud POST, y la segunda fila es la respuesta GET:
id text createdAt
-- ---- ---------
1 Hello from ASP.NET Core 2026-10-21T00:04:43.3588978+00:00
1 Hello from ASP.NET Core 2026-10-21T00:04:43.3588978+00:00
Windows PowerShell 5.1 muestra createdAt como la cadena que devuelve la API. PowerShell 7 lo convierte a una fecha en hora local, como 10/20/2026 7:04:43 PM.
En Windows PowerShell, curl es un alias para Invoke-WebRequest, que no acepta las opciones de curl. Usa los comandos de PowerShell o ejecuta curl.exe desde el Símbolo del sistema.
Para el símbolo del sistema:
curl -X POST http://localhost:5000/messages -H "Content-Type: application/json" -d "{\"text\":\"Hello from ASP.NET Core\"}"
curl http://localhost:5000/messages/1
El Prompt de Comandos no trata comillas simples como caracteres de comillas, así que el cuerpo JSON usa comillas dobles escapadas con barras invertidas. Cada comando imprime la respuesta JSON:
{"id":1,"text":"Hello from ASP.NET Core","createdAt":"2026-10-21T00:05:15.4936763+00:00"}
{"id":1,"text":"Hello from ASP.NET Core","createdAt":"2026-10-21T00:05:15.4936763+00:00"}
Instrucciones para Bash:
curl -X POST http://localhost:5000/messages -H "Content-Type: application/json" -d '{"text":"Hello from ASP.NET Core"}'
curl http://localhost:5000/messages/1
{"id":1,"text":"Hello from ASP.NET Core","createdAt":"2026-10-20T20:44:17.8634925+00:00"}
{"id":1,"text":"Hello from ASP.NET Core","createdAt":"2026-10-20T20:44:17.8634925+00:00"}
Tus ID y marcas temporales varían. Si ejecutaste primero el inicio rápido de la consola, los ID continúan a partir de las filas de esta. Una solicitud de identificación que no existe devuelve 404 Not Found. Un mensaje vacío devuelve 400 Bad Request.
Pulsa Ctrl+C en el primer terminal para detener la aplicación.
Funcionamiento del código
- La app se registra
MessageStorecomo un singleton. Solo contiene la cadena de conexión, que lee una vez deIConfiguration. No mantiene la conexión. - Cada método crea un
SqlConnection, lo abre, ejecuta un comando y lo libera conawait using. Al liberar, se devuelve la conexión física al pool de conexiones, y la siguiente petición la reutiliza. El pooling de conexiones está activado por defecto, así que no necesitas configurarlo. Para opciones de ajuste, consulta SQL Server connection pooling con Microsoft. Data.SqlClient. - ASP.NET Core vincula el parámetro
CancellationTokena la solicitud. Si el cliente se desconecta, token cancela la apertura, el comando y la lectura. - Los parámetros
@messagey@idcoinciden con los tipos y tamaños de columna. La API valida la longitud del mensaje antes de enviar el valor a la base de datos. -
OUTPUT INSERTED.Id, INSERTED.Message, INSERTED.CreatedAtdevuelve la fila insertada, incluyendo el ID generado por el servidor y la marca de tiempo, sin una segunda consulta. - En otros entornos, ASP.NET Core lee la misma
ConnectionStrings:Quickstartclave desde variables de entorno, comoConnectionStrings__Quickstart, o desde otro proveedor de configuración, como Azure Key Vault.
Troubleshoot
| Error o síntoma | Elementos que se deben comprobar | Más información |
|---|---|---|
Set the ConnectionStrings:Quickstart configuration value. |
La app no encontró la cadena de conexión. Ejecuta dotnet user-secrets list en la carpeta del proyecto y comprueba que la app se ejecute en el Development entorno. |
Almacenamiento seguro de secretos de aplicaciones en desarrollo en ASP.NET Core |
System.ArgumentException: Cannot find an authentication provider for 'ActiveDirectoryDefault' En el inicio |
La cadena de conexión utiliza el modo de autenticación Active Directory, pero el proyecto no hace referencia a Microsoft.Data.SqlClient.Extensions.Azure. Añade el paquete con la misma versión que Microsoft.Data.SqlClient. |
La autenticación Microsoft Entra pasa a un paquete de extensiones en la 7.0 |
SqlException al iniciar |
La app no pudo conectarse ni crear la tabla. El número de error identifica la causa, como 18456 por un inicio de sesión fallido. | Solucionar problemas en el inicio rápido de la consola |
415 Unsupported Media Type |
La petición no establece Content-Type: application/json. |
Referencia rápida de las API mínimas |
Cannot bind parameter 'Headers' |
Ejecutaste el comando curl en PowerShell de Windows, donde curl ejecuta Invoke-WebRequest. Usa los comandos de PowerShell en Llamar a la API. |
Invoke-RestMethod |
''' is an invalid start of a value |
Ejecutaste el comando Bash curl en el Prompt de Comandos, que envía las comillas simples como parte del cuerpo. Usa los comandos de la línea de comandos en Llamar la API. | Llamar a la API |
Limpieza de recursos
Elimina la tabla con cualquier herramienta de consulta:
DROP TABLE IF EXISTS dbo.SqlClientQuickstart;
Quite la cadena de conexión almacenada. Desde la carpeta del proyecto, ejecuta:
dotnet user-secrets clear
Luego borra la carpeta del proyecto. Desde la carpeta principal, ejecuta el siguiente comando en PowerShell:
Remove-Item -Recurse -Force SqlClientWebQuickstart
Instrucciones para Bash:
rm -rf SqlClientWebQuickstart