.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("x-api-key", 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 — 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:
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 — Swiss 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.
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:
- 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 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:
- 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 — 65 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 Swiss Ephemeris-verified precision, supporting both Vedic and Western astrology across 30 languages.