হ্যালো! আমি আপনার “Simple Coding Tutor”। আপনার দেওয়া লেকচার ট্র্যান্সক্রিপ্টটি ASP.NET Core-এ HttpClient (Part 3) (লেকচার ১৬০) নিয়ে আলোচনা করেছে। এটি একটি অত্যন্ত গুরুত্বপূর্ণ এবং প্র্যাকটিক্যাল লেকচার, যেখানে JSON ডেটা রিড করা, Configuration ম্যানেজ করা এবং View-তে ডেটা দেখানোর পুরো সাইকেলটি কমপ্লিট করা হয়েছে।

চলুন, পুরো বিষয়টি সহজভাবে এবং বিস্তারিতভাবে শিখে নেওয়া যাক।

📝 সারসংক্ষেপ (Quick Summary for Revision)

ভবিষ্যতে দ্রুত রিভিশন দেওয়ার জন্য মূল পয়েন্টগুলো নিচে লিস্ট করা হলো:

  • JSON Deserialization: API থেকে আসা JSON String-কে C#-এর Dictionary<string, object>-এ কনভার্ট করতে System.Text.Json.JsonSerializer ব্যবহার করা হয়েছে।
  • Service Interface: Dependency Injection-এর বেস্ট প্র্যাকটিসের জন্য IFinnhubService ইন্টারফেস তৈরি করা হয়েছে।
  • Error Handling: API রেসপন্স খালি থাকলে বা “error” প্রপার্টি থাকলে Exception থ্রো করার লজিক যুক্ত করা হয়েছে।
  • Security & Configuration: API Token সুরক্ষিত রাখতে User Secrets এবং ডিফল্ট Stock Symbol রাখার জন্য appsettings.json ব্যবহার করা হয়েছে।
  • Options Pattern: appsettings.json থেকে ডেটা strongly-typed ক্লাসের মাধ্যমে রিড করার জন্য IOptions<TradingOptions> ব্যবহার করা হয়েছে।
  • Data Mapping & View Model: Dictionary থেকে ডেটাগুলো রিড করে একটি Stock নামের View Model-এ ম্যাপ করা হয়েছে এবং Strongly Typed View (Index.cshtml)-এর মাধ্যমে UI-তে রেন্ডার করা হয়েছে।

🧠 Comprehensive Breakdown

১. JSON String-কে Dictionary-তে কনভার্ট করা [Priority: 10/10]

কেন প্রয়োজন (The “Why”): API থেকে ডেটা সাধারণত JSON string ফরম্যাটে আসে। C# সরাসরি এই string থেকে c (Current Price) বা h (High Price)-এর মতো ভ্যালুগুলো পড়তে পারে না। তাই একে C# অবজেক্টে রূপান্তর (Deserialize) করতে হয়।

লেকচারের পদ্ধতি: লেকচারার System.Text.Json নেমস্পেসের JsonSerializer.Deserialize ব্যবহার করে JSON-কে একটি Dictionary<string, object>-এ রূপান্তর করেছেন।

// Response string-কে Dictionary-তে কনভার্ট করা
Dictionary<string, object>? responseDictionary = JsonSerializer.Deserialize<Dictionary<string, object>>(responseString);
 

২. Service Interface এবং Error Handling [Priority: 9/10]

কেন প্রয়োজন: সরাসরি ক্লাস ব্যবহার না করে Interface ব্যবহার করলে কোড অনেক বেশি loosely coupled হয় এবং ভবিষ্যতে Unit Testing করতে সুবিধা হয়।

  • প্রথমে IFinnhubService নামে একটি Interface তৈরি করা হয়েছে।
  • এরপর FinnhubService ক্লাসে সেটি ইমপ্লিমেন্ট করা হয়েছে।
  • Error Handling: API মাঝে মাঝে error দিতে পারে। ডিকশনারিটি যদি null হয় অথবা এর ভেতরে যদি “error” নামের কোনো key থাকে, তবে InvalidOperationException থ্রো করার ব্যবস্থা করা হয়েছে।
if (responseDictionary == null)
    throw new InvalidOperationException("No response from server");
 
if (responseDictionary.ContainsKey("error"))
    throw new InvalidOperationException(responseDictionary["error"].ToString());
 

৩. User Secrets এবং AppSettings কনফিগারেশন [Priority: 10/10]

কেন প্রয়োজন: API Token একটি sensitive ডেটা, এটি সোর্স কোডে রাখা যাবে না। তাই এটি User Secrets-এ রাখা হয়েছে। অন্যদিকে Stock Symbol (যেমন: MSFT) একটি সাধারণ ডেটা, তাই এটি appsettings.json-এ রাখা হয়েছে।

  • User Secrets Setup (Terminal / VS Code):
# Initialize
dotnet user-secrets init
 
