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("Authorization", $"Bearer {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 — 700+ mock endpoints, no signup 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; XALEN 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.

704 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 native first-party 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 704 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 — 700+ 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 XALEN Ephemeris-verified precision, supporting both Vedic and Western astrology across 30 languages.

Try the #1 Astrology API for .NET Developers

700+ operations, XALEN Ephemeris precision, AI chatbot, 30 languages. Free sandbox — no signup required.

Try Free Sandbox View Documentation