public async Task <IActionResult> GetRecs([FromBody] AnimeRecsInputJson input, [FromServices] IOptionsSnapshot <Config.RecommendationsConfig> recConfig, [FromServices] IMyAnimeListApiFactory malApiFactory, [FromServices] IAnimeRecsClientFactory recClientFactory, [FromServices] IAnimeRecsDbConnectionFactory dbConnFactory, [FromServices] IRazorViewEngine viewEngine, [FromServices] ITempDataProvider tempProvider) { if (!ModelState.IsValid) { AjaxError error = new AjaxError(ModelState); _logger.LogDebug("Invalid input received for GetRecs: {0}", error.Message); return(BadRequest(error)); } if (input.RecSourceName == null) { input.RecSourceName = recConfig.Value.DefaultRecSource; } try { MalUserLookupResults userLookup = await GetUserLookupAsync(input, malApiFactory).ConfigureAwait(false); Dictionary <int, MalListEntry> animeList = new Dictionary <int, MalListEntry>(); foreach (MyAnimeListEntry listEntry in userLookup.AnimeList) { animeList[listEntry.AnimeInfo.AnimeId] = new AnimeRecs.RecEngine.MAL.MalListEntry((byte?)listEntry.Score, listEntry.Status, (short)listEntry.NumEpisodesWatched); } Dictionary <int, MalListEntry> animeWithheld = WithholdAnime(input, animeList); MalRecResults <IEnumerable <IRecommendation> > recResults = await GetRecommendationsAsync(input, recConfig.Value, animeList, animeWithheld, recClientFactory).ConfigureAwait(false); GetRecsViewModel viewModel = new GetRecsViewModel( results: recResults, userId: userLookup.UserId, userName: userLookup.CanonicalUserName, userLookup: userLookup, userAnimeList: animeList, maximumRecommendationsToReturn: recConfig.Value.MaximumRecommendationsToReturn, maximumRecommendersToReturn: recConfig.Value.MaximumRecommendersToReturn, animeWithheld: animeWithheld, dbConnectionFactory: dbConnFactory ); RecResultsAsHtmlJson resultsJson = await GetResultHtmlAsync(viewModel, input, viewEngine, tempProvider).ConfigureAwait(false); return(Ok(resultsJson)); } catch (ShortCircuitException ex) { return(ex.Result); } }
private static UpdatePropertyResultViewModel createResultForConversionFailure( UpdatePropertyModel <TEntity> updatePropertyModel, Exception ex) { var message = ex.Message; var accessor = PropertyUtility.FindPropertyByName <TEntity>(updatePropertyModel.PropertyName); var propertyName = LocalizationManager.GetHeader(accessor.InnerProperty); var error = new AjaxError { field = propertyName, message = message }; var updatePropertyResultViewModel = new UpdatePropertyResultViewModel { Success = false, }; updatePropertyResultViewModel.Errors.Add(error); return(updatePropertyResultViewModel); }
protected async Task <JsonResult> IfModelStateValidAjaxAsync(Func <Task <object> > func) { object data; if (ModelState.IsValid) { try { data = await func(); } catch (Exception ex) { data = ex; } } else { data = new AjaxError(ViewData); } return(Json(data)); }
private async Task <MalUserLookupResults> GetUserLookupAsync(AnimeRecsInputJson input, IMyAnimeListApiFactory malApiFactory) { using (IMyAnimeListApi malApi = malApiFactory.GetMalApi()) { _logger.LogInformation("Getting MAL list for user {0}.", input.MalName); MalUserLookupResults userLookup; try { userLookup = await malApi.GetAnimeListForUserAsync(input.MalName).ConfigureAwait(false); _logger.LogInformation("Got MAL list for user {0}.", input.MalName); return(userLookup); } catch (MalUserNotFoundException) { _logger.LogInformation("User {0} not found.", input.MalName); AjaxError error = new AjaxError(AjaxError.NoSuchMALUser, "No such MAL user."); JsonResult result = Json(error); result.StatusCode = 404; throw new ShortCircuitException(result); } } }
private async Task <MalRecResults <IEnumerable <IRecommendation> > > GetRecommendationsAsync(AnimeRecsInputJson input, Config.RecommendationsConfig recConfig, Dictionary <int, MalListEntry> animeList, Dictionary <int, MalListEntry> animeWithheld, IAnimeRecsClientFactory recClientFactory) { int numRecsToTryToGet = recConfig.MaximumRecommendationsToReturn; if (animeWithheld.Count > 0) { // Get rating prediction information about all anime if in debug mode and withholding anime. // For all currently implemented algorithms, this does not cause a performance problem. numRecsToTryToGet = 100000; } using (AnimeRecsClient recClient = recClientFactory.GetClient(input.RecSourceName)) { MalRecResults <IEnumerable <IRecommendation> > recResults; try { if (input.GoodPercentile != null) { decimal targetFraction = input.GoodPercentile.Value / 100; _logger.LogInformation("Querying rec source {0} for {1} recommendations for {2} using target of top {3}%.", input.RecSourceName, numRecsToTryToGet, input.MalName, targetFraction); recResults = await recClient.GetMalRecommendationsWithFractionTargetAsync(animeList, input.RecSourceName, numRecsToTryToGet, targetFraction, TimeSpan.FromMilliseconds(recConfig.TimeoutMilliseconds), CancellationToken.None).ConfigureAwait(false); } else if (input.GoodCutoff != null) { _logger.LogInformation("Querying rec source {0} for {1} recommendations for {2} using target of {3}.", input.RecSourceName, numRecsToTryToGet, input.MalName, input.GoodCutoff.Value); recResults = await recClient.GetMalRecommendationsAsync(animeList, input.RecSourceName, numRecsToTryToGet, input.GoodCutoff.Value, TimeSpan.FromMilliseconds(recConfig.TimeoutMilliseconds), CancellationToken.None).ConfigureAwait(false); } else { decimal targetFraction = recConfig.DefaultTargetPercentile / 100; _logger.LogInformation("Querying rec source {0} for {1} recommendations for {2} using default target of top {3}%.", input.RecSourceName, numRecsToTryToGet, input.MalName, targetFraction); recResults = await recClient.GetMalRecommendationsWithFractionTargetAsync(animeList, input.RecSourceName, numRecsToTryToGet, targetFraction, TimeSpan.FromMilliseconds(recConfig.TimeoutMilliseconds), CancellationToken.None) .ConfigureAwait(false); } } catch (AnimeRecs.RecService.DTO.RecServiceErrorException ex) { if (ex.Error.ErrorCode == AnimeRecs.RecService.DTO.ErrorCodes.Maintenance) { _logger.LogInformation("Could not service recommendation request for {0}. The rec service is currently undergoing maintenance.", input.MalName); AjaxError error = new AjaxError(AjaxError.InternalError, "The site is currently undergoing scheduled maintenance. Check back in a few minutes."); JsonResult result = Json(error); result.StatusCode = 500; throw new ShortCircuitException(result); } else { throw; } } _logger.LogInformation("Got results from rec service for {0}.", input.MalName); return(recResults); } }
private IActionResult ApiError(int statusCode, Exception ex) { AjaxError error = new AjaxError(AjaxError.InternalError, "Sorry, something went wrong when processing your request."); return(StatusCode(statusCode, error)); }
public static AjaxContinuation AddError(this AjaxContinuation ajaxContinuation, AjaxError ajaxError) { if (ajaxError == null) { return(ajaxContinuation); } ajaxContinuation.Errors.Add(ajaxError); return(ajaxContinuation); }
private MalUserLookupResults GetUserLookup(AnimeRecsInputJson input) { using (IMyAnimeListApi malApi = _malApiFactory.GetMalApi()) { Logging.Log.InfoFormat("Getting MAL list for user {0}.", input.MalName); MalUserLookupResults userLookup; try { userLookup = malApi.GetAnimeListForUser(input.MalName); Logging.Log.InfoFormat("Got MAL list for user {0}.", input.MalName); return userLookup; } catch (MalUserNotFoundException) { Logging.Log.InfoFormat("User {0} not found.", input.MalName); AjaxError error = new AjaxError(AjaxError.NoSuchMALUser, "No such MAL user."); Response response = Response.AsJson(error, HttpStatusCode.BadRequest); throw new ShortCircuitException(response); } } }
private object GetRecs(dynamic arg) { Logging.Log.Info("Started processing GetRecs request."); AnimeRecsInputJson input; try { input = this.BindAndValidate<AnimeRecsInputJson>(); } catch (JsonSerializationException ex) { AjaxError error = new AjaxError(AjaxError.InvalidInput, ex.Message); return Response.AsJson(error, HttpStatusCode.BadRequest); } if (!ModelValidationResult.IsValid) { string errorString = ModelBindingHelpers.ConstructErrorString(ModelValidationResult.Errors); AjaxError error = new AjaxError(AjaxError.InvalidInput, errorString); return Response.AsJson(error, HttpStatusCode.BadRequest); } try { return DoGetRecs(input); } catch (ShortCircuitException earlyResponse) { return earlyResponse.Response; } }
private MalRecResults<IEnumerable<IRecommendation>> GetRecommendations(AnimeRecsInputJson input, Dictionary<int, MalListEntry> animeList, Dictionary<int, MalListEntry> animeWithheld) { int numRecsToTryToGet = _config.MaximumRecommendationsToReturn; if (animeWithheld.Count > 0) { // Get rating prediction information about all anime if in debug mode and withholding anime. // For all currently implemented algorithms, this does not cause a performance problem. numRecsToTryToGet = 100000; } using (AnimeRecsClient recClient = _recClientFactory.GetClient(input.RecSourceName)) { MalRecResults<IEnumerable<IRecommendation>> recResults; try { if (input.GoodPercentile != null) { Logging.Log.InfoFormat("Querying rec source {0} for {1} recommendations for {2} using target of top {3}%.", input.RecSourceName, numRecsToTryToGet, input.MalName, input.GoodPercentile.Value); recResults = recClient.GetMalRecommendationsWithPercentileTarget(animeList, input.RecSourceName, numRecsToTryToGet, input.GoodPercentile.Value); } else if (input.GoodCutoff != null) { Logging.Log.InfoFormat("Querying rec source {0} for {1} recommendations for {2} using target of {3}.", input.RecSourceName, numRecsToTryToGet, input.MalName, input.GoodCutoff.Value); recResults = recClient.GetMalRecommendations(animeList, input.RecSourceName, numRecsToTryToGet, input.GoodCutoff.Value); } else { Logging.Log.InfoFormat("Querying rec source {0} for {1} recommendations for {2} using default target of top {3}%.", input.RecSourceName, numRecsToTryToGet, input.MalName, AppGlobals.Config.DefaultTargetPercentile); recResults = recClient.GetMalRecommendationsWithPercentileTarget(animeList, input.RecSourceName, numRecsToTryToGet, AppGlobals.Config.DefaultTargetPercentile); } } catch (AnimeRecs.RecService.DTO.RecServiceErrorException ex) { if (ex.Error.ErrorCode == AnimeRecs.RecService.DTO.ErrorCodes.Maintenance) { Logging.Log.InfoFormat("Could not service recommendation request for {0}. The rec service is currently undergoing maintenance.", input.MalName); AjaxError error = new AjaxError(AjaxError.InternalError, "The site is currently undergoing scheduled maintenance. Check back in a few minutes."); Response response = Response.AsJson(error, HttpStatusCode.InternalServerError); throw new ShortCircuitException(response); } else { throw; } } Logging.Log.InfoFormat("Got results from rec service for {0}.", input.MalName); return recResults; } }