Guides

ASP.NET Core and SQL Server

Running an ASP.NET Core app (API, MVC, Razor Pages, Blazor Server) on Meghly with SQL Server or another database — from preparing the project to migrations and SSMS.

What runs

  • Microsoft.NET.Sdk.Web projects: Web API, MVC, Razor Pages, Blazor Server.
  • .NET 10, 9 and 8 — the version comes from the .csproj's <TargetFramework> (such as net10.0). Use .NET 10 for new apps; on .NET 8/9 the panel warns you, as Microsoft's support is ending.
  • A Microsoft.NET.Sdk.Worker project (background service) in the same solution runs as a separate worker process.
  • Test projects (xUnit, NUnit, MSTest) are left out of the build.

Old ASP.NET MVC 5 / .NET Framework (net48, packages.config, web.config-style .csproj) runs only on Windows, so Meghly turns it away with a clear message. It has to be moved to ASP.NET Core first.

Preparing the project

Connection string

Meghly gives the database connection as ConnectionStrings__Default, so name it Default in your code:

Program.cs
builder.Services.AddDbContext<AppDbContext>(o =>
    o.UseSqlServer(builder.Configuration.GetConnectionString("Default")));

For PostgreSQL use UseNpgsql, for MySQL/MariaDB UseMySql — the name is still Default. A connection string for your own PC in appsettings.json does no harm; the environment's value takes its place.

No migrations at start-up

Remove context.Database.Migrate() and EnsureCreated(). The running app gets the runtime login, which cannot create tables. Migrations run before every deploy, in the release (see below).

Health check

By default Meghly expects a 2xx or 3xx answer on / (a redirect to the login page is fine). Your own is better:

Program.cs
builder.Services.AddHealthChecks();
app.MapHealthChecks("/healthz");

Then put /healthz in the app's General → Health check.

HTTPS and the visitor's IP

The app runs behind Meghly's router. Meghly sets ASPNETCORE_FORWARDEDHEADERS_ENABLED=true itself, so the app knows the request came over HTTPS and from which IP. app.UseHttpsRedirection() does no harm.

Data Protection keys

Login cookies and antiforgery tokens are protected by keys kept inside the container by default, and the container's file system is read-only. Unless the keys are kept somewhere, everyone is logged out after every deploy and forms show "antiforgery token" errors. Do one of these:

  • Keep them in the database (better): the Microsoft.AspNetCore.DataProtection.EntityFrameworkCore package, a DbSet<DataProtectionKey> in your DbContext, a migration, then:
    csharp
    builder.Services.AddDataProtection().PersistKeysToDbContext<AppDbContext>();
  • Keep them on a volume: add a volume on the app's Files & backups page (such as /app/keys), then PersistKeysToFileSystem(new DirectoryInfo("/app/keys")).

File uploads

wwwroot/uploads cannot be written to directly. Add a volume at that path in Files & backups (such as /app/wwwroot/uploads), and uploads survive deploys.

Creating the database and the app

  1. In the panel, Apps → New app → a Git repository or a zip.
  2. In What is it? choose ASP.NET Core, the version and the Framework (ASP.NET Core API or ASP.NET Core MVC).
  3. Tick It needs a database; to change the engine, Advanced → Database engine → SQL Server (or PostgreSQL, MySQL, MariaDB).
  4. Add the variables you need (such as ASPNETCORE_ENVIRONMENT=Production, API keys).
  5. Deploy. The Detect step shows what it found, such as "ASP.NET Core 10.0 · EF Core migrations found".

SQL Server connections are always encrypted; the certificate is the server's own, so the string Meghly gives has TrustServerCertificate=True — use that one. Everything about databases: Databases.

Migrations: two ways

Pick one, not both.

(a) EF Core migrations. With Microsoft.EntityFrameworkCore.Design (or .Tools) in the web project, the build makes a migration bundle by itself. Before every deploy it runs with the migration login and applies only the migrations not yet applied. You only create migrations and commit them:

powershell
dotnet ef migrations add AddOrders

The bundle runs your Program.cs to build the DbContext, and the release gets all the app's variables — so what start-up needs is there in the release too.

(b) SQL scripts. .sql files in a db/migrations/ folder at the repository's root: 0001_create_orders.sql, 0002_add_index.sql … They run in name order, each once. GO splits batches. The whole script runs in one transaction — on any error nothing is kept and the deploy does not happen. Changing a script that has already run stops the release; add a new script instead.

Connecting with SSMS

SQL Server's port is open only to your app by default. To connect from SSMS or Azure Data Studio:

  1. In the panel, Databases → choose the database → Remote Access → আমার IP যোগ করো (add my IP), or your office's IP / network → Save allowlist. Up to 20, public IPs only.
  2. In SSMS:
    • Server name: <host>,<port> as the panel shows it (a comma between).
    • Authentication: SQL Server Authentication, the migration login (to change the schema).
    • Encryption: Mandatory, and tick Trust server certificate.
  3. When done, remove the IP — the port closes again.

Bringing an old database with a .bak

  1. On the old SQL Server, take a full backup without encryption:
    sql
    BACKUP DATABASE [MyShop] TO DISK = N'C:\backup\MyShop.bak' WITH COPY_ONLY, CHECKSUM, INIT;
  2. In the panel, Databases → the database → Import .bak file → choose the file → Import .bak.
  3. Meghly checks that the backup is not from a newer SQL Server than this one (2025), is not encrypted or TDE, has no FILESTREAM, and fits your plan.

The restore replaces your database — the data in it now is lost. The old server's logins (such as sa) do not come along; the app runs with Meghly's runtime login.

The other way round, Download export gives a verified .bak.

When something goes wrong

What you seeCause and fix
Build: "ASP.NET MVC 5 / .NET Framework"A Windows-only project — move it to ASP.NET Core.
Build: "targets .NET 7"Set <TargetFramework>net10.0</TargetFramework>.
Release: CREATE TABLE permission deniedThe app runs migrations itself — remove Migrate() / EnsureCreated().
The deploy stops at the health checkCheck the app listens on PORT and / (or your path) answers 2xx/3xx; start-up exceptions are in Logs.
Everyone is logged out after each deployKeep the Data Protection keys (see above).
certificate chain errorUse the connection string Meghly gives (TrustServerCertificate=True).
SSMS: timeoutCheck Remote Access has your current IP — home IPs change often.

Stuck?

Talk to our engineers directly — by phone or email.

01782618248shohag.meghly@gmail.com