Skip to content

Commit e486b38

Browse files
committed
Enhance breadcrumb handling and layout updates
- Improved `GenerateBreadcrumbs` method in `BreadcrumbHelper.cs` to better manage Razor Pages and streamline breadcrumb generation. - Updated HTML structure and styling in `_Breadcrumb.cshtml` for improved visual integration with the dark theme. - Adjusted breadcrumb placement and added CSS styles in `_Layout.cshtml` for better mobile and desktop responsiveness. - Applied similar changes to `_LayoutPivot.cshtml` for consistency. - Modified `robots.txt` to disallow access to `/MvcEmployee/` while allowing `/api/` endpoints for better search engine indexing.
1 parent 66b4ecb commit e486b38

File tree

6 files changed

+157
-66
lines changed

6 files changed

+157
-66
lines changed

Mwh.Sample.Web/Helpers/BreadcrumbHelper.cs

Lines changed: 32 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ public static class BreadcrumbHelper
1414
public static List<(string Name, string Url)> GenerateBreadcrumbs(ViewContext viewContext)
1515
{
1616
var breadcrumbs = new List<(string Name, string Url)>();
17-
17+
1818
// Always start with Home
1919
breadcrumbs.Add(("Home", "/"));
2020

@@ -23,7 +23,35 @@ public static class BreadcrumbHelper
2323
var actionName = viewContext.RouteData.Values["action"]?.ToString();
2424
var idValue = viewContext.RouteData.Values["id"]?.ToString();
2525

26-
// Skip if we're already on the home page
26+
// Handle Razor Pages first - check if this is a Razor Page request
27+
var isRazorPage = viewContext.ActionDescriptor.DisplayName?.Contains("Pages") == true ||
28+
viewContext.HttpContext.Request.Path.Value?.Contains("/EmployeeRazor") == true ||
29+
viewContext.ActionDescriptor.GetType().Name.Contains("CompiledPageActionDescriptor");
30+
31+
if (isRazorPage)
32+
{
33+
breadcrumbs.Add(("Employee Razor Pages", "/EmployeeRazor"));
34+
35+
var path = viewContext.HttpContext.Request.Path.Value;
36+
var pageName = path?.Split('/', StringSplitOptions.RemoveEmptyEntries).LastOrDefault();
37+
38+
// Handle the case where URL is just /EmployeeRazor (Index page)
39+
if (string.IsNullOrEmpty(pageName) || pageName.Equals("EmployeeRazor", StringComparison.OrdinalIgnoreCase))
40+
{
41+
// This is the Index page, we already have the breadcrumbs we need
42+
return breadcrumbs;
43+
}
44+
45+
// Handle other pages (Create, Edit, Details, Delete, etc.)
46+
if (!string.IsNullOrEmpty(pageName))
47+
{
48+
AddPageBreadcrumb(breadcrumbs, pageName, idValue);
49+
}
50+
51+
return breadcrumbs;
52+
}
53+
54+
// Skip if we're already on the home page (for regular MVC controllers)
2755
if (string.IsNullOrEmpty(controllerName) || controllerName.Equals("Home", StringComparison.OrdinalIgnoreCase))
2856
{
2957
if (string.IsNullOrEmpty(actionName) || actionName.Equals("Index", StringComparison.OrdinalIgnoreCase))
@@ -66,21 +94,6 @@ public static class BreadcrumbHelper
6694
break;
6795
}
6896

69-
// Handle Razor Pages
70-
if (viewContext.ActionDescriptor.DisplayName?.Contains("Pages") == true ||
71-
viewContext.HttpContext.Request.Path.Value?.Contains("/EmployeeRazor") == true)
72-
{
73-
breadcrumbs.Clear();
74-
breadcrumbs.Add(("Home", "/"));
75-
breadcrumbs.Add(("Employee Razor Pages", "/EmployeeRazor"));
76-
77-
var pageName = viewContext.HttpContext.Request.Path.Value?.Split('/').LastOrDefault();
78-
if (!string.IsNullOrEmpty(pageName) && !pageName.Equals("EmployeeRazor", StringComparison.OrdinalIgnoreCase))
79-
{
80-
AddPageBreadcrumb(breadcrumbs, pageName, idValue);
81-
}
82-
}
83-
8497
return breadcrumbs;
8598
}
8699

