diff --git a/GanjooRazor/Pages/Hashieha.cshtml.cs b/GanjooRazor/Pages/Hashieha.cshtml.cs index fdc00477..03de14b4 100644 --- a/GanjooRazor/Pages/Hashieha.cshtml.cs +++ b/GanjooRazor/Pages/Hashieha.cshtml.cs @@ -3,11 +3,10 @@ using System.Collections.Generic; using System.Linq; using System.Net; using System.Net.Http; -using System.Net.Http.Headers; using System.Threading.Tasks; using DNTPersianUtils.Core; +using GanjooRazor.Utils; using Microsoft.AspNetCore.Mvc; -using Microsoft.Extensions.Caching.Memory; using Microsoft.Extensions.Configuration; using Newtonsoft.Json; using Newtonsoft.Json.Linq; @@ -17,27 +16,19 @@ using RMuseum.Services.Implementation; using RSecurityBackend.Models.Auth.Memory; using RSecurityBackend.Models.Generic; - namespace GanjooRazor.Pages { [IgnoreAntiforgeryToken(Order = 1001)] public class HashiehaModel : LoginPartialEnabledPageModel { - /// - /// memory cache - /// - private readonly IMemoryCache _memoryCache; - + private readonly PoetCacheService _poetCache; /// /// constructor /// - /// - /// - /// - public HashiehaModel(HttpClient httpClient, IMemoryCache memoryCache, IConfiguration configuration) : base(httpClient, configuration) + public HashiehaModel(HttpClient httpClient, IConfiguration configuration, PoetCacheService poetCache) : base(httpClient, configuration) { - _memoryCache = memoryCache; + _poetCache = poetCache; } public List Poets { get; set; } @@ -46,71 +37,18 @@ namespace GanjooRazor.Pages public string PagingToolsHtml { get; set; } public string LastError { get; set; } - private async Task preparePoets() - { - var cacheKey = $"/api/ganjoor/poets"; - if (!_memoryCache.TryGetValue(cacheKey, out List poets)) - { - var response = await _httpClient.GetAsync($"{APIRoot.Url}/api/ganjoor/poets"); - if (!response.IsSuccessStatusCode) - { - LastError = JsonConvert.DeserializeObject(await response.Content.ReadAsStringAsync()); - return false; - } - poets = JArray.Parse(await response.Content.ReadAsStringAsync()).ToObject>(); - if (AggressiveCacheEnabled) - { - _memoryCache.Set(cacheKey, poets, TimeSpan.FromHours(1)); - } - } - - Poets = poets; - return true; - } - - private async Task preparePoet() - { - var cacheKey = $"/api/ganjoor/poet/{PoetId}"; - if (!_memoryCache.TryGetValue(cacheKey, out GanjoorPoetCompleteViewModel poet)) - { - var poetResponse = await _httpClient.GetAsync($"{APIRoot.Url}/api/ganjoor/poet/{PoetId}"); - if (!poetResponse.IsSuccessStatusCode) - { - LastError = JsonConvert.DeserializeObject(await poetResponse.Content.ReadAsStringAsync()); - return false; - } - poet = JObject.Parse(await poetResponse.Content.ReadAsStringAsync()).ToObject(); - if (AggressiveCacheEnabled) - { - _memoryCache.Set(cacheKey, poet, TimeSpan.FromHours(1)); - } - } - - Poet = poet; - return true; - } - - - public List Comments { get; set; } public async Task OnGetPoetInformationAsync(int id) { if (id == 0) - return new OkObjectResult(null); - var cacheKey = $"/api/ganjoor/poet/{id}"; - if (!_memoryCache.TryGetValue(cacheKey, out GanjoorPoetCompleteViewModel poet)) { - var poetResponse = await _httpClient.GetAsync($"{APIRoot.Url}/api/ganjoor/poet/{id}"); - if (!poetResponse.IsSuccessStatusCode) - { - return BadRequest(JsonConvert.DeserializeObject(await poetResponse.Content.ReadAsStringAsync())); - } - poet = JObject.Parse(await poetResponse.Content.ReadAsStringAsync()).ToObject(); - if (AggressiveCacheEnabled) - { - _memoryCache.Set(cacheKey, poet, TimeSpan.FromHours(1)); - } + return new OkObjectResult(null); + } + var (success, poet, error) = await _poetCache.GetPoetAsync(id, AggressiveCacheEnabled); + if (!success) + { + return BadRequest(error); } return new OkObjectResult(poet); } @@ -129,26 +67,35 @@ namespace GanjooRazor.Pages public async Task OnGetAsync() { - if (bool.Parse(Configuration["MaintenanceMode"])) + var maintenanceResult = TryGetMaintenanceModeResult(); + if (maintenanceResult != null) { - return StatusCode(503); + return maintenanceResult; } - LoggedIn = !string.IsNullOrEmpty(Request.Cookies["Token"]); + InitializeCommonPageState(); PoetId = string.IsNullOrEmpty(Request.Query["a"]) ? 0 : int.Parse(Request.Query["a"]); - ViewData["TrackingScript"] = Configuration["TrackingScript"] != null && string.IsNullOrEmpty(Request.Cookies["Token"]) ? Configuration["TrackingScript"].Replace("loggedon", "") : Configuration["TrackingScript"]; - //todo: use html master layout or make it partial // 1. poets - if (false == (await preparePoets())) + var (poetsOk, poets, poetsError) = await _poetCache.GetPoetsAsync(AggressiveCacheEnabled); + if (!poetsOk) + { + LastError = poetsError; return Page(); + } + Poets = poets; if (PoetId != 0) { - if (false == (await preparePoet())) + var (poetOk, poet, poetError) = await _poetCache.GetPoetAsync(PoetId, AggressiveCacheEnabled); + if (!poetOk) + { + LastError = poetError; return Page(); + } + Poet = poet; } // 2. search comments @@ -170,7 +117,7 @@ namespace GanjooRazor.Pages var responseUserProfile = await _httpClient.GetAsync($"{APIRoot.Url}/api/ganjoor/user/profile/{filterUserId}"); if (!responseUserProfile.IsSuccessStatusCode) { - LastError = JsonConvert.DeserializeObject(await responseUserProfile.Content.ReadAsStringAsync()); + LastError = await ReadErrorMessageAsync(responseUserProfile); return Page(); } @@ -180,7 +127,7 @@ namespace GanjooRazor.Pages var responseContributions = await _httpClient.GetAsync($"{APIRoot.Url}/api/contributions/{filterUserId}"); if (!responseContributions.IsSuccessStatusCode) { - LastError = JsonConvert.DeserializeObject(await responseContributions.Content.ReadAsStringAsync()); + LastError = await ReadErrorMessageAsync(responseContributions); return Page(); } @@ -194,31 +141,19 @@ namespace GanjooRazor.Pages if (!string.IsNullOrEmpty(Request.Cookies["Token"])) { - using (HttpClient secureClient = new HttpClient()) - { - secureClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", Request.Cookies["Token"]); - var res = await secureClient.GetAsync($"{APIRoot.Url}/api/users/securableitems"); - if (res.IsSuccessStatusCode) - { - SecurableItem[] secuarbleItems = JsonConvert.DeserializeObject(await res.Content.ReadAsStringAsync()); - var userSecurableItem = secuarbleItems.Where(s => s.ShortName == SecurableItem.UserEntityShortName).FirstOrDefault(); - if (userSecurableItem != null) - { - var administerOperation = userSecurableItem.Operations.Where(o => o.ShortName == SecurableItem.Administer).FirstOrDefault(); - if (administerOperation != null) - { - CanAdministerUsers = administerOperation.Status; - } - } - } - } + // Was previously a hand-rolled HttpClient with the Bearer token set directly from + // the cookie, manually searching /api/users/securableitems for a matching + // securable + operation. GanjoorSessionChecker.IsPermitted already does exactly + // this and (unlike the hand-rolled version) goes through PrepareClient's session + // renewal, so it also correctly handles a token that needs refreshing. + CanAdministerUsers = await GanjoorSessionChecker.IsPermitted(Request, Response, SecurableItem.UserEntityShortName, SecurableItem.Administer); } url += $"&filterUserId={filterUserId}"; } - if(!string.IsNullOrEmpty(Query)) + if (!string.IsNullOrEmpty(Query)) { Query = Query.ApplyCorrectYeKe().Trim(); bool quotes = Query.IndexOf("\"") != -1; @@ -232,7 +167,7 @@ namespace GanjooRazor.Pages var response = await _httpClient.GetAsync(url); if (!response.IsSuccessStatusCode) { - LastError = JsonConvert.DeserializeObject(await response.Content.ReadAsStringAsync()); + LastError = await ReadErrorMessageAsync(response); return Page(); } @@ -253,7 +188,7 @@ namespace GanjooRazor.Pages htmlText = $"
{Environment.NewLine}"; string queryFilterUserId = string.IsNullOrEmpty(filterUserId) ? "" : $"&userid={filterUserId}"; if (!string.IsNullOrEmpty(Query)) - { + { queryFilterUserId += $"&w={WebUtility.UrlEncode(Query)}"; } if (paginationMetadata.currentPage > 3) diff --git a/GanjooRazor/Pages/Photos.cshtml.cs b/GanjooRazor/Pages/Photos.cshtml.cs index ab5157cf..1c48705d 100644 --- a/GanjooRazor/Pages/Photos.cshtml.cs +++ b/GanjooRazor/Pages/Photos.cshtml.cs @@ -1,8 +1,6 @@ using GanjooRazor.Models; using GanjooRazor.Utils; using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.Mvc.ModelBinding; -using Microsoft.AspNetCore.Mvc.ViewFeatures; using Microsoft.Extensions.Configuration; using Newtonsoft.Json; using Newtonsoft.Json.Linq; @@ -10,7 +8,6 @@ using RMuseum.Models.Auth.Memory; using RMuseum.Models.Ganjoor.ViewModels; using System.Collections.Generic; using System.IO; -using System.Net; using System.Net.Http; using System.Text; using System.Threading.Tasks; @@ -37,12 +34,15 @@ namespace GanjooRazor.Pages public bool ModeratePoetPhotos { get; set; } + // Kept local rather than PoetCacheService: unlike every other page that fetches the poet + // list, this one prefixes each poet's ImageUrl with APIRoot.InternetUrl before use, which + // the shared service intentionally doesn't do (no other caller needed it). private async Task> _PreparePoets() { var response = await _httpClient.GetAsync($"{APIRoot.Url}/api/ganjoor/poets"); if (!response.IsSuccessStatusCode) { - LastError = JsonConvert.DeserializeObject(await response.Content.ReadAsStringAsync()); + LastError = await ReadErrorMessageAsync(response); return new List(); } var poets = JArray.Parse(await response.Content.ReadAsStringAsync()).ToObject>(); @@ -56,21 +56,20 @@ namespace GanjooRazor.Pages } public async Task OnGetAsync() { - if (bool.Parse(Configuration["MaintenanceMode"])) + var maintenanceResult = TryGetMaintenanceModeResult(); + if (maintenanceResult != null) { - return StatusCode(503); + return maintenanceResult; } - LoggedIn = !string.IsNullOrEmpty(Request.Cookies["Token"]); - - + InitializeCommonPageState(); if (!string.IsNullOrEmpty(Request.Query["p"])) { var response = await _httpClient.GetAsync($"{APIRoot.Url}/api/ganjoor/poet?url=/{Request.Query["p"]}"); if (!response.IsSuccessStatusCode) { - LastError = JsonConvert.DeserializeObject(await response.Content.ReadAsStringAsync()); + LastError = await ReadErrorMessageAsync(response); return Page(); } Poet = JObject.Parse(await response.Content.ReadAsStringAsync()).ToObject().Poet; @@ -79,7 +78,7 @@ namespace GanjooRazor.Pages var responseLines = await _httpClient.GetAsync($"{APIRoot.Url}/api/poetspecs/poet/{Poet.Id}"); if (!responseLines.IsSuccessStatusCode) { - LastError = JsonConvert.DeserializeObject(await responseLines.Content.ReadAsStringAsync()); + LastError = await ReadErrorMessageAsync(responseLines); return Page(); } SpecLines = JArray.Parse(await responseLines.Content.ReadAsStringAsync()).ToObject>(); @@ -87,7 +86,7 @@ namespace GanjooRazor.Pages var responsePhotos = await _httpClient.GetAsync($"{APIRoot.Url}/api/poetphotos/poet/{Poet.Id}"); if (!responsePhotos.IsSuccessStatusCode) { - LastError = JsonConvert.DeserializeObject(await responsePhotos.Content.ReadAsStringAsync()); + LastError = await ReadErrorMessageAsync(responsePhotos); return Page(); } Photos = JArray.Parse(await responsePhotos.Content.ReadAsStringAsync()).ToObject>(); @@ -114,68 +113,50 @@ namespace GanjooRazor.Pages return Page(); } - public async Task OnPostSuggestAsync(int poetId, string contents) + private IActionResult SpecLineErrorPartial(string error) { - string error = ""; - if (string.IsNullOrEmpty(contents)) - error = "متن خالی است."; - else - using (HttpClient secureClient = new HttpClient()) - { - if (await GanjoorSessionChecker.PrepareClient(secureClient, Request, Response)) - { - var response = await secureClient.PostAsync($"{APIRoot.Url}/api/poetspecs", - new StringContent( - JsonConvert.SerializeObject - ( - new GanjoorPoetSuggestedSpecLineViewModel() - { - PoetId = poetId, - Contents = contents, - } - ), - Encoding.UTF8, "application/json") - ); - if (response.StatusCode == HttpStatusCode.OK) - { - var line = JsonConvert.DeserializeObject(await response.Content.ReadAsStringAsync()); - return new PartialViewResult() - { - ViewName = "_PoetSpecLinePartial", - ViewData = new ViewDataDictionary(new EmptyModelMetadataProvider(), new ModelStateDictionary()) - { - Model = new _PoetSpecLinePartialModel() - { - Line = line - } - } - }; - } - else - { - error = JsonConvert.DeserializeObject(await response.Content.ReadAsStringAsync()); - } - } - else - { - error = "لطفاً از گنجور خارج و مجددا به آن وارد شوید."; - } - } - return new PartialViewResult() + return Partial("_PoetSpecLinePartial", new _PoetSpecLinePartialModel() { - ViewName = "_PoetSpecLinePartial", - ViewData = new ViewDataDictionary(new EmptyModelMetadataProvider(), new ModelStateDictionary()) + Line = new GanjoorPoetSuggestedSpecLineViewModel() { - Model = new _PoetSpecLinePartialModel() - { - Line = new GanjoorPoetSuggestedSpecLineViewModel() - { - Id = 0, - Contents = error - } - } + Id = 0, + Contents = error } - }; + }); + } + + public Task OnPostSuggestAsync(int poetId, string contents) + { + if (string.IsNullOrEmpty(contents)) + { + return Task.FromResult(SpecLineErrorPartial("متن خالی است.")); + } + + return WithSecureClientAsync(async secureClient => + { + var response = await secureClient.PostAsync($"{APIRoot.Url}/api/poetspecs", + new StringContent( + JsonConvert.SerializeObject + ( + new GanjoorPoetSuggestedSpecLineViewModel() + { + PoetId = poetId, + Contents = contents, + } + ), + Encoding.UTF8, "application/json") + ); + if (response.IsSuccessStatusCode) + { + var line = JsonConvert.DeserializeObject(await response.Content.ReadAsStringAsync()); + return Partial("_PoetSpecLinePartial", new _PoetSpecLinePartialModel() + { + Line = line + }); + } + + return SpecLineErrorPartial(await ReadErrorMessageAsync(response)); + }, SpecLineErrorPartial(NotLoggedInMessage)); } public async Task OnPostAsync(PoetPhotoSuggestionUploadModel Upload) @@ -189,6 +170,9 @@ namespace GanjooRazor.Pages if (Upload.Image == null) LastError = "تصویر انتخاب نشده است."; else + // Kept as its own using/PrepareClient block rather than WithSecureClientAsync: this + // handler needs to fall through to OnGetAsync() regardless of outcome (success, + // upload failure, or auth failure), which doesn't fit the early-return helper shape. using (HttpClient secureClient = new HttpClient()) { if (await GanjoorSessionChecker.PrepareClient(secureClient, Request, Response)) @@ -210,7 +194,7 @@ namespace GanjooRazor.Pages HttpResponseMessage response = await secureClient.PostAsync($"{APIRoot.Url}/api/poetphotos", form); if (!response.IsSuccessStatusCode) { - LastError = JsonConvert.DeserializeObject(await response.Content.ReadAsStringAsync()); + LastError = await ReadErrorMessageAsync(response); } else { @@ -222,7 +206,7 @@ namespace GanjooRazor.Pages } else { - LastError = "لطفاً از گنجور خارج و مجددا به آن وارد شوید."; + LastError = NotLoggedInMessage; } } @@ -231,83 +215,55 @@ namespace GanjooRazor.Pages return await OnGetAsync(); } - public async Task OnPutChoosePhotoAsync(int id) + public Task OnPutChoosePhotoAsync(int id) { - using (HttpClient secureClient = new HttpClient()) + return WithSecureClientAsync(async secureClient => { - if (await GanjoorSessionChecker.PrepareClient(secureClient, Request, Response)) + var responsePhoto = await secureClient.GetAsync($"{APIRoot.Url}/api/poetphotos/{id}"); + if (!responsePhoto.IsSuccessStatusCode) { - var responsePhoto = await secureClient.GetAsync($"{APIRoot.Url}/api/poetphotos/{id}"); - if (!responsePhoto.IsSuccessStatusCode) - { - LastError = JsonConvert.DeserializeObject(await responsePhoto.Content.ReadAsStringAsync()); - return new BadRequestObjectResult(LastError); - } - var photo = JsonConvert.DeserializeObject(await responsePhoto.Content.ReadAsStringAsync()); - photo.ChosenOne = true; - var response = await secureClient.PutAsync($"{APIRoot.Url}/api/poetphotos", new StringContent(JsonConvert.SerializeObject(photo), Encoding.UTF8, "application/json")); - if (response.StatusCode != HttpStatusCode.OK) - { - return new BadRequestObjectResult(JsonConvert.DeserializeObject(await response.Content.ReadAsStringAsync())); - } + LastError = await ReadErrorMessageAsync(responsePhoto); + return new BadRequestObjectResult(LastError); } - else + var photo = JsonConvert.DeserializeObject(await responsePhoto.Content.ReadAsStringAsync()); + photo.ChosenOne = true; + var response = await secureClient.PutAsync($"{APIRoot.Url}/api/poetphotos", new StringContent(JsonConvert.SerializeObject(photo), Encoding.UTF8, "application/json")); + if (!response.IsSuccessStatusCode) { - return new BadRequestObjectResult("لطفاً از گنجور خارج و مجددا به آن وارد شوید."); + return new BadRequestObjectResult(await ReadErrorMessageAsync(response)); } - } - - return new OkResult(); + return new OkResult(); + }); } - public async Task OnDeleteAsync(int id) + public Task OnDeleteAsync(int id) { - using (HttpClient secureClient = new HttpClient()) + return WithSecureClientAsync(async secureClient => { - if (await GanjoorSessionChecker.PrepareClient(secureClient, Request, Response)) + var response = await secureClient.DeleteAsync($"{APIRoot.Url}/api/poetphotos/{id}"); + if (!response.IsSuccessStatusCode) { - var response = await secureClient.DeleteAsync($"{APIRoot.Url}/api/poetphotos/{id}"); - - if (response.StatusCode != HttpStatusCode.OK) - { - return new BadRequestObjectResult(JsonConvert.DeserializeObject(await response.Content.ReadAsStringAsync())); - } + return new BadRequestObjectResult(await ReadErrorMessageAsync(response)); } - else - { - return new BadRequestObjectResult("لطفاً از گنجور خارج و مجددا به آن وارد شوید."); - } - } - - return new OkResult(); + return new OkResult(); + }); } - public async Task OnDeleteSpecLineAsync(int id) + public Task OnDeleteSpecLineAsync(int id) { - using (HttpClient secureClient = new HttpClient()) + return WithSecureClientAsync(async secureClient => { - if (await GanjoorSessionChecker.PrepareClient(secureClient, Request, Response)) + var response = await secureClient.DeleteAsync($"{APIRoot.Url}/api/poetspecs/{id}"); + if (!response.IsSuccessStatusCode) { - var response = await secureClient.DeleteAsync($"{APIRoot.Url}/api/poetspecs/{id}"); - - if (response.StatusCode != HttpStatusCode.OK) - { - return new BadRequestObjectResult(JsonConvert.DeserializeObject(await response.Content.ReadAsStringAsync())); - } + return new BadRequestObjectResult(await ReadErrorMessageAsync(response)); } - else - { - return new BadRequestObjectResult("لطفاً از گنجور خارج و مجددا به آن وارد شوید."); - } - } - - return new OkResult(); + return new OkResult(); + }); } - public PhotosModel(HttpClient httpClient, IConfiguration configuration) : base(httpClient, configuration) { - } } } diff --git a/GanjooRazor/Pages/Search.cshtml.cs b/GanjooRazor/Pages/Search.cshtml.cs index 6c271b2f..402db382 100644 --- a/GanjooRazor/Pages/Search.cshtml.cs +++ b/GanjooRazor/Pages/Search.cshtml.cs @@ -6,10 +6,8 @@ using System.Net.Http; using System.Text.RegularExpressions; using System.Threading.Tasks; using DNTPersianUtils.Core; +using GanjooRazor.Utils; using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.Mvc.ModelBinding; -using Microsoft.AspNetCore.Mvc.ViewFeatures; -using Microsoft.Extensions.Caching.Memory; using Microsoft.Extensions.Configuration; using Newtonsoft.Json; using Newtonsoft.Json.Linq; @@ -22,23 +20,14 @@ namespace GanjooRazor.Pages [IgnoreAntiforgeryToken(Order = 1001)] public class SearchModel : LoginPartialEnabledPageModel { - - /// - /// memory cache - /// - private readonly IMemoryCache _memoryCache; - - + private readonly PoetCacheService _poetCache; /// /// constructor /// - /// - /// - /// - public SearchModel(HttpClient httpClient, IMemoryCache memoryCache, IConfiguration configuration) : base(httpClient, configuration) + public SearchModel(HttpClient httpClient, IConfiguration configuration, PoetCacheService poetCache) : base(httpClient, configuration) { - _memoryCache = memoryCache; + _poetCache = poetCache; } public List Poets { get; set; } @@ -63,67 +52,16 @@ namespace GanjooRazor.Pages public string LastError { get; set; } public int[] ExceptPoetId { get; set; } - private async Task preparePoets() - { - var cacheKey = $"/api/ganjoor/poets"; - if (!_memoryCache.TryGetValue(cacheKey, out List poets)) - { - var response = await _httpClient.GetAsync($"{APIRoot.Url}/api/ganjoor/poets"); - if (!response.IsSuccessStatusCode) - { - LastError = JsonConvert.DeserializeObject(await response.Content.ReadAsStringAsync()); - return false; - } - poets = JArray.Parse(await response.Content.ReadAsStringAsync()).ToObject>(); - if (AggressiveCacheEnabled) - { - _memoryCache.Set(cacheKey, poets, TimeSpan.FromHours(1)); - } - } - - Poets = poets; - return true; - } - - private async Task preparePoet() - { - var cacheKey = $"/api/ganjoor/poet/{PoetId}"; - if (!_memoryCache.TryGetValue(cacheKey, out GanjoorPoetCompleteViewModel poet)) - { - var poetResponse = await _httpClient.GetAsync($"{APIRoot.Url}/api/ganjoor/poet/{PoetId}"); - if (!poetResponse.IsSuccessStatusCode) - { - LastError = JsonConvert.DeserializeObject(await poetResponse.Content.ReadAsStringAsync()); - return false; - } - poet = JObject.Parse(await poetResponse.Content.ReadAsStringAsync()).ToObject(); - if (AggressiveCacheEnabled) - { - _memoryCache.Set(cacheKey, poet, TimeSpan.FromHours(1)); - } - } - - Poet = poet; - return true; - } - public async Task OnGetPoetInformationAsync(int id) { if (id == 0) - return new OkObjectResult(null); - var cacheKey = $"/api/ganjoor/poet/{id}"; - if (!_memoryCache.TryGetValue(cacheKey, out GanjoorPoetCompleteViewModel poet)) { - var poetResponse = await _httpClient.GetAsync($"{APIRoot.Url}/api/ganjoor/poet/{id}"); - if (!poetResponse.IsSuccessStatusCode) - { - return BadRequest(JsonConvert.DeserializeObject(await poetResponse.Content.ReadAsStringAsync())); - } - poet = JObject.Parse(await poetResponse.Content.ReadAsStringAsync()).ToObject(); - if (AggressiveCacheEnabled) - { - _memoryCache.Set(cacheKey, poet, TimeSpan.FromHours(1)); - } + return new OkObjectResult(null); + } + var (success, poet, error) = await _poetCache.GetPoetAsync(id, AggressiveCacheEnabled); + if (!success) + { + return BadRequest(error); } return new OkObjectResult(poet); } @@ -148,12 +86,13 @@ namespace GanjooRazor.Pages public async Task OnGetAsync() { - if (bool.Parse(Configuration["MaintenanceMode"])) + var maintenanceResult = TryGetMaintenanceModeResult(); + if (maintenanceResult != null) { - return StatusCode(503); + return maintenanceResult; } - LoggedIn = !string.IsNullOrEmpty(Request.Cookies["Token"]); + InitializeCommonPageState(); Query = Request.Query["s"].ApplyCorrectYeKe().Trim(); ExactSearch = Request.Query["es"] == "1"; @@ -196,7 +135,7 @@ namespace GanjooRazor.Pages var catResponse = await _httpClient.GetAsync($"{APIRoot.Url}/api/ganjoor/cat/{CatId}?poems=false&mainSections=false"); if (!catResponse.IsSuccessStatusCode) { - LastError = JsonConvert.DeserializeObject(await catResponse.Content.ReadAsStringAsync()); + LastError = await ReadErrorMessageAsync(catResponse); return Page(); } else @@ -220,12 +159,15 @@ namespace GanjooRazor.Pages StatsAtTop = !string.IsNullOrEmpty(Request.Query["stats"]); - ViewData["TrackingScript"] = Configuration["TrackingScript"] != null && string.IsNullOrEmpty(Request.Cookies["Token"]) ? Configuration["TrackingScript"].Replace("loggedon", "") : Configuration["TrackingScript"]; - //todo: use html master layout or make it partial // 1. poets - if (false == (await preparePoets())) + var (poetsOk, poets, poetsError) = await _poetCache.GetPoetsAsync(AggressiveCacheEnabled); + if (!poetsOk) + { + LastError = poetsError; return Page(); + } + Poets = poets; var poetName = Poets.SingleOrDefault(p => p.Id == PoetId); if (poetName != null) @@ -254,8 +196,13 @@ namespace GanjooRazor.Pages if (PoetId != 0) { - if (false == (await preparePoet())) + var (poetOk, poet, poetError) = await _poetCache.GetPoetAsync(PoetId, AggressiveCacheEnabled); + if (!poetOk) + { + LastError = poetError; return Page(); + } + Poet = poet; } // 2. search verses @@ -293,7 +240,7 @@ namespace GanjooRazor.Pages if (!searchQueryResponse.IsSuccessStatusCode) { - LastError = JsonConvert.DeserializeObject(await searchQueryResponse.Content.ReadAsStringAsync()); + LastError = await ReadErrorMessageAsync(searchQueryResponse); return Page(); } @@ -436,7 +383,7 @@ namespace GanjooRazor.Pages return htmlText; } - public async Task OnGetWordCountsByPoetAsync(string term, int poetId, int catId, bool blur) + public async Task OnGetWordCountsByPoetAsync(string term, int poetId, int catId, bool blur) { if (term == null) return new BadRequestObjectResult("term is null"); term = term.Replace("\"", ""); @@ -449,7 +396,7 @@ namespace GanjooRazor.Pages if (term == null) return new BadRequestObjectResult("term is empty"); } string url = $"{APIRoot.Url}/api/ganjoor/wordcounts/bycat?term={term}"; - if(poetId != 0) + if (poetId != 0) { url += $"&poetId={poetId}"; } @@ -462,26 +409,19 @@ namespace GanjooRazor.Pages if (!wordCountsResponse.IsSuccessStatusCode) { - return new BadRequestObjectResult(JsonConvert.DeserializeObject(await wordCountsResponse.Content.ReadAsStringAsync())); + return new BadRequestObjectResult(await ReadErrorMessageAsync(wordCountsResponse)); } var wordCounts = JsonConvert.DeserializeObject(await wordCountsResponse.Content.ReadAsStringAsync()); string countStr = wordCountsResponse.Headers.GetValues("items-count").FirstOrDefault(); - return new PartialViewResult() + return Partial("_CategoryWordsCountByCatPartial", new _CategoryWordsCountByCatPartialModel() { - ViewName = "_CategoryWordsCountByCatPartial", - ViewData = new ViewDataDictionary(new EmptyModelMetadataProvider(), new ModelStateDictionary()) - { - Model = new _CategoryWordsCountByCatPartialModel() - { - Term = term, - WordStats = wordCounts, - Whole = catId == 0 && poetId == 0, - TotalCount = string.IsNullOrEmpty(countStr) ? 0 : int.Parse(countStr), - Blur = blur, - } - } - }; + Term = term, + WordStats = wordCounts, + Whole = catId == 0 && poetId == 0, + TotalCount = string.IsNullOrEmpty(countStr) ? 0 : int.Parse(countStr), + Blur = blur, + }); } } diff --git a/GanjooRazor/Pages/Simi.cshtml.cs b/GanjooRazor/Pages/Simi.cshtml.cs index ee43819e..839299dc 100644 --- a/GanjooRazor/Pages/Simi.cshtml.cs +++ b/GanjooRazor/Pages/Simi.cshtml.cs @@ -7,7 +7,6 @@ using System.Threading.Tasks; using DNTPersianUtils.Core; using GanjooRazor.Utils; using Microsoft.AspNetCore.Mvc; -using Microsoft.Extensions.Caching.Memory; using Microsoft.Extensions.Configuration; using Newtonsoft.Json; using Newtonsoft.Json.Linq; @@ -17,28 +16,19 @@ using RMuseum.Services.Implementation; using RMuseum.Utils; using RSecurityBackend.Models.Generic; - namespace GanjooRazor.Pages { [IgnoreAntiforgeryToken(Order = 1001)] public class SimiModel : LoginPartialEnabledPageModel { - /// - /// memory cache - /// - private readonly IMemoryCache _memoryCache; - - + private readonly PoetCacheService _poetCache; /// /// constructor /// - /// - /// - /// - public SimiModel(HttpClient httpClient, IMemoryCache memoryCache, IConfiguration configuration) : base(httpClient, configuration) + public SimiModel(HttpClient httpClient, IConfiguration configuration, PoetCacheService poetCache) : base(httpClient, configuration) { - _memoryCache = memoryCache; + _poetCache = poetCache; } public List Poets { get; set; } @@ -71,58 +61,12 @@ namespace GanjooRazor.Pages /// public bool CanEdit { get; set; } - private async Task preparePoets() - { - var cacheKey = $"/api/ganjoor/poets"; - if (!_memoryCache.TryGetValue(cacheKey, out List poets)) - { - var response = await _httpClient.GetAsync($"{APIRoot.Url}/api/ganjoor/poets"); - if (!response.IsSuccessStatusCode) - { - LastError = JsonConvert.DeserializeObject(await response.Content.ReadAsStringAsync()); - return false; - } - poets = JArray.Parse(await response.Content.ReadAsStringAsync()).ToObject>(); - if (AggressiveCacheEnabled) - { - _memoryCache.Set(cacheKey, poets, TimeSpan.FromHours(1)); - } - } - - Poets = poets; - - await ReadLanguagesAsync(); - return true; - } - - private async Task preparePoet() - { - var cacheKey = $"/api/ganjoor/poet/{PoetId}"; - if (!_memoryCache.TryGetValue(cacheKey, out GanjoorPoetCompleteViewModel poet)) - { - var poetResponse = await _httpClient.GetAsync($"{APIRoot.Url}/api/ganjoor/poet/{PoetId}"); - if (!poetResponse.IsSuccessStatusCode) - { - LastError = JsonConvert.DeserializeObject(await poetResponse.Content.ReadAsStringAsync()); - return false; - } - poet = JObject.Parse(await poetResponse.Content.ReadAsStringAsync()).ToObject(); - if (AggressiveCacheEnabled) - { - _memoryCache.Set(cacheKey, poet, TimeSpan.FromHours(1)); - } - } - - Poet = poet; - return true; - } - private async Task ReadLanguagesAsync() { HttpResponseMessage response = await _httpClient.GetAsync($"{APIRoot.Url}/api/translations/languages"); if (!response.IsSuccessStatusCode) { - LastError = JsonConvert.DeserializeObject(await response.Content.ReadAsStringAsync()); + LastError = await ReadErrorMessageAsync(response); return; } @@ -142,39 +86,33 @@ namespace GanjooRazor.Pages public async Task OnGetPoetInformationAsync(int id) { if (id == 0) - return new OkObjectResult(null); - var cacheKey = $"/api/ganjoor/poet/{id}"; - if (!_memoryCache.TryGetValue(cacheKey, out GanjoorPoetCompleteViewModel poet)) { - var poetResponse = await _httpClient.GetAsync($"{APIRoot.Url}/api/ganjoor/poet/{id}"); - if (!poetResponse.IsSuccessStatusCode) - { - return BadRequest(JsonConvert.DeserializeObject(await poetResponse.Content.ReadAsStringAsync())); - } - poet = JObject.Parse(await poetResponse.Content.ReadAsStringAsync()).ToObject(); - if (AggressiveCacheEnabled) - { - _memoryCache.Set(cacheKey, poet, TimeSpan.FromHours(1)); - } + return new OkObjectResult(null); + } + var (success, poet, error) = await _poetCache.GetPoetAsync(id, AggressiveCacheEnabled); + if (!success) + { + return BadRequest(error); } return new OkObjectResult(poet); } public async Task OnGetAsync() { - if (bool.Parse(Configuration["MaintenanceMode"])) + var maintenanceResult = TryGetMaintenanceModeResult(); + if (maintenanceResult != null) { - return StatusCode(503); + return maintenanceResult; } bool anyParamsGiven = false; - LoggedIn = !string.IsNullOrEmpty(Request.Cookies["Token"]); + InitializeCommonPageState(); CanEdit = Request.Cookies["CanEdit"] == "True"; PoetId = string.IsNullOrEmpty(Request.Query["a"]) ? 0 : int.Parse(Request.Query["a"]); - + CatId = string.IsNullOrEmpty(Request.Query["c"]) ? 0 : int.Parse(Request.Query["c"]); anyParamsGiven |= PoetId != 0; @@ -189,7 +127,7 @@ namespace GanjooRazor.Pages anyParamsGiven |= f != null; Format = GanjoorPoemFormat.Unknown; - if(f != null) + if (f != null) { Format = (GanjoorPoemFormat)int.Parse(f); } @@ -203,28 +141,36 @@ namespace GanjooRazor.Pages Quoted = quotes && Query.Contains(" "); - - ViewData["TrackingScript"] = Configuration["TrackingScript"] != null && string.IsNullOrEmpty(Request.Cookies["Token"]) ? Configuration["TrackingScript"].Replace("loggedon", "") : Configuration["TrackingScript"]; - //todo: use html master layout or make it partial // 1. poets - if (false == (await preparePoets())) + var (poetsOk, poets, poetsError) = await _poetCache.GetPoetsAsync(AggressiveCacheEnabled); + if (!poetsOk) + { + LastError = poetsError; return Page(); + } + Poets = poets; + await ReadLanguagesAsync(); if (PoetId != 0) { - if (false == (await preparePoet())) + var (poetOk, poet, poetError) = await _poetCache.GetPoetAsync(PoetId, AggressiveCacheEnabled); + if (!poetOk) + { + LastError = poetError; return Page(); + } + Poet = poet; } // 2. search verses - + var rhythmResponse = await _httpClient.GetAsync($"{APIRoot.Url}/api/ganjoor/rhythms?sortOnVerseCount=true"); if (!rhythmResponse.IsSuccessStatusCode) { - LastError = JsonConvert.DeserializeObject(await rhythmResponse.Content.ReadAsStringAsync()); + LastError = await ReadErrorMessageAsync(rhythmResponse); return Page(); } @@ -269,7 +215,7 @@ namespace GanjooRazor.Pages CoupletCountsFrom = 0; if (!string.IsNullOrEmpty(Request.Query["c1"])) { - if(int.TryParse(Request.Query["c1"], out int i)) + if (int.TryParse(Request.Query["c1"], out int i)) { CoupletCountsFrom = i; anyParamsGiven = anyParamsGiven || CoupletCountsFrom != 0; @@ -306,14 +252,14 @@ namespace GanjooRazor.Pages title += $"{poetInfo.Nickname} "; } } - if(!string.IsNullOrEmpty(Metre)) + if (!string.IsNullOrEmpty(Metre)) { title += $"با وزن «{Metre}»"; } - if(!string.IsNullOrEmpty(Rhyme)) + if (!string.IsNullOrEmpty(Rhyme)) { - if(!string.IsNullOrEmpty(Metre)) + if (!string.IsNullOrEmpty(Metre)) { title += $" و"; } @@ -325,7 +271,7 @@ namespace GanjooRazor.Pages } - if(Language != "fa-IR") + if (Language != "fa-IR") { var langModel = Languages.Where(l => l.Code == Language).FirstOrDefault(); if (langModel != null) @@ -334,7 +280,7 @@ namespace GanjooRazor.Pages } } - if(Format != GanjoorPoemFormat.Unknown) + if (Format != GanjoorPoemFormat.Unknown) { title += $" در قالب شعری «{GanjoorPoemFormatConvertor.GetString(Format)}»"; } @@ -354,7 +300,7 @@ namespace GanjooRazor.Pages var catResponse = await _httpClient.GetAsync($"{APIRoot.Url}/api/ganjoor/cat/{CatId}?poems=false&mainSections=false"); if (!catResponse.IsSuccessStatusCode) { - LastError = JsonConvert.DeserializeObject(await catResponse.Content.ReadAsStringAsync()); + LastError = await ReadErrorMessageAsync(catResponse); return Page(); } else @@ -362,7 +308,7 @@ namespace GanjooRazor.Pages var cat = JObject.Parse(await catResponse.Content.ReadAsStringAsync()).ToObject(); CatFullUrl = cat.Cat.FullUrl; CatFullTitle = ""; - foreach (var parentCat in cat.Cat.Ancestors) + foreach (var parentCat in cat.Cat.Ancestors) { CatFullTitle += parentCat.Title; CatFullTitle += " »"; @@ -392,7 +338,7 @@ namespace GanjooRazor.Pages string url = $"{APIRoot.Url}/api/ganjoor/poems/similar?PageNumber={pageNumber}&PageSize=20&metre={Metre}&rhyme={Rhyme}&poetId={PoetId}&catId={CatId}&language={Language}&format={(int)Format}&coupletCountsFrom={CoupletCountsFrom}&coupletCountsTo={CoupletCountsTo}"; - if(!string.IsNullOrEmpty(Query)) + if (!string.IsNullOrEmpty(Query)) { url += $"&term={Query}"; } @@ -407,7 +353,7 @@ namespace GanjooRazor.Pages if (!response.IsSuccessStatusCode) { - LastError = JsonConvert.DeserializeObject(await response.Content.ReadAsStringAsync()); + LastError = await ReadErrorMessageAsync(response); return Page(); } @@ -426,7 +372,7 @@ namespace GanjooRazor.Pages { htmlText = $"
{Environment.NewLine}"; string authorParam = PoetId != 0 ? $"&a={PoetId}" : ""; - if(authorParam != "" && CatId != 0) + if (authorParam != "" && CatId != 0) { authorParam += $"&c={CatId}"; } @@ -463,64 +409,55 @@ namespace GanjooRazor.Pages } public string HtmlText { get; set; } - public async Task OnPostSendSectionMetreSuggestionAsync(int poemId, int sectionIndex, string rhythm) + public Task OnPostSendSectionMetreSuggestionAsync(int poemId, int sectionIndex, string rhythm) { - using (HttpClient secureClient = new HttpClient()) + return WithSecureClientAsync(async secureClient => { - if (await GanjoorSessionChecker.PrepareClient(secureClient, Request, Response)) + if (rhythm == "null") + rhythm = ""; + + if (string.IsNullOrEmpty(rhythm)) { - - if (rhythm == "null") - rhythm = ""; - - if(string.IsNullOrEmpty(rhythm)) - { - return new BadRequestObjectResult("وزن انتخاب نشده"); - } - - var sectionResponse = await secureClient.GetAsync($"{APIRoot.Url}/api/ganjoor/sections/{poemId}"); - if (!sectionResponse.IsSuccessStatusCode) - { - return new BadRequestObjectResult(JsonConvert.DeserializeObject(await sectionResponse.Content.ReadAsStringAsync())); - } - var sections = JsonConvert.DeserializeObject(await sectionResponse.Content.ReadAsStringAsync()); - - var section = sections.Where(s => s.Index == sectionIndex).Single(); - - var correctionResponse = await secureClient.GetAsync($"{APIRoot.Url}/api/ganjoor/section/correction/last/{section.Id}"); - if (!correctionResponse.IsSuccessStatusCode) - { - return new BadRequestObjectResult(JsonConvert.DeserializeObject(await correctionResponse.Content.ReadAsStringAsync())); - - } - - if(null != JsonConvert.DeserializeObject(await correctionResponse.Content.ReadAsStringAsync())) - { - return new BadRequestObjectResult("شما پیشتر پیشنهادی تصحیحی برای این قطع ثبت کرده‌اید."); - } - - GanjoorPoemSectionCorrectionViewModel correction = new GanjoorPoemSectionCorrectionViewModel() - { - SectionId = section.Id, - Rhythm = rhythm, - }; - - HttpResponseMessage response = await secureClient.PostAsync( - $"{APIRoot.Url}/api/ganjoor/section/correction", - new StringContent(JsonConvert.SerializeObject(correction), - Encoding.UTF8, - "application/json")); - if (!response.IsSuccessStatusCode) - { - return new BadRequestObjectResult(JsonConvert.DeserializeObject(await response.Content.ReadAsStringAsync())); - } - return new OkObjectResult(true); + return new BadRequestObjectResult("وزن انتخاب نشده"); } - else + + var sectionResponse = await secureClient.GetAsync($"{APIRoot.Url}/api/ganjoor/sections/{poemId}"); + if (!sectionResponse.IsSuccessStatusCode) { - return new BadRequestObjectResult("لطفاً از گنجور خارج و مجددا به آن وارد شوید."); + return new BadRequestObjectResult(await ReadErrorMessageAsync(sectionResponse)); } - } + var sections = JsonConvert.DeserializeObject(await sectionResponse.Content.ReadAsStringAsync()); + + var section = sections.Where(s => s.Index == sectionIndex).Single(); + + var correctionResponse = await secureClient.GetAsync($"{APIRoot.Url}/api/ganjoor/section/correction/last/{section.Id}"); + if (!correctionResponse.IsSuccessStatusCode) + { + return new BadRequestObjectResult(await ReadErrorMessageAsync(correctionResponse)); + } + + if (null != JsonConvert.DeserializeObject(await correctionResponse.Content.ReadAsStringAsync())) + { + return new BadRequestObjectResult("شما پیشتر پیشنهادی تصحیحی برای این قطع ثبت کرده‌اید."); + } + + GanjoorPoemSectionCorrectionViewModel correction = new GanjoorPoemSectionCorrectionViewModel() + { + SectionId = section.Id, + Rhythm = rhythm, + }; + + HttpResponseMessage response = await secureClient.PostAsync( + $"{APIRoot.Url}/api/ganjoor/section/correction", + new StringContent(JsonConvert.SerializeObject(correction), + Encoding.UTF8, + "application/json")); + if (!response.IsSuccessStatusCode) + { + return new BadRequestObjectResult(await ReadErrorMessageAsync(response)); + } + return new OkObjectResult(true); + }); } } diff --git a/GanjooRazor/Pages/Tagged.cshtml.cs b/GanjooRazor/Pages/Tagged.cshtml.cs index 6c479d59..ebeb3b92 100644 --- a/GanjooRazor/Pages/Tagged.cshtml.cs +++ b/GanjooRazor/Pages/Tagged.cshtml.cs @@ -1,7 +1,6 @@ using DNTPersianUtils.Core; +using GanjooRazor.Utils; using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.Mvc.RazorPages; -using Microsoft.Extensions.Caching.Memory; using Microsoft.Extensions.Configuration; using Newtonsoft.Json.Linq; using Newtonsoft.Json; @@ -20,25 +19,16 @@ namespace GanjooRazor.Pages [IgnoreAntiforgeryToken(Order = 1001)] public class TaggedModel : LoginPartialEnabledPageModel { - /// - /// memory cache - /// - private readonly IMemoryCache _memoryCache; - - + private readonly PoetCacheService _poetCache; /// /// constructor /// - /// - /// - /// - public TaggedModel(HttpClient httpClient, IMemoryCache memoryCache, IConfiguration configuration) : base(httpClient, configuration) + public TaggedModel(HttpClient httpClient, IConfiguration configuration, PoetCacheService poetCache) : base(httpClient, configuration) { - _memoryCache = memoryCache; + _poetCache = poetCache; } - public List Poets { get; set; } public int PoetId { get; set; } public GanjoorPoetCompleteViewModel Poet { get; set; } @@ -54,103 +44,59 @@ namespace GanjooRazor.Pages HttpResponseMessage response = await _httpClient.GetAsync($"{APIRoot.Url}/api/translations/languages"); if (!response.IsSuccessStatusCode) { - LastError = JsonConvert.DeserializeObject(await response.Content.ReadAsStringAsync()); + LastError = await ReadErrorMessageAsync(response); return; } Languages = JsonConvert.DeserializeObject(await response.Content.ReadAsStringAsync()); } - private async Task preparePoets() - { - var cacheKey = $"/api/ganjoor/poets"; - if (!_memoryCache.TryGetValue(cacheKey, out List poets)) - { - var response = await _httpClient.GetAsync($"{APIRoot.Url}/api/ganjoor/poets"); - if (!response.IsSuccessStatusCode) - { - LastError = JsonConvert.DeserializeObject(await response.Content.ReadAsStringAsync()); - return false; - } - poets = JArray.Parse(await response.Content.ReadAsStringAsync()).ToObject>(); - if (AggressiveCacheEnabled) - { - _memoryCache.Set(cacheKey, poets, TimeSpan.FromHours(1)); - } - } - - Poets = poets; - - await ReadLanguagesAsync(); - return true; - } - - private async Task preparePoet() - { - var cacheKey = $"/api/ganjoor/poet/{PoetId}"; - if (!_memoryCache.TryGetValue(cacheKey, out GanjoorPoetCompleteViewModel poet)) - { - var poetResponse = await _httpClient.GetAsync($"{APIRoot.Url}/api/ganjoor/poet/{PoetId}"); - if (!poetResponse.IsSuccessStatusCode) - { - LastError = JsonConvert.DeserializeObject(await poetResponse.Content.ReadAsStringAsync()); - return false; - } - poet = JObject.Parse(await poetResponse.Content.ReadAsStringAsync()).ToObject(); - if (AggressiveCacheEnabled) - { - _memoryCache.Set(cacheKey, poet, TimeSpan.FromHours(1)); - } - } - - Poet = poet; - return true; - } - public async Task OnGetPoetInformationAsync(int id) { if (id == 0) - return new OkObjectResult(null); - var cacheKey = $"/api/ganjoor/poet/{id}"; - if (!_memoryCache.TryGetValue(cacheKey, out GanjoorPoetCompleteViewModel poet)) { - var poetResponse = await _httpClient.GetAsync($"{APIRoot.Url}/api/ganjoor/poet/{id}"); - if (!poetResponse.IsSuccessStatusCode) - { - return BadRequest(JsonConvert.DeserializeObject(await poetResponse.Content.ReadAsStringAsync())); - } - poet = JObject.Parse(await poetResponse.Content.ReadAsStringAsync()).ToObject(); - if (AggressiveCacheEnabled) - { - _memoryCache.Set(cacheKey, poet, TimeSpan.FromHours(1)); - } + return new OkObjectResult(null); + } + var (success, poet, error) = await _poetCache.GetPoetAsync(id, AggressiveCacheEnabled); + if (!success) + { + return BadRequest(error); } return new OkObjectResult(poet); } public async Task OnGetAsync() { - if (bool.Parse(Configuration["MaintenanceMode"])) + var maintenanceResult = TryGetMaintenanceModeResult(); + if (maintenanceResult != null) { - return StatusCode(503); + return maintenanceResult; } - LoggedIn = !string.IsNullOrEmpty(Request.Cookies["Token"]); - + InitializeCommonPageState(); PoetId = string.IsNullOrEmpty(Request.Query["a"]) ? 0 : int.Parse(Request.Query["a"]); - ViewData["TrackingScript"] = Configuration["TrackingScript"] != null && string.IsNullOrEmpty(Request.Cookies["Token"]) ? Configuration["TrackingScript"].Replace("loggedon", "") : Configuration["TrackingScript"]; - //todo: use html master layout or make it partial // 1. poets - if (false == (await preparePoets())) + var (poetsOk, poets, poetsError) = await _poetCache.GetPoetsAsync(AggressiveCacheEnabled); + if (!poetsOk) + { + LastError = poetsError; return Page(); + } + Poets = poets; + await ReadLanguagesAsync(); if (PoetId != 0) { - if (false == (await preparePoet())) + var (poetOk, poet, poetError) = await _poetCache.GetPoetAsync(PoetId, AggressiveCacheEnabled); + if (!poetOk) + { + LastError = poetError; return Page(); + } + Poet = poet; } // 2. search verses @@ -160,7 +106,7 @@ namespace GanjooRazor.Pages var rhythmResponse = await _httpClient.GetAsync($"{APIRoot.Url}/api/ganjoor/rhythms?sortOnVerseCount=true"); if (!rhythmResponse.IsSuccessStatusCode) { - LastError = JsonConvert.DeserializeObject(await rhythmResponse.Content.ReadAsStringAsync()); + LastError = await ReadErrorMessageAsync(rhythmResponse); return Page(); } @@ -188,11 +134,11 @@ namespace GanjooRazor.Pages } } var langModel = Languages.Where(l => l.Code == Language).FirstOrDefault(); - if(langModel != null) + if (langModel != null) { title += $"با زبان غالب «{langModel.Name}»"; } - + string url = $"{APIRoot.Url}/api/ganjoor/sections/tagged/language?PageNumber={pageNumber}&PageSize=20&language={Language}&poetId={PoetId}"; @@ -200,7 +146,7 @@ namespace GanjooRazor.Pages if (!response.IsSuccessStatusCode) { - LastError = JsonConvert.DeserializeObject(await response.Content.ReadAsStringAsync()); + LastError = await ReadErrorMessageAsync(response); return Page(); }