Gets default.cshtml rendering what should work, had to update quite a few things to get to this point, now need to figure out why it doesn't start booting angular.

This commit is contained in:
Shannon
2020-05-25 19:37:16 +10:00
parent d89337e3d5
commit 0730867d74
11 changed files with 220 additions and 142 deletions

View File

@@ -34,7 +34,7 @@ namespace Umbraco.Core.WebAssets
/// <returns>
/// An html encoded string
/// </returns>
string RenderCssHere(string bundleName);
Task<string> RenderCssHereAsync(string bundleName);
/// <summary>
/// Creates a JS bundle
@@ -56,7 +56,7 @@ namespace Umbraco.Core.WebAssets
/// <returns>
/// An html encoded string
/// </returns>
string RenderJsHere(string bundleName);
Task<string> RenderJsHereAsync(string bundleName);
/// <summary>
/// Returns the asset paths for the bundle name

View File

@@ -1,52 +0,0 @@
using System;
using System.IO;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;
namespace Umbraco.Web.BackOffice.ActionResults
{
/// <summary>
/// Custom json result using newtonsoft json.net
/// </summary>
public class JsonNetResult : IActionResult
{
public Encoding ContentEncoding { get; set; }
public string ContentType { get; set; }
public object Data { get; set; }
public JsonSerializerSettings SerializerSettings { get; set; }
public Formatting Formatting { get; set; }
public JsonNetResult()
{
SerializerSettings = new JsonSerializerSettings();
}
public Task ExecuteResultAsync(ActionContext context)
{
if (context is null)
throw new ArgumentNullException(nameof(context));
var response = context.HttpContext.Response;
response.ContentType = string.IsNullOrEmpty(ContentType) == false
? ContentType
: System.Net.Mime.MediaTypeNames.Application.Json;
if (!(ContentEncoding is null))
response.Headers.Add(Microsoft.Net.Http.Headers.HeaderNames.ContentEncoding, ContentEncoding.ToString());
if (!(Data is null))
{
using var bodyWriter = new StreamWriter(response.Body);
using var writer = new JsonTextWriter(bodyWriter) { Formatting = Formatting };
var serializer = JsonSerializer.Create(SerializerSettings);
serializer.Serialize(writer, Data);
}
return Task.CompletedTask;
}
}
}

View File

@@ -1,11 +1,11 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;
using Umbraco.Core;
using Umbraco.Core.BackOffice;
using Umbraco.Core.Cache;
@@ -15,8 +15,6 @@ using Umbraco.Core.Hosting;
using Umbraco.Core.Services;
using Umbraco.Core.WebAssets;
using Umbraco.Extensions;
using Umbraco.Net;
using Umbraco.Web.BackOffice.ActionResults;
using Umbraco.Web.BackOffice.Filters;
using Umbraco.Web.Common.ActionResults;
using Umbraco.Web.Models;
@@ -93,7 +91,7 @@ namespace Umbraco.Web.BackOffice.Controllers
/// <param name="culture"></param>
/// <returns></returns>
[HttpGet]
public JsonNetResult LocalizedText(string culture = null)
public Dictionary<string, Dictionary<string, string>> LocalizedText(string culture = null)
{
var securityHelper = _umbracoContextAccessor.GetRequiredUmbracoContext().Security;
var isAuthenticated = securityHelper.IsAuthenticated();
@@ -125,14 +123,14 @@ namespace Umbraco.Web.BackOffice.Controllers
.ToDictionary(pv => pv.Key, pv =>
pv.ToDictionary(pve => pve.valueAlias, pve => pve.value));
return new JsonNetResult { Data = nestedDictionary, Formatting = Formatting.None };
return nestedDictionary;
}
[UmbracoAuthorize(Order = 0)]
[HttpGet]
public JsonNetResult GetGridConfig()
public IEnumerable<IGridEditorConfig> GetGridConfig()
{
return new JsonNetResult { Data = _gridConfig.EditorsConfig.Editors, Formatting = Formatting.None };
return _gridConfig.EditorsConfig.Editors;
}
/// <summary>
@@ -156,7 +154,7 @@ namespace Umbraco.Web.BackOffice.Controllers
}
[HttpGet]
public async Task<ActionResult> ValidatePasswordResetCode([Bind(Prefix = "u")]int userId, [Bind(Prefix = "r")]string resetCode)
public async Task<IActionResult> ValidatePasswordResetCode([Bind(Prefix = "u")]int userId, [Bind(Prefix = "r")]string resetCode)
{
var user = await _userManager.FindByIdAsync(userId.ToString());
if (user != null)
@@ -180,9 +178,9 @@ namespace Umbraco.Web.BackOffice.Controllers
/// otherwise process the external login info.
/// </summary>
/// <returns></returns>
private async Task<ActionResult> RenderDefaultOrProcessExternalLoginAsync(
Func<ActionResult> defaultResponse,
Func<ActionResult> externalSignInResponse)
private async Task<IActionResult> RenderDefaultOrProcessExternalLoginAsync(
Func<IActionResult> defaultResponse,
Func<IActionResult> externalSignInResponse)
{
if (defaultResponse is null) throw new ArgumentNullException(nameof(defaultResponse));
if (externalSignInResponse is null) throw new ArgumentNullException(nameof(externalSignInResponse));
@@ -213,7 +211,7 @@ namespace Umbraco.Web.BackOffice.Controllers
// Used for XSRF protection when adding external logins
private const string XsrfKey = "XsrfId";
private ActionResult RedirectToLocal(string returnUrl)
private IActionResult RedirectToLocal(string returnUrl)
{
if (Url.IsLocalUrl(returnUrl))
{

View File

@@ -48,6 +48,7 @@ namespace Umbraco.Web.BackOffice.Controllers
IGlobalSettings globalSettings,
IUmbracoVersion umbracoVersion,
IContentSettings contentSettings,
IHttpContextAccessor httpContextAccessor,
//TreeCollection treeCollection, // TODO: If we need this we need to migrate trees
IHostingEnvironment hostingEnvironment,
IRuntimeSettings settings,
@@ -62,6 +63,7 @@ namespace Umbraco.Web.BackOffice.Controllers
_globalSettings = globalSettings;
_umbracoVersion = umbracoVersion;
_contentSettings = contentSettings ?? throw new ArgumentNullException(nameof(contentSettings));
_httpContextAccessor = httpContextAccessor;
//_treeCollection = treeCollection ?? throw new ArgumentNullException(nameof(treeCollection));
_hostingEnvironment = hostingEnvironment;
_settings = settings;

View File

@@ -1,36 +1,32 @@
using System.Collections.Generic;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Html;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.AspNetCore.Routing;
using Newtonsoft.Json;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.Mvc;
using Microsoft.Owin.Security;
using Newtonsoft.Json;
using System.Threading.Tasks;
using Umbraco.Core;
using Umbraco.Core.Configuration;
using Umbraco.Core.Configuration.UmbracoSettings;
using Umbraco.Core.Hosting;
using Umbraco.Core.IO;
using Umbraco.Core.Runtime;
using Umbraco.Core.WebAssets;
using Umbraco.Web.Composing;
using Umbraco.Web.Editors;
using Umbraco.Web.BackOffice.Controllers;
using Umbraco.Web.Features;
using Umbraco.Web.Models;
using Umbraco.Web.Security;
using Umbraco.Web.Trees;
using Umbraco.Web.WebApi;
using Umbraco.Web.WebAssets;
namespace Umbraco.Web
namespace Umbraco.Extensions
{
/// <summary>
/// HtmlHelper extensions for the back office
/// </summary>
public static class HtmlHelperBackOfficeExtensions
{
/// <summary>
/// Outputs a script tag containing the bare minimum (non secure) server vars for use with the angular app
/// </summary>
/// <param name="html"></param>
/// <param name="uri"></param>
/// <param name="linkGenerator"></param>
/// <param name="features"></param>
/// <param name="globalSettings"></param>
/// <param name="umbracoVersion"></param>
@@ -46,10 +42,9 @@ namespace Umbraco.Web
/// These are the bare minimal server variables that are required for the application to start without being authenticated,
/// we will load the rest of the server vars after the user is authenticated.
/// </remarks>
public static IHtmlString BareMinimumServerVariablesScript(this HtmlHelper html, UrlHelper uri, UmbracoFeatures features, IGlobalSettings globalSettings, IUmbracoVersion umbracoVersion, IContentSettings contentSettings, TreeCollection treeCollection, IHostingEnvironment hostingEnvironment, IRuntimeSettings settings, ISecuritySettings securitySettings, IRuntimeMinifier runtimeMinifier)
public static async Task<IHtmlContent> BareMinimumServerVariablesScriptAsync(this IHtmlHelper html, BackOfficeServerVariables backOfficeServerVariables)
{
var serverVars = new BackOfficeServerVariables(uri, Current.RuntimeState, features, globalSettings, umbracoVersion, contentSettings, treeCollection, hostingEnvironment, settings, securitySettings, runtimeMinifier);
var minVars = serverVars.BareMinimumServerVariables();
var minVars = await backOfficeServerVariables.BareMinimumServerVariablesAsync();
var str = @"<script type=""text/javascript"">
var Umbraco = {};
@@ -66,15 +61,24 @@ namespace Umbraco.Web
/// <param name="html"></param>
/// <param name="externalLoginErrors"></param>
/// <returns></returns>
public static IHtmlString AngularValueExternalLoginInfoScript(this HtmlHelper html, IEnumerable<string> externalLoginErrors)
public static async Task<IHtmlContent> AngularValueExternalLoginInfoScriptAsync(this IHtmlHelper html,
IAuthenticationSchemeProvider authenticationSchemeProvider,
IEnumerable<string> externalLoginErrors)
{
var loginProviders = html.ViewContext.HttpContext.GetOwinContext().Authentication.GetExternalAuthenticationTypes()
.Where(p => p.Properties.ContainsKey("UmbracoBackOffice"))
var providers = await authenticationSchemeProvider.GetAllSchemesAsync();
var loginProviders = providers
// TODO: We need to filter only back office enabled schemes.
// Before we used to have a property bag to check, now we don't so need to investigate the easiest/best
// way to do this. We have the type so maybe we check for a marker interface, but maybe there's another way,
// just need to investigate.
//.Where(p => p.Properties.ContainsKey("UmbracoBackOffice"))
.Select(p => new
{
authType = p.AuthenticationType,
caption = p.Caption,
properties = p.Properties
authType = p.Name,
caption = p.DisplayName,
// TODO: See above, if we need this property bag in the vars then we'll need to figure something out
//properties = p.Properties
})
.ToArray();
@@ -105,7 +109,7 @@ namespace Umbraco.Web
/// <param name="html"></param>
/// <param name="val"></param>
/// <returns></returns>
public static IHtmlString AngularValueResetPasswordCodeInfoScript(this HtmlHelper html, object val)
public static IHtmlContent AngularValueResetPasswordCodeInfoScript(this IHtmlHelper html, object val)
{
var sb = new StringBuilder();
sb.AppendLine();
@@ -132,9 +136,9 @@ namespace Umbraco.Web
return html.Raw(sb.ToString());
}
public static IHtmlString AngularValueTinyMceAssets(this HtmlHelper html, IRuntimeMinifier runtimeMinifier)
public static async Task<IHtmlContent> AngularValueTinyMceAssetsAsync(this IHtmlHelper html, IRuntimeMinifier runtimeMinifier)
{
var files = runtimeMinifier.GetAssetPathsAsync(BackOfficeWebAssets.UmbracoTinyMceJsBundleName).GetAwaiter().GetResult();
var files = await runtimeMinifier.GetAssetPathsAsync(BackOfficeWebAssets.UmbracoTinyMceJsBundleName);
var sb = new StringBuilder();

View File

@@ -6,6 +6,11 @@ using Umbraco.Core;
using Umbraco.Web.Common.Controllers;
using Umbraco.Web.WebApi;
using Umbraco.Web.Common.Install;
using Microsoft.AspNetCore.Routing;
using Umbraco.Core.Hosting;
using System.Globalization;
using Umbraco.Core.Configuration;
using Umbraco.Core.WebAssets;
namespace Umbraco.Extensions
{
@@ -13,6 +18,8 @@ namespace Umbraco.Extensions
public static class UrlHelperExtensions
{
/// <summary>
/// Return the back office url if the back office is installed
/// </summary>
@@ -175,5 +182,40 @@ namespace Umbraco.Extensions
}
return url.GetUmbracoApiService<T>(umbracoApiControllerTypeCollection, method.Name).TrimEnd(method.Name);
}
/// <summary>
/// Return the Url for an action with a cache-busting hash appended
/// </summary>
/// <param name="url"></param>
/// <param name="actionName"></param>
/// <param name="controllerName"></param>
/// <param name="routeVals"></param>
/// <returns></returns>
public static string GetUrlWithCacheBust(this IUrlHelper url, string actionName, string controllerName, RouteValueDictionary routeVals,
IHostingEnvironment hostingEnvironment, IUmbracoVersion umbracoVersion, IRuntimeMinifier runtimeMinifier)
{
var applicationJs = url.Action(actionName, controllerName, routeVals);
applicationJs = applicationJs + "?umb__rnd=" + GetCacheBustHash(hostingEnvironment, umbracoVersion, runtimeMinifier);
return applicationJs;
}
/// <summary>
///
/// </summary>
/// <returns></returns>
public static string GetCacheBustHash(IHostingEnvironment hostingEnvironment, IUmbracoVersion umbracoVersion, IRuntimeMinifier runtimeMinifier)
{
//make a hash of umbraco and client dependency version
//in case the user bypasses the installer and just bumps the web.config or client dependency config
//if in debug mode, always burst the cache
if (hostingEnvironment.IsDebugMode)
{
return DateTime.Now.Ticks.ToString(CultureInfo.InvariantCulture).GenerateHash();
}
var version = umbracoVersion.SemanticVersion.ToSemanticString();
return $"{version}.{runtimeMinifier.CacheBuster}".GenerateHash();
}
}
}

View File

@@ -65,7 +65,7 @@ namespace Umbraco.Web.Common.RuntimeMinification
// affect this or vice versa.
}
public string RenderCssHere(string bundleName) => _smidge.SmidgeHelper.CssHereAsync(bundleName, _hostingEnvironment.IsDebugMode).ToString();
public async Task<string> RenderCssHereAsync(string bundleName) => (await _smidge.SmidgeHelper.CssHereAsync(bundleName, _hostingEnvironment.IsDebugMode)).ToString();
public void CreateJsBundle(string bundleName, params string[] filePaths)
{
@@ -82,7 +82,7 @@ namespace Umbraco.Web.Common.RuntimeMinification
// affect this or vice versa.
}
public string RenderJsHere(string bundleName) => _smidge.SmidgeHelper.JsHereAsync(bundleName, _hostingEnvironment.IsDebugMode).ToString();
public async Task<string> RenderJsHereAsync(string bundleName) => (await _smidge.SmidgeHelper.JsHereAsync(bundleName, _hostingEnvironment.IsDebugMode)).ToString();
public async Task<IEnumerable<string>> GetAssetPathsAsync(string bundleName) => await _smidge.SmidgeHelper.GenerateJsUrlsAsync(bundleName, _hostingEnvironment.IsDebugMode);

View File

@@ -1,17 +1,132 @@
@{
Layout = null;
@using Umbraco.Core
@using Umbraco.Web.Composing
@using Umbraco.Web
@using Umbraco.Web.WebAssets
@using Umbraco.Core.WebAssets
@using Umbraco.Core.Configuration
@using Umbraco.Core.Hosting
@using Umbraco.Extensions
@using Umbraco.Core.Logging
@using Umbraco.Web.BackOffice.Controllers
@using Microsoft.AspNetCore.Authentication
@inject IAuthenticationSchemeProvider authenticationSchemeProvider
@inject BackOfficeServerVariables backOfficeServerVariables
@inject IUmbracoVersion umbracoVersion
@inject IHostingEnvironment hostingEnvironment
@inject IGlobalSettings globalSettings
@inject IRuntimeMinifier runtimeMinifier
@inject IProfilerHtml profilerHtml
@{
var isDebug = false;
var qryDebug = Context.Request.Query["umbDebug"].TryConvertTo<bool>();
isDebug = qryDebug.Success && qryDebug.Result;
var backOfficePath = globalSettings.GetBackOfficePath(hostingEnvironment);
}
<!doctype html>
<!DOCTYPE html>
<html lang="en">
<head>
<base href="@backOfficePath.EnsureEndsWith('/')" />
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="robots" content="noindex, nofollow">
<meta name="pinterest" content="nopin" />
<title ng-bind="$root.locationTitle">Umbraco</title>
@Html.Raw(await runtimeMinifier.RenderCssHereAsync(BackOfficeWebAssets.UmbracoInitCssBundleName))
</head>
<body ng-class="{'touch':touchDevice, 'emptySection':emptySection, 'umb-drawer-is-visible':drawer.show, 'umb-tour-is-visible': tour.show, 'tabbing-active':tabbingActive}" ng-controller="Umbraco.MainController" id="umbracoMainPageBody">
<body>
<noscript>
<div style="margin: 10px;">
<h3><img src="assets/img/application/logo.png" alt="Umbraco logo" style="vertical-align: text-bottom;" /> Umbraco</h3>
<p>For full functionality of Umbraco CMS it is necessary to enable JavaScript.</p>
<p>Here are the <a href="https://www.enable-javascript.com/" target="_blank" style="text-decoration: underline;">instructions how to enable JavaScript in your web browser</a>.</p>
</div>
</noscript>
<h1>Hello!</h1>
<div ng-hide="!authenticated" ng-cloak>
<p>TODO: Import the default.cshtml back office page</p>
<div style="display: none;" id="mainwrapper" class="clearfix">
<umb-app-header></umb-app-header>
<div class="umb-app-content">
<umb-navigation></umb-navigation>
<section id="contentwrapper">
<div id="contentcolumn">
<div class="umb-editor" ng-view></div>
</div>
</section>
</div>
<umb-tour ng-if="tour.show"
model="tour">
</umb-tour>
<umb-notifications></umb-notifications>
</div>
<!-- help dialog controller by the help button - this also forces the backoffice UI to shift 400px -->
<umb-drawer data-element="drawer" ng-if="drawer.show" model="drawer.model" view="drawer.view"></umb-drawer>
<umb-search ng-if="search.show" on-close="closeSearch()"></umb-search>
</div>
<umb-backdrop ng-if="backdrop.show || infiniteMode"
backdrop-opacity="backdrop.opacity"
highlight-element="backdrop.element"
highlight-prevent-click="backdrop.elementPreventClick"
disable-events-on-click="backdrop.disableEventsOnClick">
</umb-backdrop>
<umb-overlay ng-if="overlay.show"
model="overlay"
position="{{overlay.position}}"
view="overlay.view"
parent-scope="overlay.parentScope">
</umb-overlay>
<umb-editors ng-show="infiniteMode"></umb-editors>
<umb-login ng-if="login.show"
on-login="hideLoginScreen()">
</umb-login>
@await Html.BareMinimumServerVariablesScriptAsync(backOfficeServerVariables)
<script>
document.angularReady = function(app) {
@await Html.AngularValueExternalLoginInfoScriptAsync(authenticationSchemeProvider, ViewData.GetExternalSignInError())
@Html.AngularValueResetPasswordCodeInfoScript(ViewData["PasswordResetCode"])
@await Html.AngularValueTinyMceAssetsAsync(runtimeMinifier)
//required for the noscript trick
document.getElementById("mainwrapper").style.display = "inherit";
}
</script>
<script src="lib/lazyload-js/lazyload.min.js"></script>
<script src="@Url.GetUrlWithCacheBust("Application", "BackOffice", null, hostingEnvironment, umbracoVersion, runtimeMinifier)"></script>
@if (isDebug)
{
@Html.Raw(profilerHtml.Render())
}
</body>
</html>

View File

@@ -261,7 +261,6 @@
<Compile Include="Editors\MemberGroupController.cs" />
<Compile Include="Composing\CompositionExtensions\Controllers.cs" />
<Compile Include="HealthCheck\HealthCheckController.cs" />
<Compile Include="HtmlHelperBackOfficeExtensions.cs" />
<Compile Include="Composing\ModuleInjector.cs" />
<Compile Include="Mvc\FilteredControllerFactoryCollection.cs" />
<Compile Include="Mvc\FilteredControllerFactoryCollectionBuilder.cs" />

View File

@@ -115,38 +115,8 @@ namespace Umbraco.Web
}
/// <summary>
/// Return the Url for an action with a cache-busting hash appended
/// </summary>
/// <param name="url"></param>
/// <param name="actionName"></param>
/// <param name="controllerName"></param>
/// <param name="routeVals"></param>
/// <returns></returns>
public static string GetUrlWithCacheBust(this UrlHelper url, string actionName, string controllerName, RouteValueDictionary routeVals = null)
{
var applicationJs = url.Action(actionName, controllerName, routeVals);
applicationJs = applicationJs + "?umb__rnd=" + GetCacheBustHash();
return applicationJs;
}
/// <summary>
///
/// </summary>
/// <returns></returns>
public static string GetCacheBustHash()
{
//make a hash of umbraco and client dependency version
//in case the user bypasses the installer and just bumps the web.config or client dependency config
//if in debug mode, always burst the cache
if (Current.HostingEnvironment.IsDebugMode)
{
return DateTime.Now.Ticks.ToString(CultureInfo.InvariantCulture).GenerateHash();
}
var version = Current.UmbracoVersion.SemanticVersion.ToSemanticString();
return $"{version}.{Current.RuntimeMinifier.CacheBuster}".GenerateHash();
}
}
}

View File

@@ -50,11 +50,11 @@ namespace Umbraco.Web.WebAssets.CDF
filePaths.Select(x => new CssFile(x)).ToArray());
}
public string RenderCssHere(string bundleName)
public Task<string> RenderCssHereAsync(string bundleName)
{
var bundleFiles = GetCssBundleFiles(bundleName);
if (bundleFiles == null) return string.Empty;
return RenderOutput(bundleFiles, AssetType.Css);
if (bundleFiles == null) return Task.FromResult(string.Empty);
return Task.FromResult(RenderOutput(bundleFiles, AssetType.Css));
}
public void CreateJsBundle(string bundleName, params string[] filePaths)
@@ -67,11 +67,11 @@ namespace Umbraco.Web.WebAssets.CDF
filePaths.Select(x => new JavascriptFile(x)).ToArray());
}
public string RenderJsHere(string bundleName)
public Task<string> RenderJsHereAsync(string bundleName)
{
var bundleFiles = GetJsBundleFiles(bundleName);
if (bundleFiles == null) return string.Empty;
return RenderOutput(bundleFiles, AssetType.Javascript);
if (bundleFiles == null) return Task.FromResult(string.Empty);
return Task.FromResult(RenderOutput(bundleFiles, AssetType.Javascript));
}
public Task<IEnumerable<string>> GetAssetPathsAsync(string bundleName)