Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/aws-samples/legacy-cycle-store-mvc-app/llms.txt

Use this file to discover all available pages before exploring further.

The presentation layer is a conventional ASP.NET MVC 4 application built on Razor views and the standard controller/action/view pipeline. What makes this project’s layout system distinctive is its heavy use of child actionsSiteLayoutController exposes three independent action methods (HeaderLayout, FooterLayout, ContentLayout) that the master Razor layout calls via Html.RenderAction, allowing each region of the page to fetch its own data independently of the page controller. Understanding this pattern is essential to following the flow of any page request through the application.

Routing

The application registers a single conventional route in App_Start/RouteConfig.cs:
routes.MapRoute(
    name: "Default",
    url: "{controller}/{action}/{id}",
    defaults: new { controller = "Home", action = "Default", id = UrlParameter.Optional }
);
Any URL that does not match a more specific pattern is parsed as {controller}/{action}/{id}. The defaults mean that a bare request to / resolves to HomeController.Default(). The id segment is optional, so both /Home/Default and /Home/Default/42 are valid — the latter passes 42 as the id route value. The Web API route registered in WebApiConfig.cs uses the separate prefix api/{controller}/{id} and does not overlap with the MVC route.

HomeController

HomeController has a single action that serves the homepage.
public class HomeController : Controller
{
    public ActionResult Default()
    {
        ViewBag.BodyClass = "homepage";
        return View();
    }
}
ViewBag.BodyClass is set to "homepage" so the Razor layout can apply a page-specific CSS class to the <body> element (e.g., <body class="@ViewBag.BodyClass">). The action returns View() with no explicit view name, so MVC resolves it to Views/Home/Default.cshtml by convention. Default.cshtml does not render any product data itself — it delegates entirely to the SiteLayoutController child actions for its visible content.

SiteLayoutController

SiteLayoutController acts as a data-provider for the three composable regions of the page layout. Its actions are never called directly via a top-level URL; they are invoked as child actions by Html.RenderAction calls inside the Razor views.
public class SiteLayoutController : Controller
{
    public ActionResult HeaderLayout()
    {
        SiteLayoutModel Header = new SiteLayoutModel();
        return View(Header);
    }

    public ActionResult FooterLayout()
    {
        SiteLayoutModel Footer = new SiteLayoutModel();
        Footer.ProductCategories = CategoryManager.GetMainCategories();
        return View(Footer);
    }

    public ActionResult ContentLayout()
    {
        SiteLayoutModel Header = new SiteLayoutModel();
        Header.ProductCategories = CategoryManager.GetMainCategories();
        return View(Header);
    }
}
1

HeaderLayout

Creates an empty SiteLayoutModel and passes it to Views/SiteLayout/HeaderLayout.cshtml. The header view renders the site logo and the “Unicorn Bike Rentals” banner. No category data is loaded here because the header does not display navigation links.
2

FooterLayout

Calls CategoryManager.GetMainCategories() to populate SiteLayoutModel.ProductCategories, then passes the model to Views/SiteLayout/FooterLayout.cshtml. The footer view uses the category list to render navigation links at the bottom of every page.
3

ContentLayout

Also calls CategoryManager.GetMainCategories() and passes the populated model to Views/SiteLayout/ContentLayout.cshtml. This view iterates each ProductCategory and its ProductSubcategories collection to build the category/subcategory navigation sidebar shown in the main content area.
Child actions (Html.RenderAction) are an ASP.NET MVC 4 concept that does not have a direct built-in equivalent in ASP.NET Core MVC. When migrating, each child action will need to be replaced with an alternative pattern — common choices include View Components (the closest structural equivalent, introduced in ASP.NET Core 1.0), Tag Helpers, or passing all required data through the parent controller’s view model. Plan this refactoring early: SiteLayoutController is called on every page, so its replacement will affect the entire layout system.

SiteLayoutModel