# Set Token
dotnet user-secrets set "FinnhubToken" "আপনার_টোকেন_এখানে"
 
  • AppSettings Setup (appsettings.json):
{
  "TradingOptions": {
    "DefaultStockSymbol": "MSFT"
  }
}
 

৪. Options Pattern দিয়ে Data Read করা [Priority: 8/10]

appsettings.json-এর “TradingOptions” সেকশনটি রিড করার জন্য একটি C# ক্লাস তৈরি করা হয়েছে।

public class TradingOptions
{
    public string DefaultStockSymbol { get; set; }
}
 

এরপর HomeController-এ IOptions<TradingOptions> ইনজেক্ট করে ভ্যালুটি রিড করা হয়েছে।

৫. View Model তৈরি এবং Data Mapping [Priority: 9/10]

কেন প্রয়োজন: Controller থেকে View-তে অর্গানাইজড ডেটা পাঠানোর জন্য একটি কাস্টম Model বা View Model লাগে।

  • Models ফোল্ডারে Stock.cs ক্লাস তৈরি করা হয়েছে।
  • Dictionary থেকে ডেটা নিয়ে Stock অবজেক্টে সেট করা হয়েছে। যেহেতু ডিকশনারির ভ্যালু ছিল object টাইপের, তাই ডিরেক্ট double-এ কনভার্ট করা যায় না। আগে ToString() করে তারপর Convert.ToDouble() করতে হয়েছে।
Stock stock = new Stock()
{
    StockSymbol = tradingOptions.DefaultStockSymbol,
    // Object -> String -> Double কনভারশন
    CurrentPrice = Convert.ToDouble(responseDictionary["c"].ToString()), 
    HighestPrice = Convert.ToDouble(responseDictionary["h"].ToString()),
    // ... অন্যান্য প্রপার্টি
};
 
return View(stock); // Model-টি View-তে পাঠানো হলো
 

৬. Strongly Typed View দিয়ে UI রেন্ডার করা [Priority: 8/10]

View (Index.cshtml)-এ সবার উপরে @model StocksApp.Models.Stock ডিক্লেয়ার করে View-টিকে strongly-typed করা হয়েছে। এর ফলে HTML-এর ভেতর সরাসরি @Model.CurrentPrice বা @Model.StockSymbol লিখে ভ্যালুগুলো প্রিন্ট করা যায়।


💡 Best Practices & .NET 10 Context (The “Smarter” Way)

লেকচারে Dictionary ব্যবহার করে ম্যানুয়ালি ToString() এবং Convert.ToDouble() করার যে পদ্ধতি দেখানো হয়েছে, সেটি অনেক পুরনো, ঝামেলার এবং Error-prone পদ্ধতি। আধুনিক .NET-এ (বিশেষ করে .NET 8, 9, এবং 10) এইভাবে ম্যানুয়ালি ম্যাপিং করা হয় না।

Updated & Smarter Approach (.NET 10): Dictionary-এর বদলে সরাসরি JSON-এর স্ট্রাকচার অনুযায়ী একটি C# ক্লাস তৈরি করতে হয় এবং JsonPropertyName ব্যবহার করে ম্যাপ করতে হয়।

1. Create a Response Model (No Dictionary needed):

using System.Text.Json.Serialization;
 
public class FinnhubQuoteResponse
{
    [JsonPropertyName("c")]
    public double CurrentPrice { get; set; }
 
    [JsonPropertyName("h")]
    public double HighestPrice { get; set; }
 
    [JsonPropertyName("l")]
    public double LowestPrice { get; set; }
 
    [JsonPropertyName("o")]
    public double OpenPrice { get; set; }
}
 

2. Modern HttpClient Fetch (in your Service): .NET 10-এ GetFromJsonAsync<T> ব্যবহার করলে আলাদা করে string read বা manual deserialization কিছুই করতে হয় না। এক লাইনেই সব হয়ে যায়!

public async Task<FinnhubQuoteResponse?> GetStockPriceQuoteAsync(string symbol)
{
    string token = _configuration["FinnhubToken"];
    string url = $"https://finnhub.io/api/v1/quote?symbol={symbol}&token={token}";
 
    // এক লাইনে রিকোয়েস্ট পাঠানো এবং JSON থেকে C# Object-এ কনভার্ট করা
    var response = await _httpClient.GetFromJsonAsync<FinnhubQuoteResponse>(url);
    
    return response;
}
 

কেন এটি Best Practice?

  • Type Safety: কোনো ToString() বা ম্যানুয়াল কনভারশন নেই। ভুল হওয়ার কোনো সুযোগ নেই।
  • Performance: System.Text.Json ডিকশনারি তৈরির চেয়ে strongly-typed অবজেক্ট তৈরি করতে অনেক বেশি ফাস্ট কাজ করে।
  • Clean Code: কোডের পরিমাণ অর্ধেকের নিচে নেমে আসে এবং বুঝতে অনেক সহজ হয়।