@@ -170,7 +183,7 @@ private static string FormatActionName(string actionName)
170183
{
171184
"Create" => "Create",
172185
"Edit" => "Edit",
173-
"Details" => "Details",
186+
"Details" => "Details",
174187
"Delete" => "Delete",
175188
_ => actionName
176189
};
@@ -186,7 +199,7 @@ private static string FormatPageName(string pageName)
186199
"Create" => "Create",
187200
"Edit" => "Edit",
188201
"Details" => "Details",
189-
"Delete" => "Delete",
202+
"Delete" => "Delete",
190203
_ => pageName
191204
};
192205
}

Mwh.Sample.Web/Helpers/StructuredDataHelper.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ public static string GenerateWebSiteSchema(string baseUrl)
5858
type = "SearchAction",
5959
target = new
6060
{
61-
type = "EntryPoint",
61+
type = "EntryPoint",
6262
urlTemplate = $"{baseUrl}/search?q={{search_term_string}}"
6363
},
6464
queryInput = "required name=search_term_string"

Mwh.Sample.Web/Views/Shared/_Breadcrumb.cshtml

Lines changed: 32 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -5,36 +5,38 @@
55

66
@if (breadcrumbs.Count > 1)
77
{
8-
<nav aria-label="breadcrumb" class="mb-4">
9-
<ol class="breadcrumb bg-light rounded p-3 shadow-sm">
10-
@for (int i = 0; i < breadcrumbs.Count; i++)
11-
{
12-
var breadcrumb = breadcrumbs[i];
13-
var isLast = i == breadcrumbs.Count - 1;
8+
<nav aria-label="breadcrumb" class="breadcrumb-nav bg-dark border-top border-secondary py-2">
9+
<div class="container">
10+
<ol class="breadcrumb mb-0">
11+
@for (int i = 0; i < breadcrumbs.Count; i++)
12+
{
13+
var breadcrumb = breadcrumbs[i];
14+
var isLast = i == breadcrumbs.Count - 1;
1415

15-
<li class="breadcrumb-item @(isLast ? "active" : "")" @(isLast ? "aria-current=\"page\"" : "")>
16-
@if (isLast)
17-
{
18-
<span class="text-muted">
19-
<i class="bi bi-geo-alt-fill me-1"></i>@breadcrumb.Name
20-
</span>
21-
}
22-
else
23-
{
24-
<a href="@breadcrumb.Url" class="text-decoration-none">
25-
@if (i == 0)
26-
{
27-
<i class="bi bi-house-door-fill me-1"></i>
28-
}
29-
else
30-
{
31-
<i class="bi bi-chevron-right me-1"></i>
32-
}
33-
@breadcrumb.Name
34-
</a>
35-
}
36-
</li>
37-
}
38-
</ol>
16+
<li class="breadcrumb-item @(isLast ? "active" : "")" @(isLast ? "aria-current=\"page\"" : "")>
17+
@if (isLast)
18+
{
19+
<span class="text-light">
20+
<i class="bi bi-geo-alt-fill me-1"></i>@breadcrumb.Name
21+
</span>
22+
}
23+
else
24+
{
25+
<a href="@breadcrumb.Url" class="text-decoration-none text-light">
26+
@if (i == 0)
27+
{
28+
<i class="bi bi-house-door-fill me-1"></i>
29+
}
30+
else
31+
{
32+
<i class="bi bi-chevron-right me-1"></i>
33+
}
34+
@breadcrumb.Name
35+
</a>
36+
}
37+
</li>
38+
}
39+
</ol>
40+
</div>
3941
</nav>
4042
}

Mwh.Sample.Web/Views/Shared/_Layout.cshtml

