Hello Sunny
The Alloy sample site has a breadcrumb already as shown below:
You should be able to use this code yourself in your project.
David
Let's say you want to keep IPageViewModel from Alloy.
First you need to create a view model for breadcrumbs:
public class BreadcrumbItemViewModel { public string Url { get; set; } public string Title { get; set; } }
Then update IPageViewModel:
public interface IPageViewModel<out T> where T : SitePageData { ... List<BreadcrumbItemViewModel> BreadcrumbItems { get; set; } }
Then update PageViewModel:
public class PageViewModel<T> : IPageViewModel<T> where T : SitePageData { public PageViewModel(T currentPage) { CurrentPage = currentPage; BreadcrumbItems = GetBreadcrumbItems(currentPage.ContentLink); } ... public List<BreadcrumbItemViewModel> BreadcrumbItems { get; set; } private List<BreadcrumbItemViewModel> GetBreadcrumbItems(ContentReference currentPage) { var contentLoader = ServiceLocator.Current.GetInstance<IContentLoader>(); var parents = contentLoader.GetAncestors(currentPage) .Reverse() .Cast<PageData>() .Filter(new FilterAccess(AccessLevel.Read)) .Filter(new FilterPublished()) .Filter(new FilterTemplate()); var urlResolver = ServiceLocator.Current.GetInstance<UrlResolver>(); var items = parents.Select(parent => new BreadcrumbItemViewModel { Title = parent.PageName, Url = urlResolver.GetUrl(parent.ContentLink) }).ToList(); return items; } }
Under Views / Shared, create a new partial view called _Breadcrumbs
@model IPageViewModel<SitePageData> @if (Model.BreadcrumbItems != null) { foreach (var item in Model.BreadcrumbItems) { <a href="@item.Url">@item.Title</a> @:/ } <span>@Model.CurrentPage.Name</span> }
And now you can render breadcrumbs in your layout / views like this:
@{ Html.RenderPartial("_Breadcrumbs"); }
Hope this helps!
Thanks Dejan Caric
But Evertime i am incuding this namespace @model IPageViewModel<SitePageData>" in my Breadcrumb.cshtml file
I am getting the following error
InvalidOperationException: The model item passed into the dictionary is of type 'Castle.Proxies.HomeProxy', but this dictionary requires a model item of type 'EpiServerDemo.Models.ViewModels.IPageViewModel`1[EpiServerDemo.Models.Pages.SitePageData]'.This ia causing a problem for me.
I have mentioned below my layout file
@using EPiServer.Core
@using EPiServer.Web.Mvc.Html
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<title></title>
<link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css">
<link href="/css/bootstrap.min.css" rel="stylesheet" type="text/css" />
<link href="/css/myStyle.css" rel="stylesheet" type="text/css" />
<!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries -->
<!--[if lt IE 9]>
<script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script>
<script src="https://oss.maxcdn.com/libs/respond.js/1.3.0/respond.min.js"></script>
<![endif]-->
<!--[if IE 7]>
<link rel="stylesheet" type="text/css" href="/css/ie7.css">
<![endif]-->
<script type="text/javascript" src="/js/bootstrap.collapse.js">
</head>
<body>
<script type="text/javascript">
(function (i, s, o, g, r, a, m) {
i['GoogleAnalyticsObject'] = r; i[r] = i[r] || function ()
{ (i[r].q = i[r].q || []).push(arguments) }
, i[r].l = 1 * new Date(); a = s.createElement(o),
m = s.getElementsByTagName(o)[0]; a.async = 1; a.src = g; m.parentNode.insertBefore(a, m)
})(window, document, 'script', '//www.google-analytics.com/analytics.js', 'ga');
ga('create', 'UA-4945871-5', 'auto');
ga('send', 'pageview');
</script>
<!-- header starts here-->
<div class="navbar">
<!-- headers starts-->
<div class="container">
<!--login, register and search box-->
<div class="pull-right hidden-xs hidden-sm marginTop-location">
<div class="col-xs-2 col-sm-8 col-md-9 col-lg-8 pull-left" style="padding: 0px;">
<div class="navbar-form hidden-xs hidden-sm pull-right" role="search">
<div class="input-group">
<input type="text" class="form-control srchInput" placeholder="Search" name="srch-term" id="srch-term" />
<div class="input-group-btn">
<button class="btn btn-default srchBtn" onclick="searchclick();return false;"><i class="fa fa-search" style="color:#224173;"></i></button>
</div>
</div>
</div>
</div>
<!-- search box-->
<div class="col-xs-2 col-sm-4 col-md-3 col-lg-4 pull-right" style="padding: 10px 0 0 0;">
<a id="loginlink" href="/login/">
<img src="/images/iconLogin.png" width="44" height="34" title="Login" /></a>
@* <a id="logoutlink" visible="false" href="/logout.aspx">
<img src="/images/iconLogout.png" width="44" height="34" title="Logout" /></a>
*@
<a id="registerlink" href="/register/">
<img src="/images/iconRegister.png" width="44" height="34" style="margin-left: 15px;" rel="tooltip" data-placement="bottom" title="Register" data-original-title="Register"/>
</a>
@*<a id="accountlink" visible="false" href="/myaccount/">
<img src="/images/iconMyAccount.png" width="44" height="34" style="margin-left: 15px;" rel="tooltip" data-placement="bottom" title="My Account" data-original-title="Register"/>
</a>*@
</div>
<div class="pullRight"><strong><asp:Literal ID="ltlFirstName" runat="server"></asp:Literal></strong></div>
</div>
<!--login, register and search box-->
<div class="navbar-header">
<div class="main-nav navMobile">
<button type="button" class="navbar-toggle mybutton" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" onclick="$('#bs-example-navbar-collapse-2').collapse('hide');">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<button type="button" class="navbar-toggle mybutton searchMobileBtn" data-target="#bs-example-navbar-collapse-2" onclick="$('#bs-example-navbar-collapse-1').collapse('hide');" data-toggle="collapse">
<i class="fa fa-search"></i>
</button>
<a id="mobloglink" class="navbar-toggle mybutton myAccountMobileBtn" runat="server" href="/login/">
<i class="fa fa-lock"></i>
</a>
<a id="moboutlink" class="navbar-toggle mybutton myAccountMobileBtn" runat="server" visible="false" href="/logout.aspx">
<i class="fa fa-unlock"></i>
</a>
</div>
<a class="navbar-brand" href="/">
<img class="logoPadding visible-lg visible-md" src="/images/logo.png" alt="Genteq"></a>
<a class="navbar-brand" href="/">
<img class="logoPadding visible-sm visible-xs" src="/images/logoSmall.png" alt="Genteq"></a>
</div>
<!-- nav header ends-->
</div>
<!-- header endss-->
<!-- container-->
<div class="container-full main-nav">
<div class="container">
<div class="navbar-collapse collapse myNavlist" id="bs-example-navbar-collapse-1">
@Html.Partial("~/Views/Shared/TopNav.cshtml")
@* <ul id="menunav" runat="server" class="nav navbar-nav">
<li> Products
<a data-hover=""dropdown"" data-delay=""0"" data-close-others=""false"" class="" dropdown-toggle="" >
<i class='fa fa-angle-down'></i></a>
<ul class="dropdown-menu">
<li>
<span>Applications</span>
<i class="fa fa-angle-double-right"></i>
</li>
<li>
Applications
<i class="fa fa-angle-double-right"></i>
</li>
<li>
Applications
<i class="fa fa-angle-double-right"></i>
</li>
<li>
Applications
<i class="fa fa-angle-double-right"></i>
</li>
</ul>
</li>
<li id="liRegister" runat="server" class="nav-item"><a href="/Register.aspx" class="visible-sm visible-xs">Register</a></li>
<li id="liAccount" runat="server" class="nav-item"><a href="/MyAccount.aspx" class="visible-sm visible-xs">My Account</a></li>
</ul>*@
</div>
<!--/.navbar-collapse -->
<div class="collapse navbar-collapse hidden-lg hidden-md myNavlist" id="bs-example-navbar-collapse-2">
<div class="form-horizontal">
</div>
<div class="verticalBelowSpacing10px"> </div>
</div>
<!-- /.navbar-collapse -->
</div>
</div>
<div class="container-fluid myNav-bar noMargin noPadding"> </div>
</div>
@{ Html.RenderPartial("Breadcrumbs"); }
@* @Html.Partial("~/Views/Shared/Breadcrumbs.cshtml");*@
<!--nav bar ends here-->
@* <div>
@{Html.RenderPartial("Breadcrumbs", new EpiServerDemo.Models.ViewModels.PageViewModel<EpiServerDemo.Models.Pages.SitePageData>(Model));}
</div>*@
<!-- content starts-->
<!-- header ends here-->
<div class="container wrap-content divCentreAlign Setheight "> @RenderBody() </div>
<div class="clearfix"></div>
<div class="container wrap-content divCentreAlign">
</div>
<!--footer starts-->
<div class="verticalBelowSpacing10px"></div>
@Html.Partial("~/Views/Shared/Footer.cshtml")
<!--footer endss-->
<div title="Scroll Back to Top" style="position: fixed; bottom: 5px; right: 5px; opacity: 0; cursor: pointer;" id="topcontrol"><i class="fa fa-angle-up"></i></div>
<script type="text/javascript">
function searchclick() {
var srchtext = $('input.srchInput').val();
if (srchtext.length > 0) {
srchtext = srchtext.replace("<", "").replace(">", "");
//alert(srchtext);
document.location.href = "/search.aspx?q=" + srchtext;
}
}
function searchmobclick() {
var srchtext = $('input.srchmobInput').val();
if (srchtext.length > 0) {
srchtext = srchtext.replace("<", "").replace(">", "");
document.location.href = "http://" + document.domain + "/search.aspx?q=" + srchtext;
}
}
$(document).ready(function () {
$('button.srchBtn').click(function () {
searchclick();
return false;
})
$('button.srchmobBtn').click(function () {
searchmobclick();
return false;
})
//jQuery.noConflict();
// $("[rel='tooltip']").tooltip();
$('#bs-example-navbar-collapse-2').addClass('hide in');
$('#bs-example-navbar-collapse-2').collapse('hide');
$('#bs-example-navbar-collapse-2').removeClass('hide');
$('#bs-example-navbar-collapse-1').addClass('hide in');
$('#bs-example-navbar-collapse-1').collapse('hide');
$('#bs-example-navbar-collapse-1').removeClass('hide');
});
</script>
<script type='text/javascript' src="/js/jquery-1.10.2.min.js"></script>
<script type='text/javascript' src="/js/jquery-1.8.3.min"></script>
@* <%-- <script type='text/javascript' src="http://code.jquery.com/jquery-1.8.3.min.js"></script>--%>*@
<script type='text/javascript' src="/js/jquery-1.11.0.min.js"></script>
<script type='text/javascript' src="/js/bootstrap.js"></script>
@* <%--<script type='text/javascript' src="/js/bootstrap.min.js"></script>--%>*@
@* <%--<script type="text/javascript" src="/js/bootstrap-hover-dropdown.min.js"></script>--%>*@
<script type="text/javascript" src="/js/back-to-top.js"></script>
</body>
</html>
And here is the Breadcrumb.cshtml file
@model IPageViewModel<SitePageData>
@if (Model.BreadcrumbItems != null)
{
foreach (var item in Model.BreadcrumbItems)
{
<a href="@item.Url">@item.Title</a> @:/
}
<span>@Model.CurrentPage.Name</span>
}
Can you please let me know whatelse could i be missing. I have inculded all the referrences from Alloy MVC site but still it is not working.
Hi,
Your view model is Home, and _Breadcrumbs.cshtml expects IPageViewModel<SitePageData>
In Layout, you need to define a model like this:
@model IPageViewModel<SitePageData>
I don't know how your Home controller looks like, it should be something like this:
public class HomeController : PageController<Home> { public ActionResult Index(Home currentPage) { var viewModel = new PageViewModel<Home>(currentPage); ... return View(viewModel); } }
View for Home page should be like this:
@model IPageViewModel<Home> ...
And that's it.
Of course, you don't have to use IPageViewModel.
That is just one way of solving things.
You can use Helpers like in Alloy, or extract the logic in some application service and call it for each view model:
viewModel.Breadcrumbs = _navigationService.GetBreadcrumbs(currentPage)
Hi Dejan Caric ,
I don't know why but evertime i am including this @model IPageViewModel<SitePageData> at the top of page.
I am always getting the same error. The model item passed into the dictionary is of type 'Castle.Proxies.HomeProxy', but this dictionary requires a model item of type 'EpiServerDemo.Models.ViewModels.IPageViewModel`1[EpiServerDemo.Models.Pages.SitePageData]'.This ia causing a problem for me.
My home view is actually using the layout file.
Here is my Home view
@model EpiServerDemo.Models.Pages.Home
@using EPiServer.Core
@{
ViewBag.Title = "Home";
Layout = "~/Views/Shared/Layout.cshtml";
}
<img class="logoPadding visible-lg visible-md" src="@Url.ContentUrl(@Model.PageImage)" alt="Genteq">
<div>
@Html.PropertyFor(m => m.HomeSection)
</div>
<div>
@Html.PropertyFor(m => m.LatestNewsSection)
</div>
Here is my home controller
public class HomeController : PageController<Home>
{
public ActionResult Index(Home currentPage)
{
/* Implementation of action. You can create your own view model class that you pass to the view or
* you can pass the page type for simpler templates */
var model = new Home
{
MainBody=currentPage.MainBody
};
return PartialView(currentPage);
}
}
and Here is my home model
[ContentType(DisplayName = "Home", GUID = "6c285875-1edc-4426-818f-13029f0b8afe", Description = "")]
public class Home : PageData
{
public virtual XhtmlString MainBody { get; set; }
public virtual ContentArea LatestNewsSection { get; set; }
public virtual ContentArea HomeSection { get; set; }
public virtual Url PageImage { get; set; }
/*
[CultureSpecific]
[Display(
Name = "Main body",
Description = "The main body will be shown in the main content area of the page, using the XHTML-editor you can insert for example text, images and tables.",
GroupName = SystemTabNames.Content,
Order = 1)]
public virtual XhtmlString MainBody { get; set; }
*/
}.
I probably have to go for some other alternative if the problem persists.
Your Home page type implements PageData, not SitePageData.
If you want to keep it that way, then you should change the model from:
@model IPageViewModel<SitePageData>
to
@model IPageViewModel<PageData>
in both Layout.cshtml and Breadcrumbs.cshtml
Also, in index action, you're returning wrong model
public class HomeController : PageController<Home> { public ActionResult Index(Home currentPage) { var model = new Home { MainBody=currentPage.MainBody }; return PartialView(currentPage); } }
should be changed to:
public class HomeController : PageController<Home> { public ActionResult Index(Home currentPage) { var model = new PageViewModel<Home>(currentPage); return View(model); } }
And then in index view, you should have something like this:
@model IPageViewModel<Home> @using EPiServer.Core @{ ViewBag.Title = "Home"; Layout = "~/Views/Shared/Layout.cshtml"; } <img class="logoPadding visible-lg visible-md" src="@Url.ContentUrl(@Model.CurrentPage.PageImage)" alt="Genteq"><div> @Html.PropertyFor(m => m.CurrentPage.HomeSection) </div> <div> @Html.PropertyFor(m => m.CurrentPage.LatestNewsSection) </div>
Hope this helps!
I am working on Episerver version 8.0. I am referring to Alloy MVC site to create breadcrumb for the site but some how i am getting issue while implementing the same.
Can anyone send me some code sample of how to create breadcrumb using Episerver Api's in MVC. Any help on this would be really appreciated.