SiteLayoutModel is the single view model class used across all three layout views.
public class SiteLayoutModel
{
    public string AnonymousTemplateVisibility { get; set; }
    public string LoggedInTemplateVisibility { get; set; }
    public string LoggedInEmailID { get; set; }
    public string ShoppingCartItemsCount { get; set; }
    public List<ProductCategory> ProductCategories { get; set; }
}
PropertyTypeStatus
ProductCategoriesList<ProductCategory>Active — populated by FooterLayout and ContentLayout, iterated in the corresponding views.
AnonymousTemplateVisibilitystringPlaceholder — intended to control the CSS visibility of UI blocks shown only to anonymous (not logged-in) users. Not set by any current controller action.
LoggedInTemplateVisibilitystringPlaceholder — mirrors AnonymousTemplateVisibility for authenticated users. Not set by any current controller action.
LoggedInEmailIDstringPlaceholder — intended to display the current user’s email address in the header. Not wired to any authentication provider.
ShoppingCartItemsCountstringPlaceholder — intended to show the number of items in the user’s cart. No shopping-cart functionality is implemented.
The four visibility and auth properties represent features that were scaffolded but never implemented. They are safe to ignore in the current application but will need real implementations if user accounts or a shopping cart are ever added.

Views

The views form a two-level composition chain: a master Razor layout wraps all pages, and individual page views slot their content into that layout.

Layout Chain

_SiteLayout.cshtml  (master layout)

├── Html.RenderAction("HeaderLayout", "SiteLayout")
│       └── HeaderLayout.cshtml  (logo + banner)

├── @RenderBody()
│       └── Home/Default.cshtml
│               └── Html.RenderAction("ContentLayout", "SiteLayout")
│                       └── ContentLayout.cshtml  (category sidebar)

└── Html.RenderAction("FooterLayout", "SiteLayout")  (if present)
        └── FooterLayout.cshtml  (footer nav links)
The root Razor layout. Defines the full HTML document structure — <html>, <head>, stylesheet link, and <body>. Calls Html.RenderAction("HeaderLayout", "SiteLayout") to inject the header before rendering @RenderBody(). Any view that sets Layout = "~/Views/Shared/_SiteLayout.cshtml" automatically inherits the header and surrounding structure.
The homepage view. Sets Layout to _SiteLayout.cshtml and its body consists primarily of a call to Html.RenderAction("ContentLayout", "SiteLayout"). This delegates the rendering of the category navigation sidebar to SiteLayoutController.ContentLayout(), which fetches categories from the database and passes them to ContentLayout.cshtml.
Receives a SiteLayoutModel with ProductCategories populated. Iterates the list with a foreach loop, rendering each category name as a heading. For each category, it iterates category.ProductSubcategories and renders each subcategory as a navigation link. This view is the primary navigation UI for the entire site.
Renders the <img> tag for logo.png and the “Unicorn Bike Rentals” heading text. Receives an empty SiteLayoutModel — no data queries are needed for this region.
The generic error page. Rendered both by ErrorController.Default() when the error route is hit directly, and by the HandleErrorAttribute global filter when an unhandled MVC exception occurs.

Error Handling

Error handling is configured in two places that work together. FilterConfig.cs registers HandleErrorAttribute as a global MVC action filter:
public class FilterConfig
{
    public static void RegisterGlobalFilters(GlobalFilterCollection filters)
    {
        filters.Add(new HandleErrorAttribute());
    }
}
When an unhandled exception propagates out of any controller action, HandleErrorAttribute intercepts it, sets the HTTP response status to 500, and renders Views/Error/Default.cshtml using the HandleErrorInfo model. Web.config complements this by mapping HTTP error codes to the error route at the IIS/ASP.NET pipeline level:
<customErrors mode="On" defaultRedirect="~/Error">
  <error statusCode="404" redirect="~/Error" />
  <error statusCode="500" redirect="~/Error" />
</customErrors>
This two-layer approach ensures that errors surfaced by MVC (caught by HandleErrorAttribute) and errors surfaced by IIS before MVC is even reached (such as a 404 for a missing static file) both end up displaying the same friendly error page.

Build docs developers (and LLMs) love