Click here to Skip to main content
15,867,568 members
Articles / Programming Languages / C#

Bootstrap HTML Helpers

Rate me:
Please Sign up or sign in to vote.
4.99/5 (34 votes)
19 May 2018CPOL3 min read 134.3K   105   17
With the Bootstrap Helpers project, I have made things even easier for .NET developers.

Introduction

The guys over at Twitter have done a serious favor for developers worldwide with their Bootstrap framework. This is especially useful for us coders with limited skills in UI design. With the Bootstrap Helpers project, I have made things even easier for .NET developers.

UPDATE (2018.05.19)

This project has been superceded by the ExtensoUI package in my Extenso project for .NET Core. It does not have all the same helpers, but most of the important ones are there (Accordion, Tabs, Panel, Modal and some smaller things). More importantly, I made it extensible, so you can add your own provider for Bootstrap 4, Foundation 5 or 6, jQueryUI, etc. I have already created a spearate package for Kendo as well and I will likely improve upon this in future. Enjoy!

Update (2013.05.10)

Note that the Bootstrap Helpers are now available as a Nuget package! Here is the link: https://www.nuget.org/packages/VortexSoft.Bootstrap[ title="New Window">^]. Additionally, the project is hosted on GitHub now, as that is what most people seem to be using these days for open source projects. I am hoping this will help with contributors. Here is the link for that: https://github.com/gordon-matt/BootstrapHelpers[ title="New Window">^]

Usage

Here are some examples of the most useful HTML helpers using the Razor syntax.

Modal Dialog

C#
<a class="btn" data-toggle="modal" href="#myModal" >Normal Modal</a>

@using (var modal = Html.Bootstrap().Begin(new Modal(new { id = "myModal" })))
{
    using (var header = modal.BeginHeader())
    {
        <button type="button" class="close" 
            data-dismiss="modal"</button>
        <h3>Modal header</h3>
    }
    using (var body = modal.BeginBody())
    {
        <p>One fine body…</p>
    }
    using (var footer = modal.BeginFooter())
    {
        @Html.Bootstrap().Button("Close", BootstrapNamedColor.Default, 
              null, new { data_dismiss = "modal" })
        @Html.Bootstrap().Button("Save Changes", BootstrapNamedColor.Primary, null)
    }
}

Tabs

C#
@using (var tabs = Html.Bootstrap().Begin(new Tabs()))
{
    tabs.Tab("Tab One", "tab1");
    tabs.Tab("Tab Two", "tab2");
    tabs.Tab("Tab Three", "tab3");

    using (tabs.BeginPanel())
    {
        <p>This is tabs panel 1 content</p>
    }
    using (tabs.BeginPanel())
    {
        <p>This is tabs panel 2 content</p>
    }
    using (tabs.BeginPanel())
    {
        <p>This is tabs panel 3 content</p>
    }
}

You could also place the tabs on the left or right. Here is an example:

C#
@using (var tabs = Html.Bootstrap().Begin(new Tabs(TabPosition.Left)))
{
//etc
}

Accordion/Collapse

C#
@using (var accordion = Html.Bootstrap().Begin(new Accordion("accordion1")))
{
    using (var panel = accordion.BeginPanel("Panel 1", "panel1"))
    {
        <p>This is accordion panel 1 content</p>
    }
    using (var panel = accordion.BeginPanel("Panel 2", "panel2"))
    {
        <p>This is accordion panel 2 content</p>
    }
}

Carousel

C#
@using (var carousel = Html.Bootstrap().Begin(new Carousel("carousel1")))
{
    carousel.Item("~/Images/Red.png", "Red");

    using (var item = carousel.ItemWithCaption("~/Images/Green.png", "Green"))
    {
        <h4>This is Green</h4>
        <p>Green is a nice color</p>
    }

    carousel.Item("~/Images/Blue.png", "Blue");
}

Sub Nav

C#
@using (var subNav = Html.Bootstrap().Begin(new SubNavBar()))
{
    subNav.Item("Modal", "#demoModal");
    subNav.Item("Tabs", "#demoTabs");
    subNav.Item("Accordion", "#demoAccordion");
    subNav.Item("Other", "#demoOther");
    subNav.Item("Toolbar", "#demoToolbar");
    subNav.Item("Thumbnails", "#demoThumbs");
    subNav.Item("Carousel", "#demoCarousel");
    subNav.Item("Code Blocks", "#demoCodeBlocks");
    subNav.Item("Forms", Url.Action("DemoForm", "Home"));

    subNav.DropDownItem("DropDown", new List<BootstrapListItem>
    {
        new BootstrapListItem { Text = "Something", Url = "#something" },
        new BootstrapListItem { Text = "Something Else", Url = "#something-else" },
        new BootstrapListItem { Text = "Yet Something More", Url = "#yet-something-more" }
    });
}

Miscellaneous

There are also many smaller helpers which you can find, such as the Buttons. Here is an example of an action button:

C#
@Html.Bootstrap().ActionButton("Home", BootstrapNamedColor.Primary, 
             "Index", "Home")

How It Was Done

When building any HTML helpers, I consider it always good practice to separate them from the rest of the standard ones. So, instead of calling:

C#
Html.BeginBootstrapAccordion()

or something like that, we want to call:

C#
Html.Bootstrap().Begin(new Accordion())

The way to do this would be to first create a class called Bootstrap with only one constructor whose accessibility is set to internal. Here is an example:

C#
public class Bootstrap<TModel>
{
    private readonly HtmlHelper<TModel> helper;

    internal Bootstrap(HtmlHelper<TModel> helper)
    {
        this.helper = helper;
    }
//etc

You of course need to pass an instance of HtmlHelper as well and in that class is where you will add all the helper methods. Here is a simple example (with overloads):

C#
public MvcHtmlString ActionButton
(string text, BootstrapNamedColor color, string actionName, string controllerName)
{
    return ActionButton(text, color, actionName, controllerName, null);
}

public MvcHtmlString ActionButton(string text, BootstrapNamedColor color, 
       string actionName, string controllerName, object routeValues)
{
    return ActionButton(text, color, actionName, controllerName, routeValues, null);
}

public MvcHtmlString ActionButton(string text, BootstrapNamedColor color, 
       string actionName, string controllerName, object routeValues, object htmlAttributes)
{
    var builder = new TagBuilder("a");
    builder.SetInnerText(text);

    builder.MergeAttributes(HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes));

    switch (color)
    {
        case BootstrapNamedColor.Important: builder.AddCssClass("btn btn-danger"); break;
        case BootstrapNamedColor.Default: builder.AddCssClass("btn"); break;
        case BootstrapNamedColor.Info: builder.AddCssClass("btn btn-info"); break;
        case BootstrapNamedColor.Inverse: builder.AddCssClass("btn btn-inverse"); break;
        case BootstrapNamedColor.Primary: builder.AddCssClass("btn btn-primary"); break;
        case BootstrapNamedColor.Success: builder.AddCssClass("btn btn-success"); break;
        case BootstrapNamedColor.Warning: builder.AddCssClass("btn btn-warning"); break;
        default: builder.AddCssClass("btn"); break;
    }

    var urlHelper = new UrlHelper(helper.ViewContext.RequestContext);
    builder.MergeAttribute("href", urlHelper.Action(actionName, controllerName, routeValues));

    return MvcHtmlString.Create(builder.ToString());
}

Finally, you need to create an instance of the Bootstrap class somewhere. Since it only has an internal constructor, you can only instantiate it from the project it is created in and since you want to be able to use it from any other project, what you do is create a public extension method in that same project like so:

C#
public static class HtmlHelperExtensions
{
    public static Bootstrap<TModel> Bootstrap<TModel>(this HtmlHelper<TModel> htmlHelper)
    {
        return new Bootstrap<TModel>(htmlHelper);
    }
}

And as easy as that, you can now add all your helper methods into the Bootstrap “we’ll call it name space; for lack of a better word”. So now I just use it like this:

C#
@Html.Bootstrap().ActionButton("Home", BootstrapNamedColor.Primary, "Index", "Home")

Awesome! Show me more! Okay, okay, here goes: Inspect the following:

C#
@using (Html.BeginForm()) {
    @Html.AntiForgeryToken()
    @Html.ValidationSummary()

    <fieldset>
        <legend>Registration Form</legend>
        <ol>
            <li>
                @Html.LabelFor(m => m.UserName)
                @Html.TextBoxFor(m => m.UserName)
            </li>
            <li>
                @Html.LabelFor(m => m.Password)
                @Html.PasswordFor(m => m.Password)
            </li>
            <li>
                @Html.LabelFor(m => m.ConfirmPassword)
                @Html.PasswordFor(m => m.ConfirmPassword)
            </li>
        </ol>
        <input type="submit" value="Register" />
    </fieldset>
}

The HTML helper in this case is BeginForm() and it is different somehow... yes, it allows you to add HTML content in between the braces. Nice! Ever wondered how it’s done? Well, stop wondering.. let’s create our own. You basically need do create a class that inherits from IDisposable like so:

C#
public class AccordionBuilder<TModel>
{
    protected readonly TextWriter textWriter;
    protected readonly HtmlHelper<TModel> htmlHelper;

    internal AccordionBuilder(HtmlHelper<TModel> htmlHelper, Accordion accordion)
    {
	this.htmlHelper = htmlHelper;
	this.textWriter = htmlHelper.ViewContext.Writer;
        	this.textWriter.Write(@"<div class=""acccordion"">");
    }

    public override void Dispose()
    {
        this.textWriter.Write(@"</div>");
    }
}

The code for the real accordion is a little more complex than the above. I have simplified the above to give you a clearer picture of what’s going on. Basically, in the constructor, we write the start of the element (a <div> in this case or <form> tag in the case of Html.BeginForm()) and in the Dispose() method, we write the end tag. Since the using statement automatically calls Dispose() on an IDisposable, then that’s all we need to do... nothing too fancy here.

Final Word

These helpers are there to benefit everyone. As such, it is my hope that there will be those who’d like to contribute and make these helpers even better for everyone. Enjoy!

Acknowledgements

I must give credit to Attila Losonc of the jQuery UI Helpers project; it is that awesome project that inspired me to create the Bootstrap Helpers.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior) Freelancer
Australia Australia
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
QuestionGreat article! Nice to have helpers for input elements Pin
superfly7121-May-18 0:01
professionalsuperfly7121-May-18 0:01 
QuestionPlay audio/video file in mvc Pin
Nawab_Ali16-Apr-18 7:25
Nawab_Ali16-Apr-18 7:25 
QuestionOnly usee cshtml files Pin
pedrualmeida15-Apr-15 1:48
pedrualmeida15-Apr-15 1:48 
QuestionGreat article. Help needed. Pin
schadha8-Jun-14 11:25
schadha8-Jun-14 11:25 
QuestionWill you move this nice helper to BootStrap 3? Pin
antrim24-Dec-13 4:24
antrim24-Dec-13 4:24 
AnswerRe: Will you move this nice helper to BootStrap 3? Pin
vnmatt8-Sep-14 14:20
vnmatt8-Sep-14 14:20 
Question5! and a newbie question Pin
Marc Clifton11-May-13 1:48
mvaMarc Clifton11-May-13 1:48 
AnswerRe: 5! and a newbie question Pin
vnmatt11-May-13 2:56
vnmatt11-May-13 2:56 
GeneralRe: 5! and a newbie question Pin
Marc Clifton11-May-13 3:08
mvaMarc Clifton11-May-13 3:08 
GeneralMy vote of 5 Pin
dzmuh7-Feb-13 15:30
dzmuh7-Feb-13 15:30 
GeneralRe: My vote of 5 Pin
vnmatt10-May-13 1:46
vnmatt10-May-13 1:46 
QuestionFluent Syntax Pin
David Sehnal21-Dec-12 5:39
David Sehnal21-Dec-12 5:39 
AnswerRe: Fluent Syntax Pin
vnmatt10-May-13 1:45
vnmatt10-May-13 1:45 
GeneralMy vote of 5 Pin
Anurag Gandhi17-Dec-12 21:25
professionalAnurag Gandhi17-Dec-12 21:25 
QuestionMy Vote of 5 Pin
Hemant.Kamalakar17-Dec-12 19:35
Hemant.Kamalakar17-Dec-12 19:35 
GeneralMy vote of 5 Pin
Wooters12-Dec-12 17:47
Wooters12-Dec-12 17:47 
QuestionVery Nice Pin
Dave Kerr12-Dec-12 8:17
mentorDave Kerr12-Dec-12 8:17 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.