Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,17 @@
# Changelog

All notable changes to this project will be documented in this file.
## [5.0.0]

- Switch from SiteDefinition to the new Application framework
- Remove remaining obsolete warnings

### Breaking changes

- IContentFilter: Signature changed on ShouldExcludeContent (removed SiteDefinition parameter)
- All use of ISiteDefinitionRepository replaced by IApplicationRepository
- XmlGenerator: SiteDefinition property replaced by CurrentSite
- HostDefinitionExtensions removed

## [4.0.0]

Expand Down Expand Up @@ -28,4 +39,4 @@ All notable changes to this project will be documented in this file.

## [1.0.0]

- Initial version
- Initial version
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@
using System.Linq;
using System.Xml.Linq;
using EPiServer;
using EPiServer.Applications;
using EPiServer.DataAbstraction;
using EPiServer.Framework.Cache;
using EPiServer.Web;
using EPiServer.Web.Routing;
using Geta.Optimizely.Sitemaps.Repositories;
using Geta.Optimizely.Sitemaps.Services;
Expand All @@ -30,7 +30,7 @@ public CommerceAndStandardSitemapXmlGenerator(
ISitemapRepository sitemapRepository,
IContentRepository contentRepository,
IUrlResolver urlResolver,
ISiteDefinitionRepository siteDefinitionRepository,
IApplicationRepository applicationRepository,
ILanguageBranchRepository languageBranchRepository,
ReferenceConverter referenceConverter,
IContentFilter contentFilter,
Expand All @@ -42,7 +42,7 @@ public CommerceAndStandardSitemapXmlGenerator(
sitemapRepository,
contentRepository,
urlResolver,
siteDefinitionRepository,
applicationRepository,
languageBranchRepository,
referenceConverter,
contentFilter,
Expand All @@ -55,9 +55,9 @@ public CommerceAndStandardSitemapXmlGenerator(

protected override IEnumerable<XElement> GetSitemapXmlElements()
{
var contentDescendants = ContentRepository.GetDescendents(this.SiteSettings.StartPage).ToList();
var contentDescendants = ContentRepository.GetDescendents(this.CurrentSite.EntryPoint).ToList();

contentDescendants.Insert(0, SiteSettings.StartPage);
contentDescendants.Insert(0, CurrentSite.EntryPoint);

var contentElements = GenerateXmlElements(contentDescendants);
return contentElements.Union(base.GetSitemapXmlElements());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,12 @@

using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;
using EPiServer;
using EPiServer.Applications;
using EPiServer.Core;
using EPiServer.DataAbstraction;
using EPiServer.Framework.Cache;
using EPiServer.Web;
using EPiServer.Web.Routing;
using Geta.Optimizely.Sitemaps.Repositories;
using Geta.Optimizely.Sitemaps.Services;
Expand All @@ -33,7 +32,7 @@ public CommerceSitemapXmlGenerator(
ISitemapRepository sitemapRepository,
IContentRepository contentRepository,
IUrlResolver urlResolver,
ISiteDefinitionRepository siteDefinitionRepository,
IApplicationRepository applicationRepository,
ILanguageBranchRepository languageBranchRepository,
ReferenceConverter referenceConverter,
IContentFilter contentFilter,
Expand All @@ -45,7 +44,7 @@ public CommerceSitemapXmlGenerator(
sitemapRepository,
contentRepository,
urlResolver,
siteDefinitionRepository,
applicationRepository,
languageBranchRepository,
contentFilter,
uriAugmenterService,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
using System.Collections.Generic;
using System.Linq;
using EPiServer.Applications;
using EPiServer.Data;
using EPiServer.DataAbstraction;
using EPiServer.Web;
using Geta.Mapping;
using Geta.Optimizely.Sitemaps.Entities;
using Geta.Optimizely.Sitemaps.Models;
Expand All @@ -19,20 +19,20 @@ namespace Geta.Optimizely.Sitemaps.Pages.Geta.Optimizely.Sitemaps;
public class IndexModel : PageModel
{
private readonly ISitemapRepository _sitemapRepository;
private readonly ISiteDefinitionRepository _siteDefinitionRepository;
private readonly IApplicationRepository _applicationRepository;
private readonly ILanguageBranchRepository _languageBranchRepository;
private readonly IMapper<SitemapViewModel, SitemapData> _modelToEntityMapper;
private readonly ICreateFrom<SitemapData, SitemapViewModel> _entityToModelCreator;

public IndexModel(
ISitemapRepository sitemapRepository,
ISiteDefinitionRepository siteDefinitionRepository,
IApplicationRepository applicationRepository,
ILanguageBranchRepository languageBranchRepository,
IMapper<SitemapViewModel, SitemapData> modelToEntityMapper,
ICreateFrom<SitemapData, SitemapViewModel> entityToModelCreator)
{
_sitemapRepository = sitemapRepository;
_siteDefinitionRepository = siteDefinitionRepository;
_applicationRepository = applicationRepository;
_languageBranchRepository = languageBranchRepository;
_modelToEntityMapper = modelToEntityMapper;
_entityToModelCreator = entityToModelCreator;
Expand Down Expand Up @@ -161,36 +161,34 @@ private void BindSitemapDataList()

private void LoadSiteHosts()
{
var hosts = _siteDefinitionRepository.List().ToList();
var sites = _applicationRepository
.List()
.OfType<IRoutableApplication>()
.ToList();

var siteUrls = new List<SelectListItem>(hosts.Count);

foreach (var siteInformation in hosts)
var urls = new List<SelectListItem>();
foreach (var site in sites)
{
var siteUrl = siteInformation.SiteUrl.ToString();
siteUrls.Add(new()
if (site.Url != null)
{
Text = siteUrl,
Value = siteUrl
});

var hostUrls = siteInformation.Hosts
.Where(host => ShouldAddToSiteHosts(host, siteInformation))
.Select(host => host.GetUri())
.Select(hostUri => new SelectListItem { Text = hostUri.ToString(), Value = hostUri.ToString() });
siteUrls.AddRange(hostUrls);
}

SiteHosts = siteUrls;
}
urls.Add(new SelectListItem { Text = site.Url.Host, Value = site.Url.Host });
}

private static bool ShouldAddToSiteHosts(HostDefinition host, SiteDefinition siteInformation)
{
if (host.Name == "*")
{
return false;
foreach (var host in site.Hosts.Where(x => x.Url != null))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Two behaviour changes worth a look:

  1. The application's primary URL (IRoutableApplication.Url) is no longer added — only per-host URLs are listed. The old code added SiteUrl explicitly, so a routable app whose primary URL isn't also represented as a Host entry will drop out of the dropdown.
  2. The de-dup that the old ShouldAddToSiteHosts provided (skipping a host equal to the site URL) is gone, so duplicate entries are now possible.

Also, with ShouldAddToSiteHosts removed, UriComparer looks unused now — consider deleting it as well (like HostDefinitionExtensions).

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Improved.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reproduced locally on this branch. With the current LoadSiteHosts, the primary application entry still breaks sitemap generation, while the per-host entry works:

http://localhost:7235/sitemap.xml → Success
localhost:5127/sitemap.xml → An error occurred while generating sitemap: Invalid URI: The format of the URI could not be determined. (primary entry: scheme-less)

Root cause: the primary entry stores Value = site.Url.Host, which is a bare host with no scheme. That value is bound to SitemapViewModel.SiteUrl → SitemapData.SiteUrl, and SitemapXmlGenerator.Generate does new Uri(SitemapData.SiteUrl), which requires an absolute URI. The host entries work because they use the full host.Url.ToString().

Fix — store the full absolute URL for the primary entry too:

// keep .Host for the display Text if you want a shorter label, but Value must be absolute
urls.Add(new SelectListItem { Text = site.Url.Host, Value = site.Url.ToString() });

{
if (UriComparer.SchemeAndServerEquals(site.Url, host.Url))
{
continue;
}

urls.Add(new SelectListItem
{
Text = host.Url!.ToString(),
Value = host.Url!.ToString()
});
}
}
return !UriComparer.SchemeAndServerEquals(host.GetUri(), siteInformation.SiteUrl);
SiteHosts = urls;
}

private void PopulateHostListControl(string selected = null)
Expand Down
20 changes: 15 additions & 5 deletions src/Geta.Optimizely.Sitemaps/Models/SitemapViewModel.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
using System;
using System.Collections.Generic;
using EPiServer;
using EPiServer.Applications;
using EPiServer.DataAbstraction;
using EPiServer.Web;
using Geta.Mapping;
using Geta.Optimizely.Sitemaps.Entities;

Expand Down Expand Up @@ -30,10 +31,12 @@ public class SitemapViewModel
public class MapperFromEntity : Mapper<SitemapData, SitemapViewModel>
{
private readonly ILanguageBranchRepository _languageBranchRepository;
private readonly IApplicationResolver _applicationResolver;

public MapperFromEntity(ILanguageBranchRepository languageBranchRepository)
public MapperFromEntity(ILanguageBranchRepository languageBranchRepository, IApplicationResolver applicationResolver)
{
_languageBranchRepository = languageBranchRepository;
_applicationResolver = applicationResolver;
}

public override void Map(SitemapData @from, SitemapViewModel to)
Expand All @@ -57,7 +60,7 @@ public override void Map(SitemapData @from, SitemapViewModel to)

private string GetLanguage(string language)
{
if (string.IsNullOrWhiteSpace(language) || SiteDefinition.WildcardHostName.Equals(language))
if (string.IsNullOrWhiteSpace(language))
{
return string.Empty;
}
Expand All @@ -75,9 +78,16 @@ private string GetSitemapUrl(SitemapData sitemapData)
return $"{sitemapData.SiteUrl}{language}{sitemapData.Host}";
}

var site = SiteDefinition.Current.SiteUrl.ToString();
var siteUrl = new Url(sitemapData.SiteUrl);
var app = _applicationResolver.GetByHostname(siteUrl.Host, true).Application;

return $"{site}{language}{sitemapData.Host}";
if (app is IRoutableApplication site)
{
return $"{site.Url}{language}{sitemapData.Host}";
}

site = _applicationResolver.GetByContext() as IRoutableApplication;
return site != null ? $"{site.Url}{language}{sitemapData.Host}" : string.Empty;
}

private static string GetRelativePathEditPart(string hostName)
Expand Down
24 changes: 11 additions & 13 deletions src/Geta.Optimizely.Sitemaps/Repositories/SitemapRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,27 +5,27 @@
using System.Collections.Generic;
using System.Linq;
using EPiServer;
using EPiServer.Applications;
using EPiServer.Data;
using EPiServer.DataAbstraction;
using EPiServer.Web;
using Geta.Optimizely.Sitemaps.Entities;

namespace Geta.Optimizely.Sitemaps.Repositories
{
public class SitemapRepository : ISitemapRepository
{
private readonly ILanguageBranchRepository _languageBranchRepository;
private readonly ISiteDefinitionResolver _siteDefinitionResolver;
private readonly IApplicationResolver _applicationResolver;
private readonly ISitemapLoader _sitemapLoader;


public SitemapRepository(
ILanguageBranchRepository languageBranchRepository,
ISiteDefinitionResolver siteDefinitionResolver,
IApplicationResolver applicationResolver,
ISitemapLoader sitemapLoader)
{
_languageBranchRepository = languageBranchRepository ?? throw new ArgumentNullException(nameof(languageBranchRepository));
_siteDefinitionResolver = siteDefinitionResolver ?? throw new ArgumentNullException(nameof(siteDefinitionResolver));
_applicationResolver = applicationResolver ?? throw new ArgumentNullException(nameof(applicationResolver));
_sitemapLoader = sitemapLoader ?? throw new ArgumentNullException(nameof(sitemapLoader));
}

Expand All @@ -46,21 +46,19 @@ public SitemapData GetSitemapData(string requestUrl)
// contains the sitemap URL, for example en/sitemap.xml
var host = url.Path.TrimStart('/').ToLowerInvariant();

//Get the site based on just the host
var siteDefinition = _siteDefinitionResolver.GetByHostname(url.Host, true, out _);
if (siteDefinition == null)
{
//If that didn't work, also include the port
siteDefinition = _siteDefinitionResolver.GetByHostname($"{url.Host}:{url.Port}", true, out _);
}
if (siteDefinition == null)
// First attempt to get the site based on just the host.
// If that fails, try to include the port and fallback to default if none is found.
var app = _applicationResolver.GetByHostname(url.Host, false).Application ??
_applicationResolver.GetByHostname($"{url.Host}:{url.Port}", true).Application;
Comment thread
OddSkancke marked this conversation as resolved.

if (app is not IRoutableApplication site)
{
return null;
}

var sitemapData = GetAllSitemapData()?.Where(x =>
GetHostWithLanguage(x) == host &&
(x.SiteUrl == null || siteDefinition.Hosts.Any(h => h.Name == new Url(x.SiteUrl).Authority))).ToList();
(x.SiteUrl == null || site.Hosts.Any(h => h.Authority == new Url(x.SiteUrl).Authority))).ToList();

if (sitemapData?.Count == 1)
{
Expand Down
3 changes: 1 addition & 2 deletions src/Geta.Optimizely.Sitemaps/SitemapCreateJob.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
using System.Linq;
using System.Text;
using EPiServer.Framework.Cache;
using EPiServer.PlugIn;
using EPiServer.Scheduler;
using Geta.Optimizely.Sitemaps.Entities;
using Geta.Optimizely.Sitemaps.Repositories;
Expand All @@ -15,7 +14,7 @@

namespace Geta.Optimizely.Sitemaps
{
[ScheduledPlugIn(GUID = "EC74D2A3-9D77-4265-B4FF-A1935E3C3110", DisplayName = "Generate search engine sitemaps")]
[ScheduledJob(GUID = "EC74D2A3-9D77-4265-B4FF-A1935E3C3110", DisplayName = "Generate search engine sitemaps")]
public class SitemapCreateJob : ScheduledJobBase
{
public const string SitemapGenerationCacheKey = "SitemapGenerationKey";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@
using System.Xml;
using System.Xml.Serialization;
using EPiServer.Core;
using EPiServer.PlugIn;
using EPiServer.DataAnnotations;

namespace Geta.Optimizely.Sitemaps.SpecializedProperties
{
[PropertyDefinitionTypePlugIn(DisplayName = "SEOSitemaps")]
[PropertyDefinitionType(DisplayName = "SEOSitemaps")]
public class PropertySEOSitemaps : PropertyString
{
public const string PropertyName = "SEOSitemaps";
Expand Down
2 changes: 1 addition & 1 deletion src/Geta.Optimizely.Sitemaps/Utils/ContentFilter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ public virtual bool ShouldExcludeContent(IContent content)
return false;
}

public virtual bool ShouldExcludeContent(CurrentLanguageContent languageContentInfo, SiteDefinition siteSettings, SitemapData sitemapData)
public virtual bool ShouldExcludeContent(CurrentLanguageContent languageContentInfo, SitemapData sitemapData)
{
return ShouldExcludeContent(languageContentInfo.Content);
}
Expand Down
23 changes: 0 additions & 23 deletions src/Geta.Optimizely.Sitemaps/Utils/HostDefinitionExtensions.cs

This file was deleted.

4 changes: 1 addition & 3 deletions src/Geta.Optimizely.Sitemaps/Utils/IContentFilter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,13 @@
// Licensed under Apache-2.0. See the LICENSE file in the project root for more information

using EPiServer.Core;
using EPiServer.Web;
using Geta.Optimizely.Sitemaps.Entities;

namespace Geta.Optimizely.Sitemaps.Utils
{
public interface IContentFilter
{
bool ShouldExcludeContent(IContent content);
bool ShouldExcludeContent(
CurrentLanguageContent languageContentInfo, SiteDefinition siteSettings, SitemapData sitemapData);
bool ShouldExcludeContent(CurrentLanguageContent languageContentInfo, SitemapData sitemapData);
}
}
Loading