Build an Astrology App with .NET & Vedika API

Build an Astrology App with .NET C# and Vedika API
Published: March 13, 2026 | By Vedika Intelligence | Reading time: 15 minutes

.NET is Microsoft's world-class platform for building enterprise applications — and with ASP.NET Core 8, it has never been faster or more capable. Whether you're adding astrology features to an existing .NET application, building a new horoscope SaaS, or integrating birth chart capabilities into a matrimony platform, this guide shows the clean, idiomatic C# approach to working with Vedika API.

By the end of this tutorial, you'll have a fully functional ASP.NET Core 8 application with a Vedika API service using IHttpClientFactory, typed model classes, IMemoryCache for cost optimization, a background service for daily horoscope pre-generation, global exception handling middleware, and a Razor Pages frontend — all following modern .NET conventions.

What You'll Build: An ASP.NET Core 8 application exposing astrology REST endpoints backed by Vedika API. Includes strongly-typed model binding, dependency injection, memory caching, a background hosted service for batch horoscope generation, problem details error responses, and a simple Razor Pages UI for end users.

Why .NET for Astrology Applications?

Native async/await

C# async/await is first-class. Every HttpClient call is non-blocking, keeping your service threads free for other requests.

IHttpClientFactory

Proper HttpClient lifecycle management with named and typed clients. No socket exhaustion from new HttpClient() misuse.

System.Text.Json

High-performance built-in JSON serialization. Zero external dependencies for deserializing Vedika API responses.

Dependency Injection

ASP.NET Core's built-in DI container wires your Vedika service into controllers and background workers cleanly.

Prerequisites

Step 1: Create the ASP.NET Core Project

# Create ASP.NET Core Web API project dotnet new webapi -n AstrologyService --use-controllers cd AstrologyService # Add Razor Pages (for frontend UI) dotnet add package Microsoft.AspNetCore.Mvc.RazorPages # Run the project dotnet run

Step 2: Configuration Classes

Define strongly-typed options bound from appsettings.json — keeping configuration separate from logic:

// appsettings.json { "VedikaApi": { "BaseUrl": "https://api.vedika.io", "ApiKey": "" // Set via environment variable: VedikaApi__ApiKey }, "Cache": { "BirthChartExpiryMinutes": 1440, // 24 hours — deterministic data "HoroscopeExpiryMinutes": 60 // 1 hour — daily predictions } } // Models/VedikaOptions.cs namespace AstrologyService.Models; public class VedikaOptions { public const string SectionName = "VedikaApi"; public string BaseUrl { get; set; } = string.Empty; public string ApiKey { get; set; } = string.Empty; }

Step 3: Model Classes

Define C# record types for request/response shapes. Records give you value equality and immutability for free:

// Models/AstrologyModels.cs using System.Text.Json.Serialization; namespace AstrologyService.Models; /// Birth data sent to Vedika API public record BirthDetails( [property: JsonPropertyName("datetime")] string Datetime, [property: JsonPropertyName("latitude")] double Latitude, [property: JsonPropertyName("longitude")] double Longitude, [property: JsonPropertyName("timezone")] string Timezone ); /// Query payload to /api/vedika/chat public record AstrologyQuery( [property: JsonPropertyName("question")] string Question, [property: JsonPropertyName("birthDetails")] BirthDetails? BirthDetails = null, [property: JsonPropertyName("system")] string? System = null ); /// Response from Vedika API public record AstrologyResponse { [JsonPropertyName("answer")] public string Answer { get; init; } = string.Empty; [JsonPropertyName("system")] public string System { get; init; } = string.Empty; [JsonPropertyName("birthChart")] public BirthChartData? BirthChart { get; init; } } public record BirthChartData { [JsonPropertyName("ascendant")] public string Ascendant { get; init; } = string.Empty; [JsonPropertyName("currentDasha")] public string CurrentDasha { get; init; } = string.Empty; [JsonPropertyName("planets")] public PlanetData[] Planets { get; init; } = []; } public record PlanetData { [JsonPropertyName("name")] public string Name { get; init; } = string.Empty; [JsonPropertyName("sign")] public string Sign { get; init; } = string.Empty; [JsonPropertyName("house")] public int House { get; init; } [JsonPropertyName("isRetrograde")] public bool IsRetrograde { get; init; } }

