Just recently I published this post about creating a “logon widget” for the ASP.NET MVC Contoso Karate application that I’ve started building.

In this post I’m going to re-factor it.

Why, you ask? Well, sometimes it’s easiest to demonstrate techniques in a “simple” way  that is not necessary the most practical way.

Such is the case of our “login widget”.

ASP.NET MVC imposes a LOT of conventions. We could have technoligious discussions ad nauseam about why the MVC way is the best way (or not). I have FAR to many of these conversations but lets just agree that for some developer’s preferences and in certain types of application needs, the impositions of the pattern pay long-term dividends.

The idea of MVC (Model – View – Controller) lets us achieve “Separation of Concerns”. While this is not necessary (I know – sacrilege!) it is normally a beneficial thing. 

But, whenever a pattern or an implementation is meant to support a specific way of doing things it can get in the way.

The problem in this case is that a view (by default) sort of wants to be rendered using a SINGLE model.

take for example the following web site layout from a Joomla theme by RocketTheme

This is a pretty common kind of web user interface and one that will be very difficult to serve using a single data source.

You’ll recall from the previous post that we want the LogOn widget to appear on every page  but we accessed the model for the login data by referencing the LogOnModel that is innate to ASP.NET MVC applications that are created using the default ASP.NET MVC template.

It works fine, but our pages will stop working as soon as we try to reference an additional model in our views as views want a SINGLE model to work with.

No problem. Not only is there a way to do what we want (now that we understand the code that delivers the LogOn behavior that wer want) there is a much better, reusable way.

Enter “Partial Views”

Note that I’m not posting screen shots here because the User Interface will look and work EXACTLY like that you will find in the previous post referenced above.

To create a Partial View you will right-click on the folder where you want that Partial View to be created. Since we want our “LogIn Widget” to be able to be used anywhere, we’ll Right-Click on the \Views\Shared folder, choose “Add and then “View”.

Note the sections indicated in the image above.

I chose a name that begins with an underscore (I don’t want this partial view to ever be rendered directly) and ends with the word “partial” so that I can tell at a glance which of my views are “full” views and which are partial.

In addition I select the check box that instructs the wizard to create a partial view.

Once I complete the wizard my

Views\Shared folder will contain a file named _LoginBoxPartial.cshtml

Next, I need to move two bits of code from my site’s _Layout.cshtml page.

  • The MOdel declaration at the very top.
  • The conditional markup that we put in the _Layout file to create the LogIn or LogOut box, depending on the user’s state of authentication.

 The complete code of our partial view (_LoginBoxPartial.cshtml) loosk like this:



@model ContosoKarateMVC.Models.LogOnModel
@if (!User.Identity.IsAuthenticated)
{
    using (Html.BeginForm('LogOn', 'Account', FormMethod.Post))
    {        
        <div class='editor-label'>
            @Html.LabelFor(m => m.UserName)
        </div>
        <div class='editor-field'>
            @Html.TextBoxFor(m => m.UserName)
            @Html.ValidationMessageFor(m => m.UserName)
        </div>
        <div class='editor-label'>
            @Html.LabelFor(m => m.Password)
        </div>
        <div class='editor-field'>
            @Html.PasswordFor(m => m.Password)
            @Html.ValidationMessageFor(m => m.Password)
        </div>
        <div class='editor-label'>
            @Html.CheckBoxFor(m => m.RememberMe)
            @Html.LabelFor(m => m.RememberMe)
        </div>   
        <span class='style-button-wrapper'>
            <span class='style-button-l'> </span>
            <span class='style-button-r'> </span>
            <input type='submit' name='Submit' class='style-button' 
			       value='Login' />
        </span>
        <hr />  
        <ul>
            <li>
		@Html.ActionLink('Create an Account.', 'Register', 'Account')
	    </li>
        </ul>
    }
}
else
{
    using (Html.BeginForm('LogOff', 'Account', FormMethod.Post))
    { 
        <span class='style-button-wrapper'>
            <span class='style-button-l'> </span>
            <span class='style-button-r'> </span>
            <input type='submit' name='Submit' class='style-button' 
			                     value='Logoff' />
        </span>                                              
    }
}   

Then we just need to insert a call to render our partial view in the same location as when the markup was in-line in the Layout file.


@{ Html.RenderPartial('_LoginBoxPartial'); }

Now the Views that derive from our _Layout.cshtml page are free to use whatever model they desire and our LogIn feature will still work.

What’s more, we can reuse the Partial View anywhere in our project.

Note: I’m intentionally not posting a like to the source code (you can easily change the source from the prior post.)

In my NEXT post I’ll illustrate a more complex use of “Widgetry” and I will post the code at that time.