I have a site where nodes of type 'Course' that are placed under a parent of type 'Courses'.
Each Course has a category.
But at the moment the url of a course works in both these situation:
DOMAIN/courses/course
DOMAIN/courses/category/course
I want only option 2 to be valid.
I have a IContentFinder and a IUrlProvider.
But i can figure out how to change these to only allow option 2.
Can anyone help?
IUrlProvider
namespace Website.UrlProviders
{
public class CoursesWithCategoryUrlProvider : IUrlProvider
{
public string GetUrl(UmbracoContext umbracoContext, int id, Uri current, UrlProviderMode mode)
{
var content = umbracoContext.ContentCache.GetById(id);
if (content != null && content.DocumentTypeAlias == Course.ModelTypeAlias)
{
if (content is Course course)
{
var category = course?.Categories?.Last();
if (category == null) return null;
return $"/{CourseContants.UrlSegmentName}/{category.UrlName}/{course.UrlName}";
}
}
return null;
}
public IEnumerable<string> GetOtherUrls(UmbracoContext umbracoContext, int id, Uri current)
{
return Enumerable.Empty<string>();
}
}
}
IContentFinder
namespace Website.ContentFinders
{
public class CoursesWithCategoryContentFinder : IContentFinder
{
public bool TryFindContent(PublishedContentRequest contentRequest)
{
if (contentRequest == null) return false;
var pathValues = contentRequest.Uri
.GetAbsolutePathDecoded()
.Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries);
if(pathValues.Length == 3 && pathValues.First().Equals(CourseContants.UrlSegmentName))
{
var course = UmbracoContext.Current.ContentCache?
.GetByXPath(CourseContants.XPathChildren)?
.Where(x => x.UrlName.Equals(pathValues.Last()))?
.FirstOrDefault();
if (course != null)
{
contentRequest.PublishedContent = course;
}
}
return contentRequest.PublishedContent != null;
}
}
}
If your CoursesWithCategoryContentFinder IContentFinder is registered in the ContentFinderCollection 'before' the core's default ContentFinderByUrl IContentFinder, then you have the chance to handle the shorter version of the Url too
What's happening at the moment is your
/courses/course
request isn't being handled by your CoursesWithCategoryContentFinder... either because it's being handled first by ContentFinderByUrl or it is falling through your CoursesWithCategoryContentFinder (because it's path length when split will be less than 3) and then it is being handled by the ContentFinderByUrl.
So if you ensure your CoursesWithCategoryContentFinder is ahead of the ContentFinderByUrl
and then add a further check to see if the length of the paths is 2, and that the last item is a course, you can then issue a 301 redirect to the desired category version of the Url, (or return a 404) ... but if you do nothing and return false, the pesky default ContentFinderByUrl will find it...!
... I'm guessing a course can be in more than one category? otherwise you could structure your content tree /courses/category/course ?
IContentFinder
Hi,
I have a site where nodes of type 'Course' that are placed under a parent of type 'Courses'.
Each Course has a category.
But at the moment the url of a course works in both these situation:
I want only option 2 to be valid. I have a IContentFinder and a IUrlProvider. But i can figure out how to change these to only allow option 2.
Can anyone help?
IUrlProvider
IContentFinder
HI Peter
If your CoursesWithCategoryContentFinder IContentFinder is registered in the ContentFinderCollection 'before' the core's default ContentFinderByUrl IContentFinder, then you have the chance to handle the shorter version of the Url too
What's happening at the moment is your
/courses/course
request isn't being handled by your CoursesWithCategoryContentFinder... either because it's being handled first by ContentFinderByUrl or it is falling through your CoursesWithCategoryContentFinder (because it's path length when split will be less than 3) and then it is being handled by the ContentFinderByUrl.
So if you ensure your CoursesWithCategoryContentFinder is ahead of the ContentFinderByUrl
and then add a further check to see if the length of the paths is 2, and that the last item is a course, you can then issue a 301 redirect to the desired category version of the Url, (or return a 404) ... but if you do nothing and return false, the pesky default ContentFinderByUrl will find it...!
... I'm guessing a course can be in more than one category? otherwise you could structure your content tree /courses/category/course ?
regards
Marc
is working on a reply...