{"slug": "finishing-what-i-started-autodoc-ai-powered-openapi-docs-from-c", "title": "Finishing What I Started: AutoDoc: AI-Powered OpenAPI Docs from C# 🤖", "summary": "AutoDoc, an AI-powered tool that generates OpenAPI 3.0.3 documentation from raw C# ASP.NET Core controller code without manual annotations, was completed as part of the GitHub Finish-Up-A-Thon Challenge. The tool uses a local AI model to automatically infer routes, HTTP methods, parameters, response codes, error schemas, and operation summaries from unmodified controller code, evolving from a terminal-based console app into a fully containerized web API with a browser-accessible playground UI.", "body_md": "*This is a submission for the GitHub Finish-Up-A-Thon Challenge*\n\nAutoDoc is a tool that automatically generates enriched OpenAPI 3.0.3 documentation from raw C# ASP.NET Core controller code using a local AI model - no manual annotations, no attribute decorators, no maintenance required.\n\nThe idea came from a real frustration I noticed during my software engineering internship. Swagger documentation in .NET projects only documents what developers explicitly declare. Miss an attribute, forget an error response, skip a summary and your docs silently drift from reality. Developers spend time writing documentation instead of writing code.\n\nAutoDoc fixes this by reading raw C# controller code directly and inferring everything automatically: routes, HTTP methods, parameters, response codes, error schemas, and operation summaries.\n\nThe project was built in 3 phases:\n\n| Phase | What it does |\n|---|---|\n| Phase 1 - Console App | Paste controller code, get OpenAPI YAML in the terminal |\n| Phase 2 - Docker Web API | Containerised REST backend, call via HTTP POST, get YAML back |\n| Phase 3 - Playground UI | Browser dashboard: paste code, see Raw YAML + Swagger Preview instantly |\n\nWhat started as a terminal script became a fully containerised, browser-accessible API documentation tool and this challenge is what pushed me to finish it.\n\nHow it works: paste any C# ASP.NET Core controller, click generate, get full OpenAPI docs instantly.\n\nThe AutoDoc Playground UI is a split-panel dashboard. On the left, you paste any ASP.NET Core controller code - no modifications needed. The sample `TodoController`\n\ncomes pre-filled so you can test immediately. Hit Generate OpenAPI Docs and AutoDoc sends the raw code to the AI backend running locally via Ollama.No attributes. No decorators. No `[ProducesResponseType]`\n\n. Just raw C# code.\n\n**Input: this is the only code AutoDoc received:**\n\n```\n[ApiController]\n[Route(\"api/[controller]\")]\npublic class TodoController : ControllerBase\n{\n    [HttpGet]\n    public IActionResult GetAll() => Ok(new[] { \"Task 1\", \"Task 2\" });\n}\n```\n\nNo `[ProducesResponseType]`\n\n. No `[SwaggerOperation]`\n\n. No XML comments.\n\nNo manual annotations of any kind. Just raw C# code.\n\n**Output: full OpenAPI 3.0.3 spec generated automatically:**\n\nAI inferred everything automatically:\n\n| What was inferred | How |\n|---|---|\n`operationId` |\nUnique names like `GetAllTodos` , `CreateTodo`\n|\n`tags` |\nGrouped by controller name `TodoController`\n|\n`summary` |\nHuman-readable descriptions per endpoint |\n`requestBody` |\nSchema inferred from method parameters |\n`responses` |\n200, 201, 400, 404, 500 from code logic |\n`components/schemas/ErrorResponse` |\nDefined once, referenced everywhere |\n\nnone of this existed in the original controller code.\n\nSwitching to the Swagger Preview tab renders the YAML as a live interactive Swagger UI. The POST `/api/Todo`\n\nendpoint shows:\n\nThe GET `/api/Todo`\n\nendpoint shows:\n\n`Ok(new[] { \"Task 1\", \"Task 2\" })`\n\n.\nInternal Server Error fallback on every endpoint automatically.The AI understood what `Ok(new[] { ... })`\n\nreturns and documented it correctly as an array schema.\n\nAt the bottom of the Swagger Preview, the **Schemas** section shows the auto-generated `ErrorResponse`\n\nschema with:\n\n`code`\n\n: integer`message`\n\n: stringThis schema was never defined anywhere in the C# controller. AutoDoc inferred it from the pattern of error responses across all endpoints and generated it once, referenced consistently throughout the entire spec.\n\nAutoDoc began as a simple console application - a proof of concept to answer 1 question:\n\nCan an AI model read raw C# controller code and generate valid OpenAPI documentation without any manual annotations?\n\nThe answer was yes. But the Phase 1 console app was far from finished:\n\n| What existed | What was missing |\n|---|---|\n| Console app that called Ollama locally | No HTTP interface - unusable by others |\n| Raw YAML printed to terminal | No output validation |\n| Basic Llama 3.2 prompt | No error handling |\n| Proof the concept worked | No UI, no Docker, no way to share it |\n\nIt worked on my machine. That was it.\n\n**Phase 2 - From console app to Docker REST API**\n\nThe console app was converted into a proper ASP.NET Core minimal API with 2 endpoints:\n\n`POST /generate-openapi`\n\n- receives controller code as JSON, returns enriched OpenAPI YAML.`GET /health`\n\n- confirms the service is running.A `Dockerfile`\n\nwas added so the entire service runs in a container with a single `docker run`\n\ncommand. The Ollama host was made configurable via environment variable so it works both locally (`localhost:11434`\n\n) and inside Docker (`host.docker.internal:11434`\n\n).\n\n**Phase 3 - Playground UI**\n\nA browser-based dashboard was built and served directly from the Docker container via `wwwroot`\n\n. No separate frontend deployment needed - the UI and API ship together.\n\nThe playground features:\n\n**The hardest part - taming Llama 3.2 output**\n\nLlama 3.2 is a small, free, local model. It does a remarkable job generating mostly correct OpenAPI YAML - but it makes small inconsistent mistakes. Each one broke the Swagger Preview with a parsing error.\n\nA full post-processing pipeline was built to fix every category of output error:\n\n| Helper function | Problem it solves |\n|---|---|\n`MergeDuplicatePaths` |\nLlama repeating the same API path twice |\n`MergeDuplicateMethods` |\nLlama repeating GET/POST under the same path |\n`MergeDuplicateComponents` |\nLlama emitting `components:` key twice |\n`RemoveDuplicateSchemaKeys` |\nLlama defining `ErrorResponse` twice |\n`RemoveMalformedSecurity` |\nLlama adding broken `security:` blocks |\n`FixMalformedOperationIds` |\nLlama using `{verb}` as a literal placeholder |\n`NormaliseOutput` |\nSchema name typos like `ErrorRespond`\n|\n\nEach helper was born from a real parsing error seen in production output. The pipeline runs on every generation before the YAML is returned to the client.\n\n| Phase 1 - Console App | Phase 3 - Full AutoDoc | |\n|---|---|---|\n| Interface | Terminal only | Browser dashboard |\n| Deployment | Local .NET required | Docker container |\n| Output | Raw YAML in terminal | Raw YAML + live Swagger Preview |\n| Validation | None | YAML cleaning pipeline + spec validation |\n| Usability | Developer only | Anyone with a browser |\n| Shareable | No | Yes - 1 `docker run` command |\n\nWhat started as a terminal experiment is now a containerised, browser-accessible documentation tool that anyone can run and use.\n\nGitHub Copilot was my implementation partner throughout AutoDoc.I defined the problems and architecture,Copilot wrote the code.\n\nI used Copilot not for autocomplete but as a problem-to-code translator. I described what I needed in plain English, Copilot read my existing code, and produced working implementations I could review, test, and keep.\n\nThe first key prompt connected the backend to the frontend:\n\n\"I am building an ASP.NET Core 10 Minimal API called AutoDoc.I want to serve static files from a wwwroot folder and make sure it serves index.html as the default page. How should I update my Program.cs to allow this?\"\n\nCopilot read my existing `Program.cs`\n\ndirectly, understood the current pipeline, and knew exactly what to add without breaking anything.\n\nIt explained what it was doing and why - then applied the change automatically:\n\n```\napp.UseDefaultFiles();\napp.UseStaticFiles();\n```\n\n2 lines. Copilot explained that `UseDefaultFiles()`\n\nrewrites `/`\n\nto `/index.html`\n\nand `UseStaticFiles()`\n\nserves everything in `wwwroot`\n\n. It then validated the file for compile errors before confirming. The change was applied in one shot - I clicked **Keep**.\n\nThe result: `index.html`\n\ncreated in `wwwroot`\n\n, `Program.cs`\n\nupdated, Copilot confirming **1 file changed, +4 -0**. The Playground UI was now being served directly from the Docker container.\n\nWith the static file serving in place, the next prompt built the entire frontend:\n\n\"Build a dark-themed single-page HTML dashboard for AutoDoc.Left panel: controller name input and C# code textarea with a Generate button. Right panel: tabbed output with Raw YAML (monospace) and Swagger Preview rendered from the YAML using SwaggerUIBundle. Show a status pill in the header that updates during generation. No frameworks, vanilla JS only.\"\n\nCopilot generated the complete `index.html`\n\n:\n\n`fetch`\n\ncall to `/generate-openapi`\n\nwith full error handling.`jsyaml`\n\nfor YAML-to-spec parsing.The entire Playground UI came from a single prompt.\n\nEvery YAML cleaner in AutoDoc came from describing a real Llama output bug to Copilot:\n\n\"Llama is generating the`components:`\n\nkey twice in the output YAML. Write a C# helper that scans line by line and removes duplicate`components:`\n\nkeys, keeping only the first.\"\n\nCopilot wrote `MergeDuplicateComponents`\n\n. I repeated this pattern for all seven helpers - each one targeting a specific category of Llama output error discovered during testing.\n\nCopilot was most valuable not when I said *\"write this\"* but when I said *\"here is the problem I am seeing, fix it.\"*\n\nIt read my existing code before responding. It explained its reasoning. It validated changes before applying them. It felt less like autocomplete and more like a senior developer who already knew my codebase.\n\nCopilot is powerful but not perfect. Here is what it could not do:\n\n| Limitation | What happened |\n|---|---|\n| Could not predict Llama output bugs | Every YAML cleaner was reactive - I discovered the bug first, then asked Copilot to fix it |\n| Did not flag environment differences | Generated `host.docker.internal` hardcoded - broke local `dotnet run` , I found the error myself |\n| Could not test browser output | Generated the Playground UI confidently but could not see the broken Swagger Preview in a browser |\n| Prompt quality = output quality | Vague prompts gave generic results - writing precise prompts was a skill I had to develop |\n\nThe pattern was consistent: Copilot excelled at implementation, but discovery and debugging required a human.It could not run the code, open the browser, or experience the errors - I had to do that and bring the findings back to Copilot to fix.\n\nAutoDoc is functional but it is just the beginning.\n\nThe current version uses **Llama 3.2 locally via Ollama** which is free\n\nand private, but limited in output consistency. The natural next step is upgrading to a more capable model for cleaner, more reliable YAML generation.\n\nHere is what I hope to build next:\n\n| Feature | Why |\n|---|---|\n| Support for larger Ollama models (Llama 3.1, Mistral) | Better output quality, fewer post-processing fixes needed |\n| Multi-controller batch generation | Generate docs for an entire project at once |\n| GitHub Actions CI/CD integration | Auto-generate docs on every push |\n| Diff-based incremental generation | Only regenerate endpoints that changed |\n| Export to JSON | Support both YAML and JSON OpenAPI formats |\n\nThe biggest hope is this: AI-generated documentation that stays in sync with code automatically - no manual maintenance, no drift, no outdated Swagger specs.\n\nDevelopers should write code. The AI should write the docs.\n\nWorking with GitHub Copilot on AutoDoc changed how I think about\n\nbuilding software. Before this project, I used it for small autocomplete suggestions. After this project, I use it as a genuine collaborator.\n\nWhat I hope to do differently next time:\n\nThe most important thing I learned: Copilot is only as good as the problem you give it.vague problems get vague code. Clear problems get working code.\n\nAutoDoc taught me to think more clearly about problems because I had to describe them precisely enough for an AI to solve them. That skill makes me a better developer with or without Copilot.\n\n*Try it yourself! clone the repo, run Ollama, and paste your 1st C# controller. I'd love to see what AutoDoc generates for your API. Drop a comment with your results.*", "url": "https://wpnews.pro/news/finishing-what-i-started-autodoc-ai-powered-openapi-docs-from-c", "canonical_source": "https://dev.to/yoges_mohan_511bda5afbe7d/finishing-what-i-started-autodoc-ai-powered-openapi-docs-from-c-25g2", "published_at": "2026-05-28 07:55:03+00:00", "updated_at": "2026-05-28 08:23:31.047589+00:00", "lang": "en", "topics": ["artificial-intelligence", "ai-tools", "generative-ai", "large-language-models", "ai-products"], "entities": ["AutoDoc", "OpenAPI", "C#", "ASP.NET Core", "Swagger", "Docker", "GitHub"], "alternates": {"html": "https://wpnews.pro/news/finishing-what-i-started-autodoc-ai-powered-openapi-docs-from-c", "markdown": "https://wpnews.pro/news/finishing-what-i-started-autodoc-ai-powered-openapi-docs-from-c.md", "text": "https://wpnews.pro/news/finishing-what-i-started-autodoc-ai-powered-openapi-docs-from-c.txt", "jsonld": "https://wpnews.pro/news/finishing-what-i-started-autodoc-ai-powered-openapi-docs-from-c.jsonld"}}