Ir al contenido

Despliegue

IZ-CentralForms puede publicarse en un servidor Windows como una aplicación ASP.NET Core hospedada en IIS. La base de datos debe ejecutarse en una instancia real de SQL Server. LocalDB queda reservado únicamente para desarrollo local.

El despliegue productivo requiere:

Windows Server + IIS + .NET Hosting Bundle + SQL Server real + SMTP externo + HTTPS
CampoValor
ProyectoIZ-CentralForms
Tipo de aplicaciónASP.NET Core Web API
Target frameworknet10.0
Hosting recomendadoIIS
Base de datosSQL Server real
SMTPMailtrap, Resend, SMTP corporativo u otro proveedor autorizado
Ambiente actualLocal
ProducciónPendiente de implementación

Antes de desplegar se debe contar con:

  • Windows Server.
  • IIS habilitado.
  • .NET Hosting Bundle compatible con net10.0.
  • SQL Server Express, Standard o Enterprise.
  • Acceso para crear base de datos y ejecutar scripts SQL.
  • Proveedor SMTP o sandbox autorizado.
  • Certificado SSL válido para QA/Staging/Producción.
  • Permisos para crear Application Pool.
  • Permisos para publicar en la carpeta IIS.
  • Acceso a logs IIS y Event Viewer.
  1. Preparar servidor Windows.
  2. Instalar IIS.
  3. Instalar .NET Hosting Bundle.
  4. Confirmar acceso a SQL Server real.
  5. Crear base de datos con scripts de sql/deploy.
  6. Publicar la API con dotnet publish o scripts/publish-iis.ps1.
  7. Copiar publicación a IIS.
  8. Crear Application Pool.
  9. Configurar appsettings.Production.json.
  10. Registrar origins autorizados.
  11. Validar /health, Swagger si aplica, GET formulario, POST submission y endpoints admin.
  12. Entregar evidencias del despliegue.

Ejecutar en orden:

sql/deploy/00-create-database.sql
sql/deploy/01-create-schema.sql
sql/deploy/02-seed-demo.sql
sql/deploy/03-add-demo-destinations.sql
sql/deploy/04-verify-deploy.sql

Script opcional para pruebas desde Swagger en IIS local:

sql/deploy/05-add-localhost-iis-origins.sql
{
"ConnectionStrings": {
"DefaultConnection": "Server=SERVIDOR_SQL;Database=CentralFormsDb;User Id=centralforms_user;Password=PASSWORD_SEGURO;TrustServerCertificate=True;MultipleActiveResultSets=true"
}
}
{
"ConnectionStrings": {
"DefaultConnection": "Server=.\\SQLEXPRESS;Database=CentralFormsDb;Trusted_Connection=True;TrustServerCertificate=True;MultipleActiveResultSets=true"
}
}
{
"ConnectionStrings": {
"DefaultConnection": "Server=(localdb)\\MSSQLLocalDB;Database=CentralFormsDb;Trusted_Connection=True;MultipleActiveResultSets=true"
}
}

Si se usa usuario SQL, se recomienda asignar permisos mínimos necesarios sobre CentralFormsDb.

Si se usa Trusted_Connection=True, se debe crear login para el Application Pool:

USE master;
IF NOT EXISTS (
SELECT 1
FROM sys.server_principals
WHERE name = 'IIS APPPOOL\CentralForms.Api'
)
BEGIN
CREATE LOGIN [IIS APPPOOL\CentralForms.Api] FROM WINDOWS;
END;
USE CentralFormsDb;
IF NOT EXISTS (
SELECT 1
FROM sys.database_principals
WHERE name = 'IIS APPPOOL\CentralForms.Api'
)
BEGIN
CREATE USER [IIS APPPOOL\CentralForms.Api]
FOR LOGIN [IIS APPPOOL\CentralForms.Api];
END;
ALTER ROLE db_datareader ADD MEMBER [IIS APPPOOL\CentralForms.Api];
ALTER ROLE db_datawriter ADD MEMBER [IIS APPPOOL\CentralForms.Api];

Para una demo controlada puede usarse temporalmente:

ALTER ROLE db_owner ADD MEMBER [IIS APPPOOL\CentralForms.Api];

Desde la raíz del proyecto:

Ventana de terminal
Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass
.\scripts\publish-iis.ps1

Alternativa manual:

Ventana de terminal
dotnet publish .\CentralForms.Api\CentralForms.Api.csproj -c Release -o .\publish\CentralForms.Api

Copiar el contenido generado desde:

publish/CentralForms.Api

hacia:

C:\inetpub\wwwroot\CentralForms.Api

Crear o editar:

C:\inetpub\wwwroot\CentralForms.Api\appsettings.Production.json

Plantilla base:

{
"ConnectionStrings": {
"DefaultConnection": "Server=SERVIDOR_SQL;Database=CentralFormsDb;User Id=centralforms_user;Password=PASSWORD_SEGURO;TrustServerCertificate=True;MultipleActiveResultSets=true"
},
"Swagger": {
"Enabled": false
},
"Seed": {
"DemoData": false
},
"Email": {
"Host": "smtp.proveedor.com",
"Port": 587,
"EnableSsl": true,
"UserName": "USUARIO_SMTP",
"Password": "PASSWORD_SMTP",
"FromEmail": "no-reply@interzone.net",
"FromName": "CentralForms"
},
"Admin": {
"ApiKeyHash": "HASH_SHA256_DE_LA_ADMIN_KEY"
},
"AllowedHosts": "*"
}