Lines changed: 42 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,19 +8,54 @@
88
<!DOCTYPE html>
99
<html lang="en" class="h-100" data-bs-theme="@(BootswatchThemeHelper.GetCurrentColorMode(Context))">
1010

11-
<head> @await Html.PartialAsync("Sections/_metatags")
12-
11+
<head>
12+
@await Html.PartialAsync("Sections/_metatags")
1313
<!-- CSS -->
1414
<link id="bootswatch-theme-stylesheet" rel="stylesheet" href="@themeUrl" />
1515
<link rel="stylesheet" href="/lib/bootstrap-icons/font/bootstrap-icons.css" />
1616
<link rel="stylesheet" href="/lib/datatables.net-bs/css/dataTables.bootstrap5.min.css" />
17-
17+
<style>
18+
/* Responsive navbar offset - account for main nav + breadcrumb */
19+
body.d-flex {
20+
padding-top: 0;
21+
}
22+
23+
/* Mobile navbar offset - account for both nav and breadcrumb */
24+
@@media (max-width: 991.98px) {
25+
main.flex-shrink-0 {
26+
margin-top: 96px;
27+
/* Increased to account for breadcrumb */
28+
}
29+
}
30+
31+
/* Desktop navbar offset - account for both nav and breadcrumb */
32+
@@media (min-width: 992px) {
33+
main.flex-shrink-0 {
34+
margin-top: 104px;
35+
/* Increased to account for breadcrumb */
36+
}
37+
}
38+
39+
/* Remove spacing between navbar and breadcrumb */
40+
.breadcrumb-nav {
41+
border-top: 1px solid rgba(255, 255, 255, 0.1);
42+
}
43+
44+
/* Custom breadcrumb styling for dark theme */
45+
.breadcrumb-nav .breadcrumb-item+.breadcrumb-item::before {
46+
color: rgba(255, 255, 255, 0.5);
47+
}
48+
49+
.breadcrumb-nav .breadcrumb a:hover {
50+
color: rgba(255, 255, 255, 0.8) !important;
51+
}
52+
</style>
1853
@RenderSection("HeadScripts", required: false)
1954
</head>
2055

2156
<body id="page-top" class="d-flex flex-column h-100">
22-
<header>
23-
<nav class="navbar navbar-expand-lg navbar-dark bg-dark fixed-top shadow" id="mainNav">
57+
<header class="fixed-top shadow">
58+
<nav class="navbar navbar-expand-lg navbar-dark bg-dark mb-0" id="mainNav">
2459
<div class="container">
2560
<a class="navbar-brand d-flex align-items-center" href="/">
2661
<i class="bi bi-code-square me-2"></i>
@@ -81,11 +116,11 @@
81116
</div>
82117
</div>
83118
</nav>
119+
@await Html.PartialAsync("_Breadcrumb")
84120
</header>
85121

86122
<main role="main" class="flex-shrink-0">
87-
<div class="container-fluid py-5 mt-5">
88-
@await Html.PartialAsync("_Breadcrumb")
123+
<div class="container-fluid py-4">
89124
@RenderBody()
90125
</div>
91126
</main>
@@ -103,4 +138,3 @@
103138
</body>
104139

105140
</html>
106-

Mwh.Sample.Web/Views/Shared/_LayoutPivot.cshtml

