From bff9477c313ae939998773a12d3ff58ccaa3ba49 Mon Sep 17 00:00:00 2001 From: Bjarke Berg Date: Tue, 19 May 2020 14:02:12 +0200 Subject: [PATCH] https://dev.azure.com/umbraco/D-Team%20Tracker/_workitems/edit/6586 - Migrated ExamineManagementController --- .../ExamineManagementController.cs | 85 +++++++++++-------- .../Exceptions/HttpResponseException.cs | 18 ++++ .../Extensions/ActionResultExtensions.cs | 20 +++++ .../Extensions/LinkGeneratorExtensions.cs | 2 +- .../Editors/BackOfficeServerVariables.cs | 9 +- src/Umbraco.Web/Umbraco.Web.csproj | 1 - 6 files changed, 92 insertions(+), 43 deletions(-) rename src/{Umbraco.Web/Editors => Umbraco.Web.BackOffice/Controllers}/ExamineManagementController.cs (73%) create mode 100644 src/Umbraco.Web.Common/Extensions/ActionResultExtensions.cs diff --git a/src/Umbraco.Web/Editors/ExamineManagementController.cs b/src/Umbraco.Web.BackOffice/Controllers/ExamineManagementController.cs similarity index 73% rename from src/Umbraco.Web/Editors/ExamineManagementController.cs rename to src/Umbraco.Web.BackOffice/Controllers/ExamineManagementController.cs index bc8590b437..f61b463346 100644 --- a/src/Umbraco.Web/Editors/ExamineManagementController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/ExamineManagementController.cs @@ -3,15 +3,19 @@ using System.Collections.Generic; using System.Linq; using System.Net; using System.Net.Http; -using System.Web.Http; using Examine; +using Microsoft.AspNetCore.Http.Features; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.Infrastructure; using Umbraco.Core; using Umbraco.Core.Cache; using Umbraco.Core.IO; using Umbraco.Core.Logging; using Umbraco.Examine; +using Umbraco.Extensions; +using Umbraco.Web.Common.Attributes; +using Umbraco.Web.Common.Exceptions; using Umbraco.Web.Models.ContentEditing; -using Umbraco.Web.Mvc; using Umbraco.Web.Search; using SearchResult = Umbraco.Web.Models.ContentEditing.SearchResult; @@ -67,10 +71,10 @@ namespace Umbraco.Web.Editors return SearchResults.Empty(); var msg = ValidateSearcher(searcherName, out var searcher); - if (!msg.IsSuccessStatusCode) + if (!msg.IsSuccessStatusCode()) throw new HttpResponseException(msg); - // NativeQuery will work for a single word/phrase too (but depends on the implementation) the lucene one will work. + // NativeQuery will work for a single word/phrase too (but depends on the implementation) the lucene one will work. var results = searcher.CreateQuery().NativeQuery(query).Execute(maxResults: pageSize * (pageIndex + 1)); var pagedResults = results.Skip(pageIndex * pageSize); @@ -99,18 +103,19 @@ namespace Umbraco.Web.Editors /// This is kind of rudimentary since there's no way we can know that the index has rebuilt, we /// have a listener for the index op complete so we'll just check if that key is no longer there in the runtime cache /// - public ExamineIndexModel PostCheckRebuildIndex(string indexName) + public ActionResult PostCheckRebuildIndex(string indexName) { var validate = ValidateIndex(indexName, out var index); - if (!validate.IsSuccessStatusCode) + + if (!validate.IsSuccessStatusCode()) throw new HttpResponseException(validate); validate = ValidatePopulator(index); - if (!validate.IsSuccessStatusCode) + if (!validate.IsSuccessStatusCode()) throw new HttpResponseException(validate); var cacheKey = "temp_indexing_op_" + indexName; - var found = AppCaches.RuntimeCache.Get(cacheKey); + var found = _runtimeCache.Get(cacheKey); //if its still there then it's not done return found != null @@ -124,15 +129,15 @@ namespace Umbraco.Web.Editors /// /// /// - public HttpResponseMessage PostRebuildIndex(string indexName) + public IActionResult PostRebuildIndex(string indexName) { var validate = ValidateIndex(indexName, out var index); - if (!validate.IsSuccessStatusCode) - return validate; + if (!validate.IsSuccessStatusCode()) + throw new HttpResponseException(validate); validate = ValidatePopulator(index); - if (!validate.IsSuccessStatusCode) - return validate; + if (!validate.IsSuccessStatusCode()) + throw new HttpResponseException(validate); _logger.Info("Rebuilding index '{IndexName}'", indexName); @@ -146,7 +151,7 @@ namespace Umbraco.Web.Editors { var cacheKey = "temp_indexing_op_" + index.Name; //put temp val in cache which is used as a rudimentary way to know when the indexing is done - AppCaches.RuntimeCache.Insert(cacheKey, () => "tempValue", TimeSpan.FromMinutes(5)); + _runtimeCache.Insert(cacheKey, () => "tempValue", TimeSpan.FromMinutes(5)); _indexRebuilder.RebuildIndex(indexName); @@ -154,18 +159,16 @@ namespace Umbraco.Web.Editors //foreach (var populator in _populators.Where(x => x.IsRegistered(indexName))) // populator.Populate(index); - return Request.CreateResponse(HttpStatusCode.OK); + return new OkResult(); } catch (Exception ex) { //ensure it's not listening index.IndexOperationComplete -= Indexer_IndexOperationComplete; - Logger.Error(ex, "An error occurred rebuilding index"); - var response = Request.CreateResponse(HttpStatusCode.Conflict); - response.Content = - new - StringContent($"The index could not be rebuilt at this time, most likely there is another thread currently writing to the index. Error: {ex}"); - response.ReasonPhrase = "Could Not Rebuild"; + _logger.Error(ex, "An error occurred rebuilding index"); + var response = new ConflictObjectResult("The index could not be rebuilt at this time, most likely there is another thread currently writing to the index. Error: {ex}"); + + SetReasonPhrase(response, "Could Not Rebuild"); return response; } } @@ -197,53 +200,61 @@ namespace Umbraco.Web.Editors return indexerModel; } - private HttpResponseMessage ValidateSearcher(string searcherName, out ISearcher searcher) + private ActionResult ValidateSearcher(string searcherName, out ISearcher searcher) { //try to get the searcher from the indexes if (_examineManager.TryGetIndex(searcherName, out var index)) { searcher = index.GetSearcher(); - return Request.CreateResponse(HttpStatusCode.OK); + return new OkResult(); } //if we didn't find anything try to find it by an explicitly declared searcher if (_examineManager.TryGetSearcher(searcherName, out searcher)) - return Request.CreateResponse(HttpStatusCode.OK); + return new OkResult(); - var response1 = Request.CreateResponse(HttpStatusCode.BadRequest); - response1.Content = new StringContent($"No searcher found with name = {searcherName}"); - response1.ReasonPhrase = "Searcher Not Found"; + var response1 = new BadRequestObjectResult($"No searcher found with name = {searcherName}"); + SetReasonPhrase(response1, "Searcher Not Found"); return response1; } - private HttpResponseMessage ValidatePopulator(IIndex index) + private ActionResult ValidatePopulator(IIndex index) { if (_indexRebuilder.CanRebuild(index)) - return Request.CreateResponse(HttpStatusCode.OK); + return new OkResult(); - var response = Request.CreateResponse(HttpStatusCode.BadRequest); - response.Content = new StringContent($"The index {index.Name} cannot be rebuilt because it does not have an associated {typeof(IIndexPopulator)}"); - response.ReasonPhrase = "Index cannot be rebuilt"; + var response = new BadRequestObjectResult($"The index {index.Name} cannot be rebuilt because it does not have an associated {typeof(IIndexPopulator)}"); + SetReasonPhrase(response, "Index cannot be rebuilt"); return response; } - private HttpResponseMessage ValidateIndex(string indexName, out IIndex index) + private ActionResult ValidateIndex(string indexName, out IIndex index) { index = null; if (_examineManager.TryGetIndex(indexName, out index)) { //return Ok! - return Request.CreateResponse(HttpStatusCode.OK); + return new OkResult(); } - var response = Request.CreateResponse(HttpStatusCode.BadRequest); - response.Content = new StringContent($"No index found with name = {indexName}"); - response.ReasonPhrase = "Index Not Found"; + var response = new BadRequestObjectResult($"No index found with name = {indexName}"); + SetReasonPhrase(response, "Index Not Found"); return response; } + private void SetReasonPhrase(IActionResult response, string reasonPhrase) + { + //TODO we should update this behavior, as HTTP2 do not have ReasonPhrase. Could as well be returned in body + // https://github.com/aspnet/HttpAbstractions/issues/395 + var httpResponseFeature = HttpContext.Features.Get(); + if (!(httpResponseFeature is null)) + { + httpResponseFeature.ReasonPhrase = reasonPhrase; + } + } + private void Indexer_IndexOperationComplete(object sender, EventArgs e) { var indexer = (IIndex)sender; diff --git a/src/Umbraco.Web.Common/Exceptions/HttpResponseException.cs b/src/Umbraco.Web.Common/Exceptions/HttpResponseException.cs index d88209fea4..750417fab6 100644 --- a/src/Umbraco.Web.Common/Exceptions/HttpResponseException.cs +++ b/src/Umbraco.Web.Common/Exceptions/HttpResponseException.cs @@ -2,6 +2,8 @@ using System.Collections.Generic; using System.Net; using System.Runtime.Serialization; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.Infrastructure; namespace Umbraco.Web.Common.Exceptions { @@ -14,6 +16,22 @@ namespace Umbraco.Web.Common.Exceptions Value = value; } + public HttpResponseException(ActionResult actionResult) + { + + Status = actionResult switch + { + IStatusCodeActionResult x => (HttpStatusCode)x.StatusCode.GetValueOrDefault((int)HttpStatusCode.InternalServerError), + _ => HttpStatusCode.InternalServerError + }; + + Value = actionResult switch + { + ObjectResult x => x.Value, + _ => null + }; + } + public HttpStatusCode Status { get; set; } public object Value { get; set; } diff --git a/src/Umbraco.Web.Common/Extensions/ActionResultExtensions.cs b/src/Umbraco.Web.Common/Extensions/ActionResultExtensions.cs new file mode 100644 index 0000000000..21bfd6f9ba --- /dev/null +++ b/src/Umbraco.Web.Common/Extensions/ActionResultExtensions.cs @@ -0,0 +1,20 @@ +using System.Net; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.Infrastructure; + +namespace Umbraco.Extensions +{ + public static class ActionResultExtensions + { + public static bool IsSuccessStatusCode(this ActionResult actionResult) + { + var statusCode = actionResult switch + { + IStatusCodeActionResult x => x.StatusCode, + _ => (int?)null + }; + + return statusCode.HasValue && statusCode.Value >= (int)HttpStatusCode.OK && statusCode.Value < (int) HttpStatusCode.Ambiguous; + } + } +} diff --git a/src/Umbraco.Web.Common/Extensions/LinkGeneratorExtensions.cs b/src/Umbraco.Web.Common/Extensions/LinkGeneratorExtensions.cs index aa7700eca0..65b81c7e64 100644 --- a/src/Umbraco.Web.Common/Extensions/LinkGeneratorExtensions.cs +++ b/src/Umbraco.Web.Common/Extensions/LinkGeneratorExtensions.cs @@ -28,7 +28,7 @@ namespace Umbraco.Extensions return hostingEnvironment.ApplicationVirtualPath; // this would indicate that the installer is installed without the back office } - return linkGenerator.GetPathByAction("Default", ControllerExtensions.GetControllerName(backOfficeControllerType), new { area = Constants.Web.Mvc.BackOfficeApiArea }); + return linkGenerator.GetPathByAction("Default", ControllerExtensions.GetControllerName(backOfficeControllerType), values: new { area = Constants.Web.Mvc.BackOfficeApiArea }); } /// diff --git a/src/Umbraco.Web/Editors/BackOfficeServerVariables.cs b/src/Umbraco.Web/Editors/BackOfficeServerVariables.cs index c94513684b..d639d3a0a8 100644 --- a/src/Umbraco.Web/Editors/BackOfficeServerVariables.cs +++ b/src/Umbraco.Web/Editors/BackOfficeServerVariables.cs @@ -279,10 +279,11 @@ namespace Umbraco.Web.Editors "tagsDataBaseUrl", _urlHelper.GetUmbracoApiServiceBaseUrl( controller => controller.GetTags("", "", null)) }, - { - "examineMgmtBaseUrl", _urlHelper.GetUmbracoApiServiceBaseUrl( - controller => controller.GetIndexerDetails()) - }, + //TODO reintroduce + // { + // "examineMgmtBaseUrl", _urlHelper.GetUmbracoApiServiceBaseUrl( + // controller => controller.GetIndexerDetails()) + // }, { "healthCheckBaseUrl", _urlHelper.GetUmbracoApiServiceBaseUrl( controller => controller.GetAllHealthChecks()) diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index 520b8845b6..614df8b29a 100755 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -256,7 +256,6 @@ -