skip to Main Content

My ASP.NET MVC5 application uses a Twitter Bootstrap navbar at the top. One item in the navigation bar is a dropdown-menu for logged in users. Inside the dropdown is an ActionLink to the profile page, and another item to Log Off.

The Log Off action is following this advice thus calling a HttpPost action, meaning it can’t use a plain ActionLink. Instead I use a BeginForm and a input of type=submit. The Razor view looks like this:

<ul class="nav navbar-nav navbar-right">
    <li class="dropdown">
        <a href="#" data-toggle="dopdown" class="dropdown-toggle">
            John Doe <span class="caret"></span>
        </a>
        <ul class="dropdown-menu">
            <li>
                @Html.ActionLink("Account", "Index", "Account")
            </li>
            <li>
                @using (Html.BeginForm("Logout", "Account", FormMethod.Post))
                {
                  <input type="submit" value="LogOff" class="btn btn-default navbar-btn"/>
                }
            </li>
        </ul>
    </li>
</ul>

However, this renders like so:

rendered dropdown-menu

I’ve tried replacing the <input type="submit" /> with this:

<a href="#" onclick="$(this).closest('form').submit(); return false;">LogOff</a>

However, the form element that wraps this a tag breaks Bootstrap styling as well, rendering like this:

rendered dropdown-menu after changing code

What’s the proper way to handle this?

I’m asking this the way I did above, because I’d prefer a solution that keeps my Razor view at least as simple as it is now, but preferably even make it simpler. Perhaps there’s a Html helper method I’ve overlooked that could do what I need in a way that the rendered markup is picked up by Bootstrap?


As a footnote, here’s a + repro to fiddle with.

Warning: the width of Stack Overflow snippets tends to trigger Bootstrap’s responsiveness features, which may alter the view slightly.

<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>

<nav class="navbar navbar-default navbar-fixed-top">
    <div class="container">
        <ul class="nav navbar-nav navbar-right">
            <li class="dropdown"> 
                <a href="#" data-toggle="dropdown" class="dropdown-toggle">
                    John Doe
                    <span class="caret"></span>
                </a>
                <ul class="dropdown-menu">
                    <li>
                        <a href="#">Profile</a>
                    </li>
                    <li>
                        <form action="xyz" method="POST">
                            <input type="submit" value="LogOff" class="btn btn-default navbar-btn" />
                        </form>
                    </li>
                </ul>
            </li>
        </ul>
    </div>
</nav>

2

Answers


  1. Chosen as BEST ANSWER

    I ended up doing something similar to @Repo's answer, yet different enough to warrant posting it as a different solution. The basic idea is the same, this answer also uses the workaround I mentioned in my question: using javascript on an anchor tag to submit the form.

    With this workaround the form is very close to the anchor tag, making the code a bit easier to read in the future, also preventing the need to use a byId selector:

    <ul class="nav navbar-nav navbar-right">
        <li class="dropdown">
            <a href="#" data-toggle="dopdown" class="dropdown-toggle">
                John Doe <span class="caret"></span>
            </a>
            <ul class="dropdown-menu">
                <li>
                    @Html.ActionLink("Account", "Index", "Account")
                </li>
                <li>
                    @* WORKAROUND: Anchor tag outside the form element to make Bootstrap style it properly. *@
                    @using (Html.BeginForm("Logout", "Account", FormMethod.Post))
                    { }
                    <a href="#" onclick="$(this).parent().find('form').submit(); return false;">LogOff</a>
                </li>
            </ul>
        </li>
    </ul>
    

    I do consider this an ugly workaround though, so invite anyone to include a more proper solution that doesn't require this type of hard to understand markup or a bunch of custom css rules...


  2. Place your form in a div with display: none; and use an anchor to click the submit button =)

    <ul class="nav navbar-nav navbar-right">
        <li class="dropdown">
            <a href="#" data-toggle="dopdown" class="dropdown-toggle">
                John Doe <span class="caret"></span>
            </a>
            <ul class="dropdown-menu">
                <li>
                    @Html.ActionLink("Account", "Index", "Account")
                </li>
                <li>
                    <a href="#" onclick="$('#mySubmit').click();">Log Off</a>
                </li>
            </ul>
        </li>
    </ul>
    <div style="display: none;">
        @using (Html.BeginForm("Logout", "Account", FormMethod.Post))
        {
            <input id="mySubmit" type="submit" value="LogOff" class="btn btn-default navbar-btn"/>
        }
    </div>
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search