Lines changed: 49 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,65 @@
1-
@{
1+
@inject StyleCache StyleCache
2+
@{
23
var currentYear = DateTime.Now.Year.ToString();
34
var status = new ApplicationStatus(Assembly.GetExecutingAssembly());
5+
var themeName = BootswatchThemeHelper.GetCurrentThemeName(Context);
6+
var themeUrl = BootswatchThemeHelper.GetThemeUrl(StyleCache, themeName);
47
}
58
<!DOCTYPE html>
6-
<html lang="en" class="h-100">
9+
<html lang="en" class="h-100" data-bs-theme="@(BootswatchThemeHelper.GetCurrentColorMode(Context))">
710

811
<head>
912
@await Html.PartialAsync("Sections/_metatags")
1013

1114
<!-- CSS -->
12-
<link rel="stylesheet" href="/lib/bootstrap/dist/css/bootstrap.min.css" />
15+
<link id="bootswatch-theme-stylesheet" rel="stylesheet" href="@themeUrl" />
1316
<link rel="stylesheet" href="/lib/bootstrap-icons/font/bootstrap-icons.css" />
1417
<link rel="stylesheet" href="~/css/site.css" asp-append-version="true" />
1518
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/pivottable/2.13.0/pivot.min.css" />
1619

20+
<style>
21+
/* Responsive navbar offset - account for main nav + breadcrumb */
22+
body.d-flex {
23+
padding-top: 0;
24+
}
25+
26+
/* Mobile navbar offset - account for both nav and breadcrumb */
27+
@@media (max-width: 991.98px) {
28+
main.flex-shrink-0 {
29+
margin-top: 96px;
30+
/* Increased to account for breadcrumb */
31+
}
32+
}
33+
34+
/* Desktop navbar offset - account for both nav and breadcrumb */
35+
@@media (min-width: 992px) {
36+
main.flex-shrink-0 {
37+
margin-top: 104px;
38+
/* Increased to account for breadcrumb */
39+
}
40+
}
41+
42+
/* Remove spacing between navbar and breadcrumb */
43+
.breadcrumb-nav {
44+
border-top: 1px solid rgba(255, 255, 255, 0.1);
45+
}
46+
47+
/* Custom breadcrumb styling for dark theme */
48+
.breadcrumb-nav .breadcrumb-item+.breadcrumb-item::before {
49+
color: rgba(255, 255, 255, 0.5);
50+
}
51+
52+
.breadcrumb-nav .breadcrumb a:hover {
53+
color: rgba(255, 255, 255, 0.8) !important;
54+
}
55+
</style>
56+
1757
@RenderSection("HeadScripts", required: false)
1858
</head>
1959

2060
<body id="page-top" class="d-flex flex-column h-100">
21-
<header>
22-
<nav class="navbar navbar-expand-lg navbar-dark bg-dark fixed-top shadow" id="mainNav">
61+
<header class="fixed-top shadow">
62+
<nav class="navbar navbar-expand-lg navbar-dark bg-dark mb-0" id="mainNav">
2363
<div class="container">
2464
<a class="navbar-brand d-flex align-items-center" href="/">
2565
<i class="bi bi-code-square me-2"></i>
@@ -76,14 +116,15 @@
76116
</a>
77117
</li>
78118
</ul>
119+
<bootswatch-theme-switcher />
79120
</div>
80121
</div>
81122
</nav>
123+
@await Html.PartialAsync("_Breadcrumb")
82124
</header>
83125

84126
<main role="main" class="flex-shrink-0">
85-
<div class="container-fluid py-5 mt-5">
86-
@await Html.PartialAsync("_Breadcrumb")
127+
<div class="container-fluid py-4">
87128
@RenderBody()
88129
</div>
89130
</main>
@@ -95,6 +136,7 @@
95136
<!-- JavaScript Bundle -->
96137
<script src="~/lib/jquery/jquery.js" asp-append-version="true"></script>
97138
<script src="~/lib/bootstrap/dist/js/bootstrap.bundle.min.js" crossorigin="anonymous"></script>
139+
<script src="/_content/WebSpark.Bootswatch/js/bootswatch-theme-switcher.js"></script>
98140
<script src="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.11.4/jquery-ui.min.js"></script>
99141
<script
100142
src="https://cdnjs.cloudflare.com/ajax/libs/jqueryui-touch-punch/0.2.3/jquery.ui.touch-punch.min.js"></script>
@@ -105,4 +147,3 @@
105147
</body>
106148

107149
</html>
108-

Mwh.Sample.Web/wwwroot/robots.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ Allow: /
1111
# Disallow admin and API documentation areas
1212
Disallow: /swagger/
1313
Disallow: /health
14+
Disallow /MvcEmployee/
1415
1516
# Allow API endpoints for public access
1617
Allow: /api/

0 commit comments

Comments
 (0)