Tag: ASP.NET

ASP.NET MVC Menu using Site Map Provider & Bootstrap Navbar

Updated Blog Post: ASP.NET MVC 5 Menu using Site Map Provider & Bootstrap 3 Navbar

1. Install Bootstrap for MVC 4 NuGet package. This package will install Twitter Bootstrap to the project and add bundling and minification to application start.

2. Install MvcSiteMapProvider NuGet package. This package is a SiteMapProvider implementation for the ASP.NET MVC framework.

3. In web.config, downsize the MvcSiteMapProvider configuration to the minimal. Keep it simple, stupid. (KISS)

<system.web>
  <siteMap defaultProvider=&amp;amp;quot;MvcSiteMapProvider&amp;amp;quot;>
    <providers>
      <clear />
      <add name=&amp;amp;quot;MvcSiteMapProvider&amp;amp;quot; type=&amp;amp;quot;MvcSiteMapProvider.DefaultSiteMapProvider, MvcSiteMapProvider&amp;amp;quot; siteMapFile=&amp;amp;quot;~/Mvc.Sitemap&amp;amp;quot; />
    </providers>
  </siteMap>
</system.web>

4. Modify the ~\Mvc.sitemap file as the following.

<?xml version=&amp;amp;quot;1.0&amp;amp;quot; encoding=&amp;amp;quot;utf-8&amp;amp;quot; ?>
<mvcSiteMap xmlns:xsi=&amp;amp;quot;http://www.w3.org/2001/XMLSchema-instance&amp;amp;quot;
            xmlns=&amp;amp;quot;http://mvcsitemap.codeplex.com/schemas/MvcSiteMap-File-3.0&amp;amp;quot;
            xsi:schemaLocation=&amp;amp;quot;http://mvcsitemap.codeplex.com/schemas/MvcSiteMap-File-3.0 MvcSiteMapSchema.xsd&amp;amp;quot;
            enableLocalization=&amp;amp;quot;true&amp;amp;quot;>
  <mvcSiteMapNode title=&amp;amp;quot;Home&amp;amp;quot; controller=&amp;amp;quot;Home&amp;amp;quot; action=&amp;amp;quot;Index&amp;amp;quot;>
    <mvcSiteMapNode title=&amp;amp;quot;About&amp;amp;quot; controller=&amp;amp;quot;Home&amp;amp;quot; action=&amp;amp;quot;About&amp;amp;quot; />
    <mvcSiteMapNode title=&amp;amp;quot;Contact&amp;amp;quot; controller=&amp;amp;quot;Home&amp;amp;quot; action=&amp;amp;quot;Contact&amp;amp;quot; />
    <mvcSiteMapNode title=&amp;amp;quot;Administration&amp;amp;quot; clickable=&amp;amp;quot;false&amp;amp;quot;>
      <mvcSiteMapNode title=&amp;amp;quot;User Mgmt&amp;amp;quot; controller=&amp;amp;quot;Home&amp;amp;quot; action=&amp;amp;quot;UserMgmt&amp;amp;quot; />
      <mvcSiteMapNode title=&amp;amp;quot;Role Mgmt&amp;amp;quot; controller=&amp;amp;quot;Home&amp;amp;quot; action=&amp;amp;quot;RoleMgmt&amp;amp;quot; />
    </mvcSiteMapNode>
    <mvcSiteMapNode title=&amp;amp;quot;Profile&amp;amp;quot; clickable=&amp;amp;quot;false&amp;amp;quot;>
      <mvcSiteMapNode title=&amp;amp;quot;Change Password&amp;amp;quot; controller=&amp;amp;quot;Home&amp;amp;quot; action=&amp;amp;quot;ChangePassword&amp;amp;quot; />
      <mvcSiteMapNode title=&amp;amp;quot;Separator&amp;amp;quot; clickable=&amp;amp;quot;false&amp;amp;quot; />
      <mvcSiteMapNode title=&amp;amp;quot;Sign Off&amp;amp;quot; controller=&amp;amp;quot;Home&amp;amp;quot; action=&amp;amp;quot;SignOff&amp;amp;quot; />
    </mvcSiteMapNode>
  </mvcSiteMapNode>
</mvcSiteMap>

5. The Twitter Bootstrap package installed in step 1 wouldn’t add the style and script rendering to the layout file. You need to do it manually by modifying the _Layout.cshtml file as following.

<!DOCTYPE html>
<html>
<head>
  <meta charset=&amp;amp;quot;utf-8&amp;amp;quot; />
  <meta name=&amp;amp;quot;viewport&amp;amp;quot; content=&amp;amp;quot;width=device-width&amp;amp;quot; />
  <title>@ViewBag.Title</title>
  @Styles.Render(&amp;amp;quot;~/Content/css&amp;amp;quot;)
  @Styles.Render(&amp;amp;quot;~/Content/bootstrap&amp;amp;quot;)
  @Scripts.Render(&amp;amp;quot;~/bundles/modernizr&amp;amp;quot;)
</head>
<body>
  @RenderBody()

  @Scripts.Render(&amp;amp;quot;~/bundles/jquery&amp;amp;quot;)
  @Scripts.Render(&amp;amp;quot;~/bundles/bootstrap&amp;amp;quot;)
  @RenderSection(&amp;amp;quot;scripts&amp;amp;quot;, required: false)
</body>
</html>

6. The MvcSiteMapProvider renders a menu as a unordered list which doesn’t fit the Bootstrap’s Navbar component. We need to create a partial view to fill this gap. Add a partial view file BootstrapMenuHelperModel.cshtml under ~\Views\Shared\DisplayTemplates

@model MvcSiteMapProvider.Web.Html.Models.MenuHelperModel
@using System.Web.Mvc.Html
@using MvcSiteMapProvider.Web.Html.Models

@helper  TopMenu(List<SiteMapNodeModel> nodeList)
{
  @:<div class=&amp;amp;quot;navbar&amp;amp;quot;><div class=&amp;amp;quot;navbar-inner&amp;amp;quot;><ul class=&amp;amp;quot;nav&amp;amp;quot;>
  foreach (SiteMapNodeModel node in nodeList)
  {
    string url = node.IsClickable ? node.Url : &amp;amp;quot;#&amp;amp;quot;;

    if (!node.Children.Any())
    {
      @:<li><a href=&amp;amp;quot;@url&amp;amp;quot;>@node.Title</a></li>
    }
    else
    {
      @:<li class=&amp;amp;quot;dropdown&amp;amp;quot;><a class=&amp;amp;quot;dropdown-toggle&amp;amp;quot; data-toggle=&amp;amp;quot;dropdown&amp;amp;quot; href=&amp;amp;quot;@url&amp;amp;quot;>@node.Title <b class=&amp;amp;quot;caret&amp;amp;quot;></b></a>@DropDownMenu(node.Children)</li>
    }

    if (node != nodeList.Last())
    {
      @:<li class=&amp;amp;quot;divider-vertical&amp;amp;quot;></li>
    }
  }

  @:</ul></div></div>
}

@helper DropDownMenu(SiteMapNodeModelList nodeList)
{
  <ul class=&amp;amp;quot;dropdown-menu&amp;amp;quot;>
  @foreach (SiteMapNodeModel node in nodeList)
  {
    if (node.Title == &amp;amp;quot;Separator&amp;amp;quot;)
    {
      @:<li class=&amp;amp;quot;divider&amp;amp;quot;></li>
      continue;
    }

    string url = node.IsClickable ? node.Url : &amp;amp;quot;#&amp;amp;quot;;

    if (!node.Children.Any())
    {
      @:<li><a href=&amp;amp;quot;@url&amp;amp;quot;>@node.Title</a></li>
    }
    else
    {
      @:<li class=&amp;amp;quot;dropdown-submenu&amp;amp;quot;><a href=&amp;amp;quot;@url&amp;amp;quot;>@node.Title</a>@DropDownMenu(node.Children)</li>
    }
  }
  </ul>
}

@TopMenu(Model.Nodes)

Notes: 2 value-added features worth mention in the above code snippet. a) Handle multi-level site map using Bootstrap’s Dropdowns component (This post shows 2 levels site map, I tested with 4 levels site map); b) Support adding Separator in the menu (Refer to above ~\Mvc.sitemap snippet in step 4).

7. Add HomeController, and then add Index View for testing.

8. Edit the _Layout.cshtml file again to render the MvcSiteMap’s menu using the Bootstrap menu partial view.

......
<body>
    <div class=&amp;amp;quot;container&amp;amp;quot;>
        <div class=&amp;amp;quot;row&amp;amp;quot;>
            <div class=&amp;amp;quot;span12&amp;amp;quot;>
                <nav>
                    @Html.MvcSiteMap().Menu(&amp;amp;quot;BootstrapMenuHelperModel&amp;amp;quot;)
                </nav>
            </div>
        </div>
        <!-- //row -->
        <div class=&amp;amp;quot;row&amp;amp;quot;>
            <div class=&amp;amp;quot;span12&amp;amp;quot;>
                @RenderBody()
            </div>
        </div>
        <!-- //row -->
    </div>
    ......
</body>
......

9. Completed!!!
Drop Down Menu
DropDown Menu

Drop Down Menu w/ Separator
DropDown Menu w/ Separator

You can download the code sample here.

References

Advertisements

CascadingDropDown in ASP.NET MVC

1. Download CascadingDropDown jQuery Plugin

2. Put file jquery.cascadingDropDown.js in ~\Scripts

3. Add the following line of code in ~\App_Start\BundleConfig.cs

    bundles.Add(new ScriptBundle("~/bundles/jqueryplugin").Include(
        "~/Scripts/jquery.cascadingDropDown.js"));

4. Create a View Model for the Cascading DropDown Select Lists and the selected values

public class CascadingDropDownViewModel
{
    public SelectList AreaSelectList { get; set; }

    public SelectList DistrictSelectList { get; set; }

    [Display(Name = "Area")]
    public Area Area { get; set; }

    [Display(Name = "District")]
    public District District { get; set; }
}

5. Create a Controller for populating the View Model

public ActionResult CascadingDropDown()
{
    CascadingDropDownViewModel model = new CascadingDropDownViewModel();
    model.AreaSelectList = new SelectList(_entities.Areas, "AreaId", "Name");
    model.DistrictSelectList = new SelectList(Enumerable.Empty(), "DistrictId", "Name");

    return View(model);
}

6. Create a View to show the Cascading DropDown

@using (Html.BeginForm())
{
    @Html.AntiForgeryToken()
    @Html.LabelFor(m => m.Area) :
    @Html.DropDownListFor(m => m.Area, Model.AreaSelectList, "-- Please Select --")
    @Html.ValidationMessageFor(m => m.Area)


    @Html.LabelFor(m => m.District) :
    @Html.DropDownListFor(m => m.District, Model.DistrictSelectList)
    @Html.ValidationMessageFor(m => m.District)


    <button type="submit">Submit</button>
}

@section scripts{
<script type="text/javascript">// <![CDATA[
        $(document).ready(function () {
            $("#District").CascadingDropDown("#Area", "/Ajax/DistrictCascadingDropDown",
            {
                promptText: "-- Please Select --",
                postData: function () {
                    return { areaId: $("#Area").val() };
                }
            });
        });

// ]]></script>
}

7. Create a dedicated Controller AjaxController and an Action method DistrictCascadingDropDown

public ActionResult DistrictCascadingDropDown(int areaId)
{
	var query = from d in _entities.Districts
				where d.AreaId == areaId
				select d;

	SelectList selectList = new SelectList(query, "DistrictId", "Name");

	return Json(selectList);
}

References

DropDownList in ASP.NET MVC

View Model

public class DropDownListViewModel
{
    public SelectList DistrictSelectList { get; set; }

    [Display(Name = "District")]
    public District District { get; set; }
}

Controller

public ActionResult DropDownList()
{
    DropDownListViewModel model = new DropDownListViewModel();
    model.DistrictSelectList = new SelectList(_entities.Districts, "DistrictId", "Name");

    return View(model);
}

View

@using (Html.BeginForm())
{
    @Html.AntiForgeryToken()
    @Html.LabelFor(m => m.District) <text>:</text>
    @Html.DropDownListFor(m => m.District, Model.DistrictSelectList, "-- Please Select --")
    @Html.ValidationMessageFor(m => m.District)
    <button type="submit">Submit</button>
}

References

Learning ASP.NET Web Pages

ASP.NET Web Pages is a framework that you can use to create dynamic web pages. A simple HTML web page is static; its content is determined by the fixed HTML markup that’s in the page. Dynamic pages like those you create with ASP.NET Web Pages let you create the page content on the fly, by using code.

9 Parts Tutorial
  1. Getting Started
  2. Programming Basics
  3. Displaying Data
  4. HTML Form Basics
  5. Entering Database Data by Using Forms
  6. Updating Database Data
  7. Deleting Database Data
  8. Creating a Consistent Layout
  9. Publishing a Site by Using WebMatrix
See Also

Get Started ASP.NET

1. Web Forms
* Familiar control- and event-based programming model
* Controls encapsulate HTML, JS and CSS
* Rich UI controls included – datagrids, charts, AJAX
* Browser differences handled for you
* SharePoint builds on Web Forms

2. MVC
* Feels comfortable for many traditional web developers
* Total control of HTML markup
* Supports Unit Testing, TDD and Agile methodologies
* Encourages more prescriptive applications
* Extremely flexible and extensible

3. Web Pages
* Easy to pick up and learn
* Inline scripting model with Razor and C# or VB.NET
* Simplified model with Top-to-bottom execution
* Full control over your HTML
* Friendly Helper syntax make extending your apps easy

References