Step 4: Typed HttpClient Service

Create a typed HttpClient that encapsulates all Vedika API calls. ASP.NET Core's DI will manage the HttpClient lifecycle correctly:

// Services/VedikaApiService.cs using AstrologyService.Models; using Microsoft.Extensions.Caching.Memory; using Microsoft.Extensions.Options; using System.Net.Http.Json; namespace AstrologyService.Services; public class VedikaApiService { private readonly HttpClient _httpClient; private readonly IMemoryCache _cache; private readonly ILogger<VedikaApiService> _logger; public VedikaApiService( HttpClient httpClient, IMemoryCache cache, ILogger<VedikaApiService> logger) { _httpClient = httpClient; _cache = cache; _logger = logger; } /// Ask any astrology question — AI-powered, chart-verified response public async Task<AstrologyResponse> QueryAsync( AstrologyQuery query, CancellationToken ct = default) { var response = await _httpClient .PostAsJsonAsync("/api/vedika/chat", query, ct); if (!response.IsSuccessStatusCode) { var body = await response.Content.ReadAsStringAsync(ct); _logger.LogError("Vedika API error {Status}: {Body}", response.StatusCode, body); throw new VedikaApiException((int)response.StatusCode, body); } return await response.Content .ReadFromJsonAsync<AstrologyResponse>(ct) ?? throw new InvalidOperationException("Empty response from Vedika API"); } /// Get birth chart — cached for 24h (deterministic) public async Task<AstrologyResponse> GetBirthChartAsync( BirthDetails details, CancellationToken ct = default) { var cacheKey = $"chart:{details.Datetime}:{details.Latitude}:{details.Longitude}"; return await _cache.GetOrCreateAsync(cacheKey, async entry => { entry.AbsoluteExpirationRelativeToNow = TimeSpan.FromHours(24); return await QueryAsync(new AstrologyQuery( "Generate my complete Vedic birth chart with planetary positions, active yogas, and current dasha.", details ), ct); }) ?? throw new InvalidOperationException("Cache returned null"); } /// Get daily horoscope — cached for 1h public async Task<AstrologyResponse> GetDailyHoroscopeAsync( string zodiacSign, BirthDetails? details = null, CancellationToken ct = default) { var cacheKey = $"horoscope:{zodiacSign}:{DateTime.UtcNow:yyyyMMddHH}"; return await _cache.GetOrCreateAsync(cacheKey, async entry => { entry.AbsoluteExpirationRelativeToNow = TimeSpan.FromHours(1); return await QueryAsync(new AstrologyQuery( $"What is today's horoscope for {zodiacSign}? " + "Cover career, love, health, and finance in detail.", details ), ct); }) ?? throw new InvalidOperationException("Cache returned null"); } } // Services/VedikaApiException.cs public class VedikaApiException(int statusCode, string message) : Exception(message) { public int StatusCode { get; } = statusCode; }

Step 5: Program.cs — Registering Services

Wire everything together in Program.cs using the modern minimal hosting model:

// Program.cs using AstrologyService.Models; using AstrologyService.Services; var builder = WebApplication.CreateBuilder(args); // Bind VedikaOptions from configuration builder.Services.Configure<VedikaOptions>( builder.Configuration.GetSection(VedikaOptions.SectionName)); var vedikaOpts = builder.Configuration .GetSection(VedikaOptions.SectionName) .Get<VedikaOptions>()!; // Register typed HttpClient with default headers builder.Services.AddHttpClient<VedikaApiService>(client => { client.BaseAddress = new Uri(vedikaOpts.BaseUrl); client.DefaultRequestHeaders.Add("x-api-key", vedikaOpts.ApiKey); client.Timeout = TimeSpan.FromSeconds(60); }); // Memory cache for birth chart and horoscope caching builder.Services.AddMemoryCache(); // Controllers + Razor Pages builder.Services.AddControllers(); builder.Services.AddRazorPages(); // Register background horoscope service builder.Services.AddHostedService<DailyHoroscopeWorker>(); // Global exception handler middleware builder.Services.AddExceptionHandler<VedikaExceptionHandler>(); builder.Services.AddProblemDetails(); var app = builder.Build(); app.UseExceptionHandler(); app.UseHttpsRedirection(); app.MapControllers(); app.MapRazorPages(); app.Run();

