[{"data":1,"prerenderedAt":513},["ShallowReactive",2],{"docs-nav":3,"docs:\u002Fdocs\u002Ftutorials\u002Fdotnet-web-api":139},[4,7,10,13,16,19,22,25,28,31,34,37,40,43,46,49,52,55,58,61,64,67,70,73,76,79,82,85,88,91,94,97,100,103,106,109,112,115,118,121,124,127,130,133,136],{"path":5,"title":6},"\u002Fdocs\u002Faccess-gating","Protect a local route",{"path":8,"title":9},"\u002Fdocs\u002Farchitecture\u002Fsecurity-and-trust","Security and trust",{"path":11,"title":12},"\u002Fdocs\u002Fconcepts\u002Fbuilds-and-deployments","Build and deploy",{"path":14,"title":15},"\u002Fdocs\u002Fconcepts\u002Fconfiguration-ownership","Where configuration belongs",{"path":17,"title":18},"\u002Fdocs\u002Fconcepts\u002Fenvironments-and-secrets","Environment values and secrets",{"path":20,"title":21},"\u002Fdocs\u002Fconcepts\u002Fmental-model","How projects fit together",{"path":23,"title":24},"\u002Fdocs\u002Fconcepts\u002Fplans-and-apply","Plans and apply",{"path":26,"title":27},"\u002Fdocs\u002Fconcepts\u002Ftargets-and-runtimes","Choose a target and runtime",{"path":29,"title":30},"\u002Fdocs\u002Fcontribute\u002Freleases","Publish a release",{"path":32,"title":33},"\u002Fdocs\u002Fdevelopment-mounts","Development mounts",{"path":35,"title":36},"\u002Fdocs\u002Fgetting-started","Getting started",{"path":38,"title":39},"\u002Fdocs\u002Fhelp\u002Ffaq","FAQ",{"path":41,"title":42},"\u002Fdocs\u002Fhelp\u002Ftroubleshooting","Troubleshooting",{"path":44,"title":45},"\u002Fdocs\u002Fhow-to\u002Fdeploy-production","Prepare a deployment environment",{"path":47,"title":48},"\u002Fdocs\u002Fhow-to\u002Fswarm-cluster","Run on a multi-node Swarm",{"path":50,"title":51},"\u002Fdocs","mm documentation",{"path":53,"title":54},"\u002Fdocs\u002Fjobs-and-schedules","Jobs and schedules",{"path":56,"title":57},"\u002Fdocs\u002Flocal-dashboard","Local dashboard",{"path":59,"title":60},"\u002Fdocs\u002Flocal-https","Local HTTPS",{"path":62,"title":63},"\u002Fdocs\u002Flocal-services","Local services",{"path":65,"title":66},"\u002Fdocs\u002Fmcp","Let an AI agent work on your project",{"path":68,"title":69},"\u002Fdocs\u002Fmulti-project-hosts","Run multiple projects on one host",{"path":71,"title":72},"\u002Fdocs\u002Fonboarding","Set up a project",{"path":74,"title":75},"\u002Fdocs\u002Fopenbao","Use OpenBao",{"path":77,"title":78},"\u002Fdocs\u002Fproject\u002Fcontributing","Contributing",{"path":80,"title":81},"\u002Fdocs\u002Fproject\u002Flicense","License",{"path":83,"title":84},"\u002Fdocs\u002Fproject\u002Fsecurity","Security",{"path":86,"title":87},"\u002Fdocs\u002Freference\u002Fcapability-matrix","Supported features and platforms",{"path":89,"title":90},"\u002Fdocs\u002Freference\u002Fcli","CLI command reference",{"path":92,"title":93},"\u002Fdocs\u002Freference\u002Fconfiguration","Configuration",{"path":95,"title":96},"\u002Fdocs\u002Freference\u002Fenvironment-variables","Environment variables",{"path":98,"title":99},"\u002Fdocs\u002Freference\u002Ferrors-and-exit-codes","Errors and exit codes",{"path":101,"title":102},"\u002Fdocs\u002Freference\u002Fknown-issues","Known limitations",{"path":104,"title":105},"\u002Fdocs\u002Fremote-access","Manage remote access",{"path":107,"title":108},"\u002Fdocs\u002Fremote-daemon","Set up a remote host",{"path":110,"title":111},"\u002Fdocs\u002Fruntime-observability","Status, logs, and commands",{"path":113,"title":114},"\u002Fdocs\u002Fsecret-delivery","Pass secrets to your app",{"path":116,"title":117},"\u002Fdocs\u002Fsecret-providers","Choose a secret store",{"path":119,"title":120},"\u002Fdocs\u002Fstart\u002Finstall","Install mm",{"path":122,"title":123},"\u002Fdocs\u002Fterminal-ui","Terminal UI",{"path":125,"title":126},"\u002Fdocs\u002Ftutorials\u002Fdotnet-web-api",".NET web API example",{"path":128,"title":129},"\u002Fdocs\u002Ftutorials\u002Ffirst-local-app","First local app",{"path":131,"title":132},"\u002Fdocs\u002Ftutorials\u002Flaravel-rust","Laravel and Rust example",{"path":134,"title":135},"\u002Fdocs\u002Ftutorials\u002Fnode-fullstack","Node full stack example",{"path":137,"title":138},"\u002Fdocs\u002Fvault","Use HashiCorp Vault",{"id":140,"title":126,"body":141,"description":506,"extension":507,"meta":508,"navigation":509,"path":125,"seo":510,"stem":511,"__hash__":512},"docs\u002Fdocs\u002Ftutorials\u002Fdotnet-web-api.md",{"type":142,"value":143,"toc":500},"minimark",[144,152,157,166,170,193,298,301,304,310,382,386,478,489,496],[145,146,147,151],"p",{},[148,149,150],"code",{},"examples\u002Fdotnet-web-api"," is an ASP.NET Core 10 minimal API backed by PostgreSQL 17. Locked NuGet restore and pinned images keep builds deterministic.",[153,154,156],"h2",{"id":155},"before-you-start","Before you start",[145,158,159,160,165],{},"Complete ",[161,162,164],"a",{"href":163},".\u002Ffirst-local-app#set-up-the-workstation","workstation setup"," on a\nLinux systemd host with HAProxy. You need Docker Buildx, Docker Compose or\nPodman Compose, and a registry you can push to. Replace the example image\nrepository, commit the change, and use a full checkout with tags.",[153,167,169],{"id":168},"prepare-the-project","Prepare the project",[145,171,172,173,176,177,180,181,184,185,188,189,192],{},"The local environment selects the Dockerfile's ",[148,174,175],{},"development"," target. It runs\n",[148,178,179],{},"dotnet watch",", source mounts at ",[148,182,183],{},"\u002Fsource",", and managed volumes preserve\n",[148,186,187],{},"\u002Fsource\u002Fbin"," and ",[148,190,191],{},"\u002Fsource\u002Fobj",". Production selects the final ASP.NET runtime\ntarget and direct environment delivery.",[194,195,200],"pre",{"className":196,"code":197,"language":198,"meta":199,"style":199},"language-sh shiki shiki-themes mm","cd examples\u002Fdotnet-web-api\nmm config validate\nmm env review\nmm dev mounts plan api\nmm config ingress explain api\nmm secret init age\nmm secret generate --missing\n","sh","",[148,201,202,215,227,238,255,270,284],{"__ignoreMap":199},[203,204,207,211],"span",{"class":205,"line":206},"line",1,[203,208,210],{"class":209},"svrjQ","cd",[203,212,214],{"class":213},"sv8ni"," examples\u002Fdotnet-web-api\n",[203,216,218,221,224],{"class":205,"line":217},2,[203,219,220],{"class":209},"mm",[203,222,223],{"class":213}," config",[203,225,226],{"class":213}," validate\n",[203,228,230,232,235],{"class":205,"line":229},3,[203,231,220],{"class":209},[203,233,234],{"class":213}," env",[203,236,237],{"class":213}," review\n",[203,239,241,243,246,249,252],{"class":205,"line":240},4,[203,242,220],{"class":209},[203,244,245],{"class":213}," dev",[203,247,248],{"class":213}," mounts",[203,250,251],{"class":213}," plan",[203,253,254],{"class":213}," api\n",[203,256,258,260,262,265,268],{"class":205,"line":257},5,[203,259,220],{"class":209},[203,261,223],{"class":213},[203,263,264],{"class":213}," ingress",[203,266,267],{"class":213}," explain",[203,269,254],{"class":213},[203,271,273,275,278,281],{"class":205,"line":272},6,[203,274,220],{"class":209},[203,276,277],{"class":213}," secret",[203,279,280],{"class":213}," init",[203,282,283],{"class":213}," age\n",[203,285,287,289,291,294],{"class":205,"line":286},7,[203,288,220],{"class":209},[203,290,277],{"class":213},[203,292,293],{"class":213}," generate",[203,295,297],{"class":296},"sbRf1"," --missing\n",[145,299,300],{},"Compose defines PostgreSQL and its data volume. mm supplies the API build,\nenvironment values, and managed network settings.",[153,302,12],{"id":303},"build-and-deploy",[145,305,306,307,309],{},"After ",[161,308,164],{"href":163},", replace\nthe illustrative registry repository and publish from a clean full clone:",[194,311,313],{"className":196,"code":312,"language":198,"meta":199,"style":199},"mm build --publish plan\nmm build --publish apply --plan BUILD_PLAN_HASH --yes\nmm deploy plan\nmm deploy apply --plan DEPLOY_PLAN_HASH --yes\nmm service status\n",[148,314,315,328,348,357,372],{"__ignoreMap":199},[203,316,317,319,322,325],{"class":205,"line":206},[203,318,220],{"class":209},[203,320,321],{"class":213}," build",[203,323,324],{"class":296}," --publish",[203,326,327],{"class":213}," plan\n",[203,329,330,332,334,336,339,342,345],{"class":205,"line":217},[203,331,220],{"class":209},[203,333,321],{"class":213},[203,335,324],{"class":296},[203,337,338],{"class":213}," apply",[203,340,341],{"class":296}," --plan",[203,343,344],{"class":213}," BUILD_PLAN_HASH",[203,346,347],{"class":296}," --yes\n",[203,349,350,352,355],{"class":205,"line":229},[203,351,220],{"class":209},[203,353,354],{"class":213}," deploy",[203,356,327],{"class":213},[203,358,359,361,363,365,367,370],{"class":205,"line":240},[203,360,220],{"class":209},[203,362,354],{"class":213},[203,364,338],{"class":213},[203,366,341],{"class":296},[203,368,369],{"class":213}," DEPLOY_PLAN_HASH",[203,371,347],{"class":296},[203,373,374,376,379],{"class":205,"line":257},[203,375,220],{"class":209},[203,377,378],{"class":213}," service",[203,380,381],{"class":213}," status\n",[153,383,385],{"id":384},"verify-https-and-mail","Verify HTTPS and mail",[194,387,389],{"className":196,"code":388,"language":198,"meta":199,"style":199},"curl --resolve api.dotnet-web-api.test:443:127.0.0.1 \\\n  https:\u002F\u002Fapi.dotnet-web-api.test\u002Fhealth\ncurl --resolve api.dotnet-web-api.test:443:127.0.0.1 \\\n  https:\u002F\u002Fapi.dotnet-web-api.test\u002Fapi\u002Fwidgets\ncurl --resolve api.dotnet-web-api.test:443:127.0.0.1 \\\n  -H 'content-type: application\u002Fjson' \\\n  -d '{\"to\":\"developer@example.test\"}' \\\n  https:\u002F\u002Fapi.dotnet-web-api.test\u002Fapi\u002Fmail-preview\nmm service logs api --follow\n",[148,390,391,406,411,421,426,436,446,456,462],{"__ignoreMap":199},[203,392,393,396,399,402],{"class":205,"line":206},[203,394,395],{"class":209},"curl",[203,397,398],{"class":296}," --resolve",[203,400,401],{"class":213}," api.dotnet-web-api.test:443:127.0.0.1",[203,403,405],{"class":404},"s1Wbj"," \\\n",[203,407,408],{"class":205,"line":217},[203,409,410],{"class":213},"  https:\u002F\u002Fapi.dotnet-web-api.test\u002Fhealth\n",[203,412,413,415,417,419],{"class":205,"line":229},[203,414,395],{"class":209},[203,416,398],{"class":296},[203,418,401],{"class":213},[203,420,405],{"class":404},[203,422,423],{"class":205,"line":240},[203,424,425],{"class":213},"  https:\u002F\u002Fapi.dotnet-web-api.test\u002Fapi\u002Fwidgets\n",[203,427,428,430,432,434],{"class":205,"line":257},[203,429,395],{"class":209},[203,431,398],{"class":296},[203,433,401],{"class":213},[203,435,405],{"class":404},[203,437,438,441,444],{"class":205,"line":272},[203,439,440],{"class":296},"  -H",[203,442,443],{"class":213}," 'content-type: application\u002Fjson'",[203,445,405],{"class":404},[203,447,448,451,454],{"class":205,"line":286},[203,449,450],{"class":296},"  -d",[203,452,453],{"class":213}," '{\"to\":\"developer@example.test\"}'",[203,455,405],{"class":404},[203,457,459],{"class":205,"line":458},8,[203,460,461],{"class":213},"  https:\u002F\u002Fapi.dotnet-web-api.test\u002Fapi\u002Fmail-preview\n",[203,463,465,467,469,472,475],{"class":205,"line":464},9,[203,466,220],{"class":209},[203,468,378],{"class":213},[203,470,471],{"class":213}," logs",[203,473,474],{"class":213}," api",[203,476,477],{"class":296}," --follow\n",[145,479,480,481,484,485,488],{},"Open ",[148,482,483],{},"https:\u002F\u002Fmail.mm.test"," or the installation dashboard at ",[148,486,487],{},"https:\u002F\u002Fmm.test",".\nFollow the project link there. Shared services may need one\nservices plan\u002Fapply after a newly cloned project is registered so the project\ndashboard certificate includes its hostname.",[145,490,491,492,495],{},"Use this example for development. Coordinate PostgreSQL\npassword rotation with the database. If an application supports a password-file\nsetting, prefer ",[148,493,494],{},"secret-files"," and runtime-native delivery; this API accurately\nuses secret-backed environment delivery because Npgsql expects a value.",[497,498,499],"style",{},"html pre.shiki code .svrjQ, html code.shiki .svrjQ{--shiki-default:var(--mm-code-function)}html pre.shiki code .sv8ni, html code.shiki .sv8ni{--shiki-default:var(--mm-code-string)}html pre.shiki code .sbRf1, html code.shiki .sbRf1{--shiki-default:var(--mm-code-option)}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html pre.shiki code .s1Wbj, html code.shiki .s1Wbj{--shiki-default:var(--mm-code-constant)}",{"title":199,"searchDepth":217,"depth":217,"links":501},[502,503,504,505],{"id":155,"depth":217,"text":156},{"id":168,"depth":217,"text":169},{"id":303,"depth":217,"text":12},{"id":384,"depth":217,"text":385},"Run ASP.NET Core with an SDK live mount, PostgreSQL, HTTPS, and Mailpit.","md",{},true,{"title":126,"description":506},"docs\u002Ftutorials\u002Fdotnet-web-api","yw9aWADWyIPiWUEx_qkdX0ou85u88pEEsQjzepzhGZQ",1794512546196]