.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
- .NET 8 SDK (download from dot.net)
- Visual Studio 2022, VS Code with C# Dev Kit, or JetBrains Rider
- Vedika API key — get yours here
- Basic familiarity with C# and ASP.NET Core
Step 1: Create the ASP.NET Core Project
dotnet new webapi -n AstrologyService --use-controllers
cd AstrologyService
dotnet add package Microsoft.AspNetCore.Mvc.RazorPages
dotnet run
Step 2: Configuration Classes
Define strongly-typed options bound from appsettings.json — keeping configuration separate from logic:
{
"VedikaApi": {
"BaseUrl": "https://api.vedika.io",
"ApiKey": ""
},
"Cache": {
"BirthChartExpiryMinutes": 1440,
"HoroscopeExpiryMinutes": 60
}
}
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:
using System.Text.Json.Serialization;
namespace AstrologyService.Models;
public record BirthDetails(
[property: JsonPropertyName("datetime")] string Datetime,
[property: JsonPropertyName("latitude")] double Latitude,
[property: JsonPropertyName("longitude")] double Longitude,
[property: JsonPropertyName("timezone")] string Timezone
);
public record AstrologyQuery(
[property: JsonPropertyName("question")] string Question,
[property: JsonPropertyName("birthDetails")] BirthDetails? BirthDetails = null,
[property: JsonPropertyName("system")] string? System = null
);
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:
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;
}
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");
}
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");
}
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");
}
}
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:
using AstrologyService.Models;
using AstrologyService.Services;
var builder = WebApplication.CreateBuilder(args);
builder.Services.Configure<VedikaOptions>(
builder.Configuration.GetSection(VedikaOptions.SectionName));
var vedikaOpts = builder.Configuration
.GetSection(VedikaOptions.SectionName)
.Get<VedikaOptions>()!;
builder.Services.AddHttpClient<VedikaApiService>(client =>
{
client.BaseAddress = new Uri(vedikaOpts.BaseUrl);
client.DefaultRequestHeaders.Add("Authorization", $"Bearer {vedikaOpts.ApiKey}");
client.Timeout = TimeSpan.FromSeconds(60);
});
builder.Services.AddMemoryCache();
builder.Services.AddControllers();
builder.Services.AddRazorPages();
builder.Services.AddHostedService<DailyHoroscopeWorker>();
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
using AstrologyService.Models;
using AstrologyService.Services;
using Microsoft.AspNetCore.Mvc;
namespace AstrologyService.Controllers;
[ApiController]
[Route("api/[controller]")]
public class AstrologyController(VedikaApiService vedikaService)
: ControllerBase
{
[HttpPost("query")]
public async Task<ActionResult<AstrologyResponse>> Query(
[FromBody] AstrologyQuery request,
CancellationToken ct)
{
var result = await vedikaService.QueryAsync(request, ct);
return Ok(result);
}
[HttpPost("birth-chart")]
public async Task<ActionResult<AstrologyResponse>> BirthChart(
[FromBody] BirthDetails details,
CancellationToken ct)
{
var result = await vedikaService.GetBirthChartAsync(details, ct);
return Ok(result);
}
[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:
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:
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));
await GenerateAllHoroscopesAsync(stoppingToken);
while (await timer.WaitForNextTickAsync(stoppingToken))
{
await GenerateAllHoroscopesAsync(stoppingToken);
}
}
private async Task GenerateAllHoroscopesAsync(CancellationToken ct)
{
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:
@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 — XALEN Ephemeris precision</small>
</div>
}
</body>
</html>
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:
- Starter: $12/month — ideal for hobby projects and MVPs
- Professional: $60/month — for production .NET SaaS
- Business: $120/month — for enterprise ASP.NET Core services
- Enterprise: $240/month — top-up credits, dedicated support, SLA
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:
- IHttpClientFactory with typed clients — correct HttpClient lifecycle, no socket exhaustion
- IMemoryCache with GetOrCreateAsync — birth chart caching that eliminates 90%+ of repeat API calls in real applications
- BackgroundService + PeriodicTimer — daily pre-generation of all 12 zodiac horoscopes so users see zero-latency cached responses
- IExceptionHandler — centralized mapping of VedikaApiException to HTTP problem details (402, 429, 502)
- Record types with JsonPropertyName — immutable, cleanly serialized models that match Vedika API's JSON contract
- IServiceScopeFactory in BackgroundService — correctly resolves scoped services inside singleton-lifetime hosted services
Next steps:
- Get your API key at vedika.io/dashboard
- Explore the free sandbox — 700+ mock endpoints, no cost
- Browse the C#-specific code examples in our API docs
- Add Polly retry policies to
AddHttpClient for production-grade resilience
- 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.