Replaced nonodes.aspx with MVC controller and view, with configurable view location.

This commit is contained in:
Andy Butland
2020-02-29 14:26:35 +01:00
parent dc36fa1290
commit e6a55a215a
16 changed files with 200 additions and 118 deletions

View File

@@ -407,5 +407,22 @@ namespace Umbraco.Core.Configuration
return backingField;
}
/// <summary>
/// Gets the path to the razor file used when no published content is available.
/// </summary>
public string NoNodesViewPath
{
get
{
var configuredValue = ConfigurationManager.AppSettings[Constants.AppSettings.NoNodesViewPath];
if (!string.IsNullOrWhiteSpace(configuredValue))
{
return configuredValue;
}
return "~/config/splashes/NoNodes.cshtml";
}
}
}
}

View File

@@ -95,5 +95,10 @@
bool DisableElectionForSingleServer { get; }
string RegisterType { get; }
string DatabaseFactoryServerVersion { get; }
/// <summary>
/// Gets the path to the razor file used when no published content is available.
/// </summary>
string NoNodesViewPath { get; }
}
}

View File

@@ -115,6 +115,11 @@ namespace Umbraco.Core
/// </summary>
public const string DisableElectionForSingleServer = "Umbraco.Core.DisableElectionForSingleServer";
/// <summary>
/// Gets the path to the razor file used when no published content is available.
/// </summary>
public const string NoNodesViewPath = "Umbraco.Core.NoNodesViewPath";
/// <summary>
/// Debug specific web.config AppSetting keys for Umbraco
/// </summary>

View File

@@ -34,6 +34,11 @@
/// The header name that angular uses to pass in the token to validate the cookie
/// </summary>
public const string AngularHeadername = "X-UMB-XSRF-TOKEN";
/// <summary>
/// The route for rendering a page when no content is published.
/// </summary>
public const string NoContentRoute = "/UmbNoContent";
}
}
}

View File

@@ -286,6 +286,7 @@
<Compile Include="StringNewlineExtensions.cs" />
<Compile Include="Strings\StylesheetHelperTests.cs" />
<Compile Include="Strings\StringValidationTests.cs" />
<Compile Include="Web\Mvc\RenderNoContentControllerTests.cs" />
<Compile Include="Web\Mvc\ValidateUmbracoFormRouteStringAttributeTests.cs" />
<Compile Include="Web\PublishedContentQueryTests.cs" />
<Compile Include="Web\UmbracoHelperTests.cs" />

View File

@@ -0,0 +1,54 @@
using System.Web.Mvc;
using Moq;
using NUnit.Framework;
using Umbraco.Core.Configuration;
using Umbraco.Core.IO;
using Umbraco.Web;
using Umbraco.Web.Models;
using Umbraco.Web.Mvc;
namespace Umbraco.Tests.Web.Mvc
{
[TestFixture]
public class RenderNoContentControllerTests
{
[Test]
public void Redirects_To_Root_When_Content_Published()
{
var mockUmbracoContext = new Mock<IUmbracoContext>();
mockUmbracoContext.Setup(x => x.Content.HasContent()).Returns(true);
var mockIOHelper = new Mock<IIOHelper>();
var mockGlobalSettings = new Mock<IGlobalSettings>();
var controller = new RenderNoContentController(mockUmbracoContext.Object, mockIOHelper.Object, mockGlobalSettings.Object);
var result = controller.Index() as RedirectResult;
Assert.IsNotNull(result);
Assert.AreEqual("~/", result.Url);
}
[Test]
public void Renders_View_When_No_Content_Published()
{
const string UmbracoPathSetting = "~/umbraco";
const string UmbracoPath = "/umbraco";
const string ViewPath = "~/config/splashes/NoNodes.cshtml";
var mockUmbracoContext = new Mock<IUmbracoContext>();
mockUmbracoContext.Setup(x => x.Content.HasContent()).Returns(false);
var mockIOHelper = new Mock<IIOHelper>();
mockIOHelper.Setup(x => x.ResolveUrl(It.Is<string>(y => y == UmbracoPathSetting))).Returns(UmbracoPath);
var mockGlobalSettings = new Mock<IGlobalSettings>();
mockGlobalSettings.SetupGet(x => x.UmbracoPath).Returns(UmbracoPathSetting);
mockGlobalSettings.SetupGet(x => x.NoNodesViewPath).Returns(ViewPath);
var controller = new RenderNoContentController(mockUmbracoContext.Object, mockIOHelper.Object, mockGlobalSettings.Object);
var result = controller.Index() as ViewResult;
Assert.IsNotNull(result);
Assert.AreEqual(ViewPath, result.ViewName);
var model = result.Model as NoNodesViewModel;
Assert.IsNotNull(model);
Assert.AreEqual(UmbracoPath, model.UmbracoPath);
}
}
}

View File

