Problem is I just cannot get it to work, my last attempt was:
namespace Web.Model.Breadcrumbs
{
public class test
{
public string tests()
{
IPublishedContent content = null;
var yy = content.Children.DescendantsOrSelf("-1").Select(x => x.Ancestors());
return null;
}
}
public class WebsiteBreadcrumbs
{
public string SiteBreadcrumbs()
{
var test = new UmbracoHelper();
var selection = test.Ancestors().ToList();
StringBuilder sb = new StringBuilder();
if (selection.Any())
{
sb.Append("<ul>");
foreach (var links in selection)
{
sb.AppendLine("<li>" + links + "</li>");
}
sb.Append(CurrentPage.Name);
sb.Append("/ul>");
}
return "test";
//}
}
}
}
All the above fail, can any help with this
Thanks
George
Before we get into this, why aren't you happy with the Partial View that you have? When else are you going to need the "breadcrumbs"?
Personally, I think what you currently have works pretty well for a breadcrumb process. You can simply call the your partial view on any page and it will work.
Looking at your code, you've got a bit of conflicting code present, in addition, you never pass in your current page anywhere as a result the breadcrumbs have nowhere to identify what they are doing.
If you modify your "WebsiteBreadcrumbs" class as follows:
public static class WebsiteBreadcrumbs
{
public string SiteBreadcrumbs(IPublishedContent currentPage)
{
var selection = currentPage.Ancestors().ToList();
StringBuilder sb = new StringBuilder();
if (selection.Any())
{
sb.Append("<ul>");
foreach (var links in selection)
{
sb.AppendLine("<li>" + links + "</li>");
}
sb.Append(currentPage.Name);
sb.Append("/ul>");
}
return sb.ToString();
}
}
You can then call WebsiteBreadcrumbs.SiteBreadCrumbs(Model.Content) on any template that inherits from UmbracoTemplatePage and it should give you an output. Assuming that Model.Content is not null.
I used Ronald's simple breadcrumbs navigation and I ran into a problem because in the design I have, they are supposed to be in Nested Content and 'Model' in NC means nothing. So I did this:
@inherits Umbraco.Web.Mvc.UmbracoViewPage
@{
var currentPageId = Umbraco.UmbracoContext.PageId;
var currentPage = Umbraco.Content(currentPageId);
}
@foreach (var content in currentPage.Ancestors().Reverse())
{
<a class="breadcrumb" href="@content.Url">
@content.Name
</a>
}
<span class="breadcrumb">@currentPage.Name</span>
Now, the breadcrumbs don't actually care if Model is there or not. They will just pick up the current document type and let you work your magic.
Although this works, you shouldn't really be doing it this way. The use of Umbraco.Content results in a dynamic object being returned and this isn't advised any more. You also have an unnecessary step in your code, I believe you could simplify this as follows:
@inherits Umbraco.Web.Mvc.UmbracoViewPage
@foreach(var content in Umbraco.AssignedContentItem.Ancestors().Reverse())
{
//put your rendering code here
}
<span class="breadcrumb">@Umbraco.AssignedContentItem.Name</span>
I've not tested this fully, but the premise behind it is that AssignedContentItem (it might be AssignedContent, I can't remember) should already have your current page as an IPublishedContent item. You can then use this to get ancestors, and do the reverse of the enumerable it results in. This saves you getting the ID from context and then getting the dynamic object from the Umbraco helper.
You were right about the dynamic object being returned, but your code had the same problem as the first breadcrumbs (looking into nested content instead of the actual document type/page).
So instead of returning a dynamic object I changed:
var currentPage = Umbraco.Content(currentPageId);
to:
var currentPage = Umbraco.TypedContent(currentPageId);
And now it returns IPublishedContent
Thanks for the help! Cheers!
Final code is:
@inherits Umbraco.Web.Mvc.UmbracoViewPage
@{
var currentPageId = Umbraco.UmbracoContext.PageId;
var currentPage = Umbraco.TypedContent(currentPageId);
}
@foreach (var content in currentPage.Ancestors().Reverse())
{
<a class="breadcrumb" href="@content.Url">@content.Name ></a>
}
<span class="breadcrumb">@currentPage.Name</span>
P.S. If you see anything else wrong in my code, please let me know.
Not sure what you mean with 'pass the .Name for the content all the way down', but it just gets all ancestors (if you're currently on 'Grandchild', that would be 'Child' and 'Start'), reverses it (so you get 'Start' and then 'Child') and then renders a link for every ancestor (as these are IPublishedContent, you can just use the Name and Url properties).
The thing is that we have a parent (Start) that has a child (Aktiviteter) and a grand child (Frukostmöten). The child and the grand child uses the same template (defaultpagetemplate), but the bread crumbs only works at the child and not the grand child. Any ideas on how to solve this?
If nothing is rendered, you probably have a condition somewhere that just prevents it from executing... Otherwise, when using Umbraco 8 and especially with culture variants, it might even be a bug in how the ancestors are fetched...
I have one section on the website where the bread crumbs works on the grand child as well. The thing that stands out here is that the grand child doesn't have the same template as the other grand childs (defaultpagetemplate). Could it be that I need to use a different template for the grand children to make this work?
@nik Umbraco.AssignedContentItem doesn't work inside partials rendering Nested Content items, but UmbracoContext.PublishedContentRequest.PublishedContent does get the current page.
Not sure why you would have a NC item for rendering the breadcrumb, as you probably want to have it on a fixed place in the site and don't want editors forget adding it, moving it to a different place or even add multiple breadcrumbs to a page...
I personally like to create an Html Helper class which I can call from wherever I want like this
@Html.Breadcrumb(Model.Content)
Here is the code I like to use:
using System.Collections.Generic;
using System.Text;
using System.Web;
using System.Web.Mvc;
using Umbraco.Core.Models;
using Umbraco.Web;
namespace CodeShare.Library.Helpers.General
{
public static class HtmlExtensions
{
public static IHtmlString Breadcrumb(this HtmlHelper helper, IPublishedContent thisPage)
{
StringBuilder breadcrumb = new StringBuilder();
IEnumerable<IPublishedContent> ancestors = thisPage.Ancestors().Reverse();
foreach(IPublishedContent page in ancestors)
{
breadcrumb.Append($"<a href=\"{page.Url}\">{page.Name}</a>");
}
breadcrumb.Append($"<span>{thisPage.Name}</span>");
return MvcHtmlString.Create(breadcrumb.ToString());
}
}
}
Big fan of your work by the way since I basically learned how to use Umbraco from your tutorials.
I like the extension, but the boss has decided that we're going on a view only kind of approach since we have a lot of time pressuring us. I'm definitely going to use it at some point later on though. Thanks for the reply.
I used 'Level' as this code is for Umbraco 8 and was written when I was playing about, Umbraco.TypedContent does not work in V8 as it returns:
UmbracoHelper' does not contain a definition for 'TypedContent' and no
accessible extension method 'TypedContent' accepting a first argument
of type 'UmbracoHelper'
Breadcrumb using c# class
Hi
I currently have the following for creating breadcrumbs:
What I want is to move the above code and put it into a .cs class so that the partial that contains the above will look something like:
Problem is I just cannot get it to work, my last attempt was:
All the above fail, can any help with this Thanks George
Hi George,
Where did you put this class?
What error exactly do you have?
Is UmbracoHelper accessible from this class?
We will fix it together :)
Thanks,
Alex
Hi Alex
No error, value is always null. Class is in another class library that has umbraco core installed.
Thanks George
Hi George,
Before we get into this, why aren't you happy with the Partial View that you have? When else are you going to need the "breadcrumbs"?
Personally, I think what you currently have works pretty well for a breadcrumb process. You can simply call the your partial view on any page and it will work.
Looking at your code, you've got a bit of conflicting code present, in addition, you never pass in your current page anywhere as a result the breadcrumbs have nowhere to identify what they are doing.
If you modify your "WebsiteBreadcrumbs" class as follows:
You can then call WebsiteBreadcrumbs.SiteBreadCrumbs(Model.Content) on any template that inherits from UmbracoTemplatePage and it should give you an output. Assuming that Model.Content is not null.
Nik
Hi Nik
The reason I wanted the code in .cs file was I learning Umbraco and thought there must be another way.
Just experimenting :)
Regards George
Nik tells the truth. Partials rock! :)
The easiest partial view could even look like this:
No
StringBuilders
or custom classes needed! ;-)I used Ronald's simple breadcrumbs navigation and I ran into a problem because in the design I have, they are supposed to be in Nested Content and 'Model' in NC means nothing. So I did this:
Now, the breadcrumbs don't actually care if Model is there or not. They will just pick up the current document type and let you work your magic.
Hi Harry,
Although this works, you shouldn't really be doing it this way. The use of
Umbraco.Content
results in a dynamic object being returned and this isn't advised any more. You also have an unnecessary step in your code, I believe you could simplify this as follows:I've not tested this fully, but the premise behind it is that AssignedContentItem (it might be AssignedContent, I can't remember) should already have your current page as an IPublishedContent item. You can then use this to get ancestors, and do the reverse of the enumerable it results in. This saves you getting the ID from context and then getting the dynamic object from the Umbraco helper.
Cheers
Nik
Hi Nik,
It doesn't work, but let me test it a little bit more, since I didn't notice the dynamic object you were talking about. Thanks for that.
Harry
Hi Nik,
You were right about the dynamic object being returned, but your code had the same problem as the first breadcrumbs (looking into nested content instead of the actual document type/page).
So instead of returning a dynamic object I changed:
to:
And now it returns
IPublishedContent
Thanks for the help! Cheers!
Final code is:
P.S. If you see anything else wrong in my code, please let me know.
Hi Ronald,
How does it work if you have a tree that looks like this:
Does the foreach loop go through the grandchild so that you can pass the .Name for the content all the way down?
Br, Arnel Gajek
Not sure what you mean with 'pass the .Name for the content all the way down', but it just gets all ancestors (if you're currently on 'Grandchild', that would be 'Child' and 'Start'), reverses it (so you get 'Start' and then 'Child') and then renders a link for every ancestor (as these are
IPublishedContent
, you can just use theName
andUrl
properties).The thing is that we have a parent (Start) that has a child (Aktiviteter) and a grand child (Frukostmöten). The child and the grand child uses the same template (defaultpagetemplate), but the bread crumbs only works at the child and not the grand child. Any ideas on how to solve this?
BTW I'm using Umbraco v.8.
Br, Arnel Gajek
If nothing is rendered, you probably have a condition somewhere that just prevents it from executing... Otherwise, when using Umbraco 8 and especially with culture variants, it might even be a bug in how the ancestors are fetched...
I have one section on the website where the bread crumbs works on the grand child as well. The thing that stands out here is that the grand child doesn't have the same template as the other grand childs (defaultpagetemplate). Could it be that I need to use a different template for the grand children to make this work?
@nik
Umbraco.AssignedContentItem
doesn't work inside partials rendering Nested Content items, butUmbracoContext.PublishedContentRequest.PublishedContent
does get the current page.Not sure why you would have a NC item for rendering the breadcrumb, as you probably want to have it on a fixed place in the site and don't want editors forget adding it, moving it to a different place or even add multiple breadcrumbs to a page...
This is the best solution ever!
I personally like to create an Html Helper class which I can call from wherever I want like this
Here is the code I like to use:
I wrote a blog post about it. You can read it here: https://codeshare.co.uk/blog/how-to-create-a-custom-html-helper-extension-method-in-mvc-and-umbraco/
Hi paul,
Big fan of your work by the way since I basically learned how to use Umbraco from your tutorials.
I like the extension, but the boss has decided that we're going on a view only kind of approach since we have a lot of time pressuring us. I'm definitely going to use it at some point later on though. Thanks for the reply.
Cheers, Harry
This works for me in a partial view
Regards George
What's the use for
counter
if it is always 1? And why useOrderBy(x => x.Level)
, if you can just reverse all items?The addition of microdata is a good one though!
Hi Ronald
I deleted some code and took out the counter++ by mistake
when added back inside foreach it returns
and if you read https://schema.org/itemListElement it explains about the position
I used 'Level' as this code is for Umbraco 8 and was written when I was playing about, Umbraco.TypedContent does not work in V8 as it returns:
You only need the
Ancestors()
method on the model (as that's the currently rendered page) and reverse the order...Umbraco 8 removed dynamics, so they changed
Umbraco.TypedContent()
back toUmbraco.Content()
, that's all!Hi Ronald
Learn something new every day, did not know it had been changed back
Regards George
If anyone wants the code I have put it below
is working on a reply...