Como alternativa a appsettings.Production.json, la configuración sensible puede definirse mediante variables de entorno. ASP.NET Core lee claves jerárquicas usando doble guion bajo __.

ASPNETCORE_ENVIRONMENT=Production
ConnectionStrings__DefaultConnection=Server=SERVIDOR_SQL;Database=CentralFormsDb;User Id=USUARIO_SQL;Password=PASSWORD_SQL;TrustServerCertificate=True;MultipleActiveResultSets=true
Admin__ApiKeyHash=HASH_SHA256_DE_LA_ADMIN_KEY
Email__Host=smtp.proveedor.com
Email__Port=587
Email__EnableSsl=true
Email__UserName=USUARIO_SMTP
Email__Password=PASSWORD_SMTP
Email__FromEmail=no-reply@interzone.net
Email__FromName=CentralForms
Swagger__Enabled=false
Seed__DemoData=false
CampoValor
NombreCentralForms.Api
.NET CLR VersionNo Managed Code
Managed Pipeline ModeIntegrated
IdentityApplicationPoolIdentity
CampoValor recomendado
Physical PathC:\inetpub\wwwroot\CentralForms.Api
Application PoolCentralForms.Api
Binding HTTPSolo para pruebas internas
Binding HTTPSObligatorio fuera de local
URL públicaPendiente según ambiente

El valor en AllowedOrigins.OriginUrl debe coincidir exactamente con el header Origin enviado por el navegador. En el código actual, Origin se valida cuando viene informado; para ambientes reales se recomienda exigirlo en los flujos públicos de navegador.

Ejemplos válidos:

http://localhost
https://localhost
https://localhost:7122
https://app.interzone.net

Ejemplos incorrectos:

http://localhost/CentralForms.Api
https://app.interzone.net/formulario

Si la aplicación se publica bajo una ruta virtual, por ejemplo:

http://localhost/CentralForms.Api

Swagger debe usar una ruta relativa para el JSON:

options.SwaggerEndpoint("v1/swagger.json", "CentralForms API v1");

No usar ruta absoluta:

options.SwaggerEndpoint("/swagger/v1/swagger.json", "CentralForms API v1");

porque buscaría el JSON en la raíz del sitio IIS y no dentro de /CentralForms.Api.

Validar en este orden:

GET /health
GET /swagger
GET /api/forms/demo/contacto
POST /api/forms/demo/contacto/submit
GET /api/admin/submissions
GET /api/admin/integration-logs

GET formulario:

X-Api-Key: demo-api-key
Origin: http://localhost

POST submit:

X-Api-Key: demo-api-key
X-CSRF-Token: TOKEN_DEL_GET
Origin: http://localhost
Content-Type: application/json

Admin:

X-Admin-Key: demo-admin-key

Después de un POST exitoso, validar persistencia e integraciones:

USE CentralFormsDb;
SELECT TOP 20 *
FROM Submissions
ORDER BY CreatedAt DESC;
SELECT TOP 20
Type,
Target,
Status,
StatusCode,
ErrorMessage,
StartedAt,
CompletedAt
FROM IntegrationLogs
ORDER BY StartedAt DESC;
ValidaciónResultado esperado
/health respondeAPI disponible
Swagger cargaSolo si está habilitado para el ambiente
GET formulario responde200 OK con definición y csrfToken
POST submit responde200 OK con submissionId
Submission se guardaRegistro visible en Submissions
Email se ejecutaRegistro visible en IntegrationLogs
Webhook se ejecutaRegistro visible en IntegrationLogs
HTTPS activoCertificado válido
Swagger producciónDeshabilitado o restringido
Seed demo producciónDesactivado
SíntomaCausa probableAcción
500.19Hosting Bundle no instalado o web.config no reconocidoInstalar o reparar Hosting Bundle y ejecutar iisreset.
/health OK pero GET formulario devuelve 500Problema SQL o connection stringRevisar base de datos, permisos y appsettings.Production.json.
GET formulario devuelve 404consumerCode o formCode incorrectoUsar demo/contacto o revisar tablas.
POST devuelve 403 OriginFalta Origin exacto en AllowedOriginsInsertar Origin exacto, sin path.
POST devuelve 403 CSRFToken vencido, reutilizado o de otro formularioEjecutar GET nuevamente y usar nuevo token.
POST devuelve 200 pero no llega correoSMTP o destino email mal configuradoRevisar FormDestinations, configuración Email e IntegrationLogs.
Swagger no carga JSONRuta Swagger absoluta bajo ruta virtualUsar v1/swagger.json como ruta relativa.
  1. Detener sitio o aplicación IIS.
  2. Restaurar carpeta publicada anterior.
  3. Restaurar appsettings.Production.json anterior si cambió.
  4. Restaurar backup de base de datos si hubo migración destructiva.
  5. Iniciar sitio IIS.
  6. Validar /health.
  7. Validar GET formulario.
  8. Validar POST submit.

El responsable del despliegue debe entregar:

  • URL publicada.
  • Fecha y hora de publicación.
  • Versión, commit o paquete publicado.
  • Resultado de /health.
  • Evidencia de Swagger si aplica.
  • Evidencia de GET formulario.
  • Evidencia de POST submit.
  • Evidencia de submission en base de datos o admin endpoint.
  • Evidencia de IntegrationLogs.
  • Observaciones y errores encontrados.