Step 6: API Controller

// Controllers/AstrologyController.cs using AstrologyService.Models; using AstrologyService.Services; using Microsoft.AspNetCore.Mvc; namespace AstrologyService.Controllers; [ApiController] [Route("api/[controller]")] public class AstrologyController(VedikaApiService vedikaService) : ControllerBase { /// POST api/astrology/query — Natural language AI query [HttpPost("query")] public async Task<ActionResult<AstrologyResponse>> Query( [FromBody] AstrologyQuery request, CancellationToken ct) { var result = await vedikaService.QueryAsync(request, ct); return Ok(result); } /// POST api/astrology/birth-chart — Full Vedic birth chart [HttpPost("birth-chart")] public async Task<ActionResult<AstrologyResponse>> BirthChart( [FromBody] BirthDetails details, CancellationToken ct) { var result = await vedikaService.GetBirthChartAsync(details, ct); return Ok(result); } /// GET api/astrology/horoscope/{sign} — Daily horoscope [HttpGet("horoscope/{sign}")] public async Task<ActionResult<AstrologyResponse>> DailyHoroscope( string sign, CancellationToken ct) { var result = await vedikaService.GetDailyHoroscopeAsync(sign, ct: ct); return Ok(result); } }

Ready to Build Your .NET Astrology Service?

Try the FREE Sandbox — 65 mock endpoints, no credit card required. Plans from $12/month.

Explore the Sandbox

Step 7: Global Exception Handler

ASP.NET Core 8's IExceptionHandler interface provides clean centralized error handling that maps domain exceptions to HTTP problem detail responses:

// Middleware/VedikaExceptionHandler.cs using AstrologyService.Services; using Microsoft.AspNetCore.Diagnostics; using Microsoft.AspNetCore.Mvc; public class VedikaExceptionHandler : IExceptionHandler { public async ValueTask<bool> TryHandleAsync( HttpContext context, Exception exception, CancellationToken ct) { if (exception is not VedikaApiException vex) return false; var statusCode = vex.StatusCode switch { 402 => StatusCodes.Status402PaymentRequired, 429 => StatusCodes.Status429TooManyRequests, 401 => StatusCodes.Status401Unauthorized, _ => StatusCodes.Status502BadGateway }; context.Response.StatusCode = statusCode; await context.Response.WriteAsJsonAsync(new ProblemDetails { Status = statusCode, Title = "Astrology API Error", Detail = vex.Message, Type = $"https://vedika.io/errors/{vex.StatusCode}" }, ct); return true; } }

Step 8: Background Worker for Daily Horoscopes

Use a BackgroundService to pre-generate daily horoscopes for all 12 zodiac signs at midnight — so daytime requests are served from cache at near-zero latency:

// Workers/DailyHoroscopeWorker.cs using AstrologyService.Services; public class DailyHoroscopeWorker(IServiceScopeFactory scopeFactory, ILogger<DailyHoroscopeWorker> logger) : BackgroundService { private static readonly string[] ZodiacSigns = [ "Aries", "Taurus", "Gemini", "Cancer", "Leo", "Virgo", "Libra", "Scorpio", "Sagittarius", "Capricorn", "Aquarius", "Pisces" ]; protected override async Task ExecuteAsync(CancellationToken stoppingToken) { using var timer = new PeriodicTimer(TimeSpan.FromHours(24)); // Generate immediately on startup, then every 24 hours await GenerateAllHoroscopesAsync(stoppingToken); while (await timer.WaitForNextTickAsync(stoppingToken)) { await GenerateAllHoroscopesAsync(stoppingToken); } } private async Task GenerateAllHoroscopesAsync(CancellationToken ct) { // Must use IServiceScopeFactory — BackgroundService is singleton, // VedikaApiService is scoped via IHttpClientFactory await using var scope = scopeFactory.CreateAsyncScope(); var service = scope.ServiceProvider.GetRequiredService<VedikaApiService>(); logger.LogInformation("Generating daily horoscopes for all 12 signs..."); var tasks = ZodiacSigns.Select(sign => service.GetDailyHoroscopeAsync(sign, ct: ct)); await Task.WhenAll(tasks); logger.LogInformation("Daily horoscopes cached successfully."); } }

Step 9: Razor Pages Frontend

Add a simple Razor Pages frontend so end users can enter birth details and see their horoscope without needing an API client:

@* Pages/Horoscope.cshtml *@ @page @model AstrologyService.Pages.HoroscopeModel @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers <!DOCTYPE html> <html> <head> <title>Vedic Horoscope — Powered by Vedika AI</title> <link rel="stylesheet" href="/css/site.css"> </head> <body> <h1>Get Your Daily Horoscope</h1> <form method="post"> <label>Zodiac Sign:</label> <select asp-for="ZodiacSign"> <option value="Aries">Aries</option> <option value="Taurus">Taurus</option> <option value="Gemini">Gemini</option> <option value="Cancer">Cancer</option> <option value="Leo">Leo</option> <option value="Virgo">Virgo</option> <option value="Libra">Libra</option> <option value="Scorpio">Scorpio</option> <option value="Sagittarius">Sagittarius</option> <option value="Capricorn">Capricorn</option> <option value="Aquarius">Aquarius</option> <option value="Pisces">Pisces</option> </select> <button type="submit">Get Horoscope</button> </form> @if (Model.Prediction != null) { <div class="prediction-card"> <h2>Today's @Model.ZodiacSign Horoscope</h2> <p>@Model.Prediction</p> <small>Powered by Vedika AI &mdash; Swiss Ephemeris precision</small> </div> } </body> </html>
// Pages/Horoscope.cshtml.cs using AstrologyService.Services; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.RazorPages; public class HoroscopeModel(VedikaApiService vedikaService) : PageModel { [BindProperty] public string ZodiacSign { get; set; } = "Aries"; public string? Prediction { get; private set; } public void OnGet() { } public async Task<IActionResult> OnPostAsync(CancellationToken ct) { var result = await vedikaService.GetDailyHoroscopeAsync(ZodiacSign, ct: ct); Prediction = result.Answer; return Page(); } }

Why Choose Vedika API Over Competitors?

AI Chatbot Included

One natural language endpoint replaces dozens of calculation-specific endpoints. Your C# service stays lean — no complex orchestration needed.

140+ Calculations

From basic birth charts to advanced ashtakavarga, muhurta, compatibility, and numerology — all accessible via the same JSON API.

Clean JSON

Standard camelCase JSON responses that deserialize perfectly into C# records with System.Text.Json — no custom converters required.

MCP Server

The world's first astrology MCP server. Integrate Vedika directly with Semantic Kernel or other AI agent frameworks for .NET.

30 Languages

Hindi, Tamil, Telugu, Bengali, and 26 more. A single .NET service can serve a global multilingual astrology platform.

$12/Month Starting

Wallet-based billing starting at $12/month — a fraction of what enterprise data providers charge for specialized APIs.

Pricing

Vedika API offers transparent wallet-based pricing that scales with your .NET application's usage:

All plans include the full 140+ endpoint catalog, AI chatbot, and 30-language support. View full pricing details.

Conclusion

Integrating Vedika API into a .NET 8 application follows idiomatic C# patterns. The key architectural decisions from this guide:

Next steps:

  1. Get your API key at vedika.io/dashboard
  2. Explore the free sandbox — 65 mock endpoints, no cost
  3. Browse the C#-specific code examples in our API docs
  4. Add Polly retry policies to AddHttpClient for production-grade resilience
  5. Integrate with Semantic Kernel to build an AI-powered .NET astrology agent

About Vedika Intelligence: Vedika is the only B2B astrology API with an AI-powered chatbot engine, serving production applications worldwide. The Vedika Intelligence Engine enables natural language astrology queries with Swiss Ephemeris-verified precision, supporting both Vedic and Western astrology across 30 languages.

Try the #1 Astrology API for .NET Developers

140+ endpoints, Swiss Ephemeris precision, AI chatbot, 30 languages. Free sandbox — no credit card required.

Try Free Sandbox View Documentation