@@ -141,13 +141,6 @@
<Compile Include="..\SolutionInfo.cs">
<Link>Properties\SolutionInfo.cs</Link>
</Compile>
<Compile Include="Config\splashes\NoNodes.aspx.cs">
<DependentUpon>noNodes.aspx</DependentUpon>
<SubType>ASPXCodeBehind</SubType>
</Compile>
<Compile Include="Config\splashes\NoNodes.aspx.designer.cs">
<DependentUpon>noNodes.aspx</DependentUpon>
</Compile>
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Properties\Settings.Designer.cs">
<AutoGen>True</AutoGen>
@@ -173,11 +166,10 @@
<Content Include="Config\Lang\ru-RU.user.xml" />
<Content Include="Config\Lang\sv-SE.user.xml" />
<Content Include="Config\Lang\zh-CN.user.xml" />
<Content Include="Config\splashes\noNodes.aspx" />
<None Include="Config\splashes\NoNodes.cshtml" />
<Content Include="Umbraco\Config\Lang\cs.xml" />
<Content Include="Umbraco\Config\Lang\tr.xml" />
<Content Include="Umbraco\Config\Lang\zh_tw.xml" />
<Content Include="Config\Splashes\noNodes.aspx" />
<Content Include="Umbraco\Install\Views\Web.config" />
<None Include="Config\ClientDependency.Release.config">
<DependentUpon>ClientDependency.config</DependentUpon>

View File

@@ -1,22 +0,0 @@
using System;
using Umbraco.Web.Composing;
namespace Umbraco.Web.UI.Config.Splashes
{
public partial class NoNodes : System.Web.UI.Page
{
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
var store = Current.UmbracoContext.Content;
if (store.HasContent())
{
//if there is actually content, go to the root
Response.Redirect("~/");
}
}
}
}

View File

@@ -1,15 +0,0 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace Umbraco.Web.UI.Config.Splashes {
public partial class NoNodes {
}
}

View File

@@ -0,0 +1,49 @@
@inherits System.Web.Mvc.WebViewPage<Umbraco.Web.Models.NoNodesViewModel>
<!doctype html>
<html class="no-js" lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<title>Umbraco: No Published Content</title>
<link rel="stylesheet" href="../../Umbraco/assets/css/nonodes.style.min.css" />
</head>
<body>
<section>
<article>
<div>
<div class="logo"></div>
<h1>Welcome to your Umbraco installation</h1>
<h3>You're seeing this wonderful page because your website doesn't contain any published content yet.</h3>
<div class="cta">
<a href="@Model.UmbracoPath" class="button">Open Umbraco</a>
</div>
<div class="row">
<div class="col">
<h2>Easy start with Umbraco.tv</h2>
<p>We have created a bunch of 'how-to' videos, to get you easily started with Umbraco. Learn how to build projects in just a couple of minutes. Easiest CMS in the world.</p>
<a href="https://umbraco.tv?ref=tvFromInstaller" target="_blank">Umbraco.tv &rarr;</a>
</div>
<div class="col">
<h2>Be a part of the community</h2>
<p>The Umbraco community is the best of its kind, be sure to visit, and if you have any questions, we're sure that you can get your answers from the community.</p>
<a href="https://our.umbraco.com/?ref=ourFromInstaller" target="_blank">our.Umbraco &rarr;</a>
</div>
</div>
</div>
</article>
</section>
</body>
</html>

View File

@@ -1,63 +0,0 @@
<%@ Page Language="C#" AutoEventWireup="True" Inherits="Umbraco.Web.UI.Config.Splashes.NoNodes" CodeBehind="NoNodes.aspx.cs" %>
<%@ Import Namespace="Umbraco.Core" %>
<%@ Import Namespace="Umbraco.Web.Composing" %>
<%@ Import Namespace="Umbraco.Core.Configuration" %>
<%@ Import Namespace="Umbraco.Core.IO" %>
<!doctype html>
<!--[if lt IE 7]> <html class="no-js ie6 oldie" lang="en"> <![endif]-->
<!--[if IE 7]> <html class="no-js ie7 oldie" lang="en"> <![endif]-->
<!--[if IE 8]> <html class="no-js ie8 oldie" lang="en"> <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js" lang="en"> <!--<![endif]-->
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<title></title>
<meta name="description" content="">
<meta name="author" content="">
<link rel="stylesheet" href="../../Umbraco/assets/css/nonodes.style.min.css" />
</head>
<body>
<section>
<article>
<div>
<div class="logo"></div>
<h1>Welcome to your Umbraco installation</h1>
<h3>You're seeing this wonderful page because your website doesn't contain any published content yet.</h3>
<div class="cta">
<a href="<%= Current.IOHelper.ResolveUrl(Current.Configs.Global().UmbracoPath) %>" class="button">Open Umbraco</a>
</div>
<div class="row">
<div class="col">
<h2>Easy start with Umbraco.tv</h2>
<p>We have created a bunch of 'how-to' videos, to get you easily started with Umbraco. Learn how to build projects in just a couple of minutes. Easiest CMS in the world.</p>
<a href="https://umbraco.tv?ref=tvFromInstaller" target="_blank">Umbraco.tv &rarr;</a>
</div>
<div class="col">
<h2>Be a part of the community</h2>
<p>The Umbraco community is the best of its kind, be sure to visit, and if you have any questions, we're sure that you can get your answers from the community.</p>
<a href="https://our.umbraco.com/?ref=ourFromInstaller" target="_blank">our.Umbraco &rarr;</a>
</div>
</div>
</div>
</article>
</section>
<script src="https://code.jquery.com/jquery-latest.min.js"></script>
</body>
</html>

View File

@@ -0,0 +1,7 @@
namespace Umbraco.Web.Models
{
public class NoNodesViewModel
{
public string UmbracoPath { get; set; }
}
}

View File

@@ -0,0 +1,39 @@
using System;
using System.Web.Mvc;
using Umbraco.Core.Configuration;
using Umbraco.Core.IO;
using Umbraco.Web.Models;
namespace Umbraco.Web.Mvc
{
public class RenderNoContentController : Controller
{
private readonly IUmbracoContext _umbracoContext;
private readonly IIOHelper _ioHelper;
private readonly IGlobalSettings _globalSettings;
public RenderNoContentController(IUmbracoContext umbracoContext, IIOHelper ioHelper, IGlobalSettings globalSettings)
{
_umbracoContext = umbracoContext ?? throw new ArgumentNullException(nameof(umbracoContext));
_ioHelper = ioHelper ?? throw new ArgumentNullException(nameof(ioHelper));
_globalSettings = globalSettings ?? throw new ArgumentNullException(nameof(globalSettings));
}
public ActionResult Index()
{
var store = _umbracoContext.Content;
if (store.HasContent())
{
// If there is actually content, go to the root.
return Redirect("~/");
}
var model = new NoNodesViewModel
{
UmbracoPath = _ioHelper.ResolveUrl(_globalSettings.UmbracoPath),
};
return View(_globalSettings.NoNodesViewPath, model);
}
}
}

View File

@@ -17,7 +17,6 @@ using Umbraco.Core.Configuration;
using Umbraco.Core.Hosting;
using Umbraco.Core.Strings;
using Umbraco.Core.IO;
using Umbraco.Core.Strings;
using Umbraco.Web.Install;
using Umbraco.Web.JavaScript;
using Umbraco.Web.Mvc;
@@ -181,6 +180,9 @@ namespace Umbraco.Web.Runtime
);
defaultRoute.RouteHandler = new RenderRouteHandler(umbracoContextAccessor, ControllerBuilder.Current.GetControllerFactory(), shortStringHelper);
// register no content route
RouteNoContentController(umbracoPath);
// register install routes
RouteTable.Routes.RegisterArea<UmbracoInstallArea>();
@@ -191,6 +193,14 @@ namespace Umbraco.Web.Runtime
RoutePluginControllers(globalSettings, surfaceControllerTypes, apiControllerTypes, ioHelper);
}
private static void RouteNoContentController(string umbracoPath)
{
RouteTable.Routes.MapRoute(
"umbraco-no-content",
umbracoPath + Core.Constants.Web.NoContentRoute,
new { controller = "RenderNoContent", action = "Index" });
}
private static void RoutePluginControllers(
IGlobalSettings globalSettings,
SurfaceControllerTypeCollection surfaceControllerTypes,
@@ -252,6 +262,5 @@ namespace Umbraco.Web.Runtime
// make it use our custom/special SurfaceMvcHandler
route.RouteHandler = new SurfaceRouteHandler();
}
}
}

View File

@@ -143,6 +143,8 @@
<Compile Include="Composing\BuildManagerTypeFinder.cs" />
<Compile Include="Composing\CompositionExtensions\Installer.cs" />
<Compile Include="Composing\LightInject\LightInjectContainer.cs" />
<Compile Include="Models\NoNodesViewModel.cs" />
<Compile Include="Mvc\RenderNoContentController.cs" />
<Compile Include="Editors\BackOfficePreviewModel.cs" />
<Compile Include="Editors\EditorModelEventManager.cs" />
<Compile Include="Editors\Filters\ContentSaveModelValidator.cs" />

View File

@@ -1,17 +1,14 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Web;
using System.Web.Routing;
using Umbraco.Core;
using Umbraco.Core.Cache;
using Umbraco.Core.Configuration;
using Umbraco.Core.IO;
using Umbraco.Core.Logging;
using Umbraco.Web.Routing;
using Umbraco.Core.Exceptions;
using Umbraco.Core.Security;
using Umbraco.Core.Logging;
using Umbraco.Web.Composing;
using Umbraco.Web.Routing;
using Umbraco.Web.Security;
namespace Umbraco.Web
@@ -244,8 +241,8 @@ namespace Umbraco.Web
_logger.Warn<UmbracoModule>("Umbraco has no content");
const string noContentUrl = "~/config/splashes/noNodes.aspx";
httpContext.RewritePath(_uriUtility.ToAbsolute(noContentUrl));
var rewriteTo = _uriUtility.ToAbsolute(_globalSettings.UmbracoPath + Constants.Web.NoContentRoute);
httpContext.RewritePath(_uriUtility.ToAbsolute(rewriteTo));
return false;
}