Avoid CSS Footer Class To Overlap Content

Preface

Unfortunately I can’t recall where I found the initial implementation. Anyway, from somewhere I copied some CSS class definition to create a footer that is fixed at bottom of a web page, no matter how high the browser window and the page’s content is.

When using this in my ASP.NET MVC 5 Web application (that was based on Bootstrap, I noticed that, when I resized the browser window by making it narrower and less high, the footer was overlapping some of the page’s content when the page’s content needs to be scrolled.

My first thought was that something with Bootstrap went wrong. But later on I learned that Bootstrap was not involved here.

Because it took me some time to find a work-around, I will describe it here for later re-use.

The Footer Definition

The CSS Class

The CSS definition I found in the Web looks like this:

.footer {
  position: absolute;
  bottom: 0;
  width: 100%;
  /* Set the minimum height of the footer here */
  min-height: 60px;
  background-color: rgb(238, 238, 238);
}

The Footer Definition

The class was used like this by the _Layout.cshtml file:

<footer class="footer">
  <p>© @DateTime.Now.Year by proccelerate GmbH</p>
</footer>

Explanation

I found the explanation for the observed behavior on Stack Overflow:

“…[position: absolute]… takes your element out of the document’s regular flow, so there’s no way for the text to have any positional-relationship with it, unfortunately.”

I found a JavaScript based attempt to solve this here, but it did not worked correctly in my app.

Workaround

Well, at least I added a “filler” below the page’s redenred body that makes sure there will be enough space for the footer in case the content of the page needs to be scrolled.
Maybe the height of the filler needs to be adjusted in your code. This depends on your page’s content.

This is the changed content of the _Layout.cshtml file (snipped):

<div class="container body-content">
  @RenderBody()
  <div style="height:45px;"></div>
</div>

Links

Bootstrap

Stack Overflow: bootstrap footer hiding contents above it

Stack Overflow: Stop absolutely positioned div from overlapping text

Paging Made Easy with ASP.NET MVC 5, Entity Framework 6 and PageList.Mvc

Preface

In former days, implementing paging sometimes took a little bit of time. That was independent from the used platform, native Windows Client or Web or whatever.

Fortunately, that was then and this is now. Implementing paging in an ASP.NET MVC 5 Entity Framework 6 application really became simple. Just a few lines of code, and you’re done.

The Basics

The basics of paging in ASP.NET MVC are described by the Getting Started with EF 6 using MVC 5 tutorial Sorting, Filtering, and Paging with the Entity Framework in an ASP.NET MVC Application.

As the title says, you need EF 6 and MVC 5. The author Tom Dykstra suggests to use PagedList.Mvc. NuGet Must Haves lists this package on top of the Top 20 packages for paging. So I thought I’ll give it a try.

Using PagedList.Mvc

The usage is simple. As described by the ASP.NET tutorial, the package needs to be installed. I used the menu: Tools / NuGet Package Manager / Manage NuGet Packages for Solution….

Changing the View

The model of the view that should contain paging needs to be changed from IEnumetablle<MyModel> to PagedList.IPagedList<MyModel>. Also, the using of PagedList.Mvc and a link to the PagedList stylesheet needs to be added. After changing the code, the first tree lines of the view look like this:

@model PagedList.IPagedList<MyModel>
@using PagedList.Mvc;
<link href="~/Content/PagedList.css" rel="stylesheet" 
  type="text/css" />

In case you want to show the current page and the total number of pages, add something like this to the appropriate place.

Page @(Model.PageCount < Model.PageNumber ? 0 : Model.PageNumber)
 of @Model.PageCount

The last change is adding the paging buttons into the view.

@Html.PagedListPager(Model, 
  page => Url.Action("Index", new { page }) )

Changing the Controller

Because the view expects a different kind of model, the controller has to generate it. And because we need to return the content of different pages, the requested page is passed as a parameter. Given that db.MyModels returns something of type MyModel, the controller might look like this:

public ActionResult Index
  (
    int? page
  )
{
  var items = for item in db.MyModels select item;

  return (View(items.ToPagedList(pageNumber: page ?? 1, 
    pageSize: 10)));
}

That's really simple, isn't it.

Paging Extended

The code above works really good. But I want to extend the paging a little bit.

Let the User Choose

The number of items shown per page is fix in the sample above. I do not like that. So I added a dropdown list to the view to let the user choose how many items per page will be displayed.

The list of items shown by the dropdown list is generated by a helper method to make it reuseable.

public static class DefaultValues
{
  ...
  public static SelectList ItemsPerPageList 
    { 
      get 
      { return (new SelectList(new List { 5, 10, 25, 50, 100 }, 
        selectedValue: 10)); 
      } 
    }
  ...
}

To use this list, the view defines a local variable.

SelectList itemsPerPageList = DefaultValues.ItemsPerPageList;

And the dropdown list is placed wherever I like using the HtmlHelper

@Html.DropDownList("ItemsPerPage", itemsPerPageList, 
  new { @id = "ItemsPerPageList" })

To have the correct number of items per page shown when the user switches the page, we need to pass the current number of items to the controller. Therefor the HtmlHelper for the paging buttons needs to be extended.

@Html.PagedListPager(Model, page => Url.Action(ActionNames.Index,
  new { page, itemsPerPage = ViewBag.CurrentItemsPerPage }));

As you can see by this code, the controller needs some changes too.

public ActionResult Index
  (
    int? itemsPerPage,
    int? page
  )
{
  ViewBag.CurrentItemsPerPage = itemsPerPage;

  var items = for item in db.MyModels select item;

  return (View(items.ToPagedList(pageNumber: page ?? 1, 
    pageSize: itemsPerPage ?? 10)));
}

Handling an Empty List

From what I noticed, the Model of the view is null in case the list itself does not contain any items.

The extension method PagedListPager is not able to handle that. And of course, when showing the current page and the total number of pages, accessing a null reference leads to an exception too.

To avoid these exceptions, some more code is required.

@if (Model != null
  && Model.PageCount > 0)
  {
    <div>
      Page @(Model.PageCount < Model.PageNumber 
             ? 0 : Model.PageNumber) 
      of @Model.PageCount
    </div>
  }
@if (Model != null)
  {
    @Html.DropDownList("ItemsPerPage", itemsPerPageList, 
      new { @id = "ItemsPerPageList" })
}

Minor Stylesheet Additions

In my ASP.NET MVC application, I have a footer defined in the _Layout.cshtml file. In some cases I saw that the paging buttons partly were overlapped by the footer. To avoid this, I added a bottom margin to the pagination container style and put this into the Content/Site.css file:

.pagination-container {
  margin-bottom:25px;
}

Conclusion

Even with these small additions, paging is made really easy. What I was not looking at is the performance of the database access. For web applications with small databases, this does not seem to be important from my point of view. In case you do have a large database and complex database requests where performance is an issue, I think it's worth to check out the impact of this implementation.

Links

ASP.NET Tutorial: Sorting, Filtering, and Paging with the Entity Framework in an ASP.NET MVC Application

PagedList.Mvc on NuGet

NuGet Must Haves Top 20 NuGet packages for paging

Handle Deactivated JavaScript in ASP.NET MVC Web Application

Preface

Depending on what your ASP.NET MVC Web application is supposed to do, it might be necessary that the client’s browser has JavaScript support enabled.

If this is not the case, maybe you want to make sure the user will be informed and cannot use the application.

And because there is no JavaScript available, this has to be done in a non-script way.

Use The noscript-Tag & Redirect

To handle all this without any script is quite simple. HTML offers the noscript tag.

Inside the noscript area, one can add whatever HTML code is required.

Since I want the user to be redirected to another page, I will use meta http-equiv="refresh" content="0;…" to redirect the user to the page explaining that JavaScript is required to use my application.

Add It To The Layout Page

To make sure the user will be redirected independent which page should be opened, I add the noscsript area to the _Layout.cshtml page.

And because I do use a meta tag, the code is placed into the head area to avoid warnings that meta elements cannot be nested inside the body element.

In case you use different layout pages in your application, you should put the redirection code into a partial view and add this to all of your layout pages. If there is the need to change the redirection, there will be only one place that needs to be changed.

NoJScript Controller And View

I do have a ASP.NET MVC application, so want to redirect to an appropriate controller when JavaScript is disabled, not to a HTML page.

Accordingly, I add the NoJScript controller with an Index view to my project and redirect the user to /NoJScript. The view is used to inform the user that JavaScript support is required and can contain all non-script elements that are needed.

It is important that this view does not use the layout page itself. Otherwise there will be an endless redirection loop, because when the view is opened, the browser detects there is no JavaScript enabled, and again redirects to this view, and so forth.

Access Restrictions

In case you restrict access to your application by setting the AuthorizeAttribute either to your controller or by adding

filters.Add(new System.Web.Mvc.AuthorizeAttribute());

to the App_Start/FilterConfig.cs, remember to set the AllowAnonymousAttribute to the Index method of the NoJScript controller. Otherwise, the browser is hooked in an endless loop, switching between the login page and the JavaScript required page.

Putting It Together

Here are all changes listed.

In the _Layout.cshtml page, this section is added to the head element:

<head>
…
<noscript>
  <meta http-equiv="refresh" content="0;url=/NoJScript" />
</noscript>
…
<head>

The NoJScript controller is really simple:

public class NoJScriptController : Controller
{
  //
  // GET: /NoJScript/
  [AllowAnonymous]
  public ActionResult Index()
  {
    return View();
  }
}

And the view should contain a little bit more information than this sample:

@{
  ViewBag.Title = "JavaScript required";
  Layout = null; // <= Important!
}

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>@ViewBag.Title - My MVC App</title>

  @Styles.Render("~/Content/css")
  @Scripts.Render("~/bundles/modernizr")

</head>
<body>
 To use this application JavaScript is required.
</body>

Create a 1:1 Table Relationship using Entity Framework

Preface

My database roots are pure SQL. When I create a database, I use an Excel sheet for documentation purposes, which creates SQL statements to build up the tables.

Table relationships (parent / child) with foreign keys I do define by hand, like the good old craftsmen do. It’s simple for me, and having the appropriate SQL code from another project, it takes a few seconds to adapt it to the new tables.

But from time to time one should try something else, so I decided to use the Entity Framework (EF) Code First approach for a new project I started. This post was written to document the required steps for later re-use.

Starting Point

As a starting point, I built an ASP.NET MVC 5 application with EF 6 and “Individual User Accounts” authentication, using Visual Studio 2013 Update 1.

Project Settings

Because the key of the AspNetUsers table is a string containing a GUID, I wanted to add a UserProfile table to map the GUID to an integer. This integer value will be used by the application to map other data to specific users. From my point of view, an integer is much more readable than a GUID.

Adding the Model

Since I was using the Code First approach, I added a class called UserProfile to the models. To link the UserProfile to the user main table, it needs to contain a property of type ApplicationUser. This class is created by the ASP.NET MVC project template and maps to the database table dbo.AspNetUsers.

I also wanted to keep the date and time when a user was created, so the UserProfile class got a CreationDate property. And because it seems that EF Code First does not support database default values, this property is set by the default constructor of the class. As a result, UserProfile looks like this:

public class UserProfile
{
  public long Id { get; set; }

  [Required]
  public DateTime CreationDate { get; set; }

  public ApplicationUser User { get; set; }

  public UserProfile()
  {
    CreationDate = DateTime.Now;
  }
}

To make sure the UserProfile data will be read when the ApplicationUser is accessed, I added a UserProfile property to this class, which is located in the file Models/IdentityModels.cs.

public class ApplicationUser : IdentityUser
{
  public virtual UserProfile UserProfile { get; set; }
}

Try to Create the Database Tables

After creating the database itself using SQL Server Management Studio and changing the connection string in Web.Config, I used the Package Manager Console to create the database tables. The console can be opened via Tools / NuGet Package Manager / Package Manager Console (or use Quick Launch [Ctrl+Q]).

To enable database migration, I first ran Enable-Migrations, which failed.

The error message was “Unable to determine the principal end of an association between the types ‘OneToOneTableRelationship.Models.UserProfile’ and ‘OneToOneTableRelationship.Models.ApplicationUser’. The principal end of this association must be explicitly configured using either the relationship fluent API or data annotations.“.

What does that mean? In short, EF does not know how the UserProfile and ApplicationUser relationship should be organized. Which one is the parent, and which one is the child. There are two ways on how to define this: by the relationship fluent API (means coding) or data annotations (means attributes on class properties).

Declare the Principal End of Association

I decided to use the coding approach and added the method OnModelCreating to the context class ApplicationDbContext (can be found in Models/IdentityModels.cs).

To complete the database context, I also added a DbSet<UserProfile> to gain access to that table.

public class ApplicationDbContext 
  : IdentityDbContext<ApplicationUser>
{
  public DbSet<UserProfile> UserProfile { get; set; }

  public ApplicationDbContext()
    : base("DefaultConnection")
  {
  }

  protected override void OnModelCreating
    (
    DbModelBuilder modelBuilder
    )
  {
    modelBuilder.Entity<UserProfile>()
      .HasRequired<ApplicationUser>(profile => profile.User);

    base.OnModelCreating(modelBuilder);
  }
}

Create the Database Tables

Now that EF knows how to build up the relationship, I created the database tables with two steps at the Package Manager Console.

Add-Migration Initiallize

created the code for the initial table setup. This code is located at the Migration folder.

Update-Database

ran that code and created the database tables.

After the update, the database contains, beside others, these two tables:

AspNetUsers tableUserProfiles table

Setting Up the Controller

When Visual Studio creates the controller class from the ASP.NET MVC project template, the class AccountController does not provide a DbContext property. A DbContext is passed as a parameter directly to the newly created UserManager instance by the default constructor. Unfortunately, UserManager does not provide access to the encapsulated DbContext.

To be able to access to the DbContext, I changed the AccountController to look like this:

[Authorize]
public class AccountController : Controller
{
  private ApplicationDbContext DbContext { get; set; }

  public AccountController()
  {
    DbContext = new ApplicationDbContext();

    UserManager 
      = new UserManager<ApplicationUser>(
          new UserStore<ApplicationUser>(DbContext));
    }

// removed: public AccountController(UserManager userManager)

// the rest was left unchanged

Fill the Child Table

Now I was ready to add a new entry to the UserProfile table when a new user registers. The method AccountController.Register was changed like this:

[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task Register(RegisterViewModel model)
{
  if (ModelState.IsValid)
  {
    var user = new ApplicationUser() 
    { 
      UserName = model.UserName, 
      UserProfile = new UserProfile()
    };

    using (TransactionScope scope 
      = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled))
    {
      var result 
        = await UserManager.CreateAsync(user, model.Password);

      scope.Complete();

      if (result.Succeeded)
      {
        await SignInAsync(user, isPersistent: false);
        return RedirectToAction("Index", "Home");
      }
      else
      {
        AddErrors(result);
      }
    }
  }

  // If we got this far, something failed, redisplay form
  return View(model);
}

Creating the user is wrapped by a database transaction to make sure the user will be created completely or not at all. Because UserManager.CreateAsync is async, the TransactionScope needs to be created with TransactionScopeAsyncFlowOption.Enabled. Please notice that this option is only available for .NET Framework 4.5.1 or above. To use the class TransactionScope, a reference to System.Transaction needs to be added to the project.

The call to UserManager.CreateAsync is doing all the magic. It creates the records in the tables AspNetUsers and UserProfile. It also makes sure that reference between the tables is set properly, means it sets UserProfile.User_Id to the correct value.

Summary

I took the following steps to have my custom user profile data connected to the ASP.NET user table:

  • Add the child model class
  • Add a property of the new type to the existing parent class
  • Declare the principal end of association, i.e. add a OnModelCreating to the DbContext to define which class is parent, and which is child
  • Create the database tables using the Package Manager Console
  • Update the controller to be able to store and retrieve the additional data

Consuming the data is easy. Just access the corresponding property like this:

DateTime creationDate = user.UserProfile.CreationDate;

Links

MSDN Data Developer Center: Code First to a New Database

Stack Overflow: What does principal end of an association means in 1:1 relationship in Entity framework

Stack Overflow: Get TransactionScope to work with async / await

Entity Framework: Loading Related Entities

Using Membership and Authorization in ASP.NET MVC 4

With the introduction of .NET 4.5 and MVC 4, some changes to Membership and Authorization came along.

To keep this posting as short as possible, I will just list the findings and refer to some postings I read.

1. Web Site Administration Tool is gone, and there is no replacement for it (weblogs.asp.net/jgalloway/archive/2012/08/29/simplemembership-membership-providers-universal-providers-and-the-new-asp-net-4-5-web-forms-and-asp-net-mvc-4-templates.aspx).

2. Use WebMatrix.WebData.SimpleMembershipProvider instead of System.Web.Providers.DefaultMembershipProvider in web.config (type="WebMatrix.WebData.SimpleMembershipProvider, WebMatrix.WebData, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35")

3. Use WebMatrix.WebData.SimpleRoleProvider instead of System.Web.Providers.DefaultRoleProvider in web.config (type="WebMatrix.WebData.SimpleRoleProvider, WebMatrix.WebData, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35")

4. There is no (WebMatrix.WebData.)SimpleProfileProvider.

5. To create the required tables yourself, here is a sample script from http://notebookheavy.com/2012/08/22/mvc-4-authentication/.

CREATE TABLE [dbo].[UserProfile] (
[UserId] INT IDENTITY (1, 1) NOT NULL,
[UserName] NVARCHAR (MAX) NULL,
PRIMARY KEY CLUSTERED ([UserId] ASC)
);
 
CREATE TABLE [dbo].[webpages_Membership] (
[UserId] INT NOT NULL,
[CreateDate] DATETIME NULL,
[ConfirmationToken] NVARCHAR (128) NULL,
[IsConfirmed] BIT DEFAULT ((0)) NULL,
[LastPasswordFailureDate] DATETIME NULL,
[PasswordFailuresSinceLastSuccess] INT DEFAULT ((0)) NOT NULL,
[Password] NVARCHAR (128) NOT NULL,
[PasswordChangedDate] DATETIME NULL,
[PasswordSalt] NVARCHAR (128) NOT NULL,
[PasswordVerificationToken] NVARCHAR (128) NULL,
[PasswordVerificationTokenExpirationDate] DATETIME NULL,
PRIMARY KEY CLUSTERED ([UserId] ASC)
);
 
 
CREATE TABLE [dbo].[webpages_OAuthMembership] (
[Provider] NVARCHAR (30) NOT NULL,
[ProviderUserId] NVARCHAR (100) NOT NULL,
[UserId] INT NOT NULL,
PRIMARY KEY CLUSTERED ([Provider] ASC, [ProviderUserId] ASC)
);
 
CREATE TABLE [dbo].[webpages_Roles] (
[RoleId] INT IDENTITY (1, 1) NOT NULL,
[RoleName] NVARCHAR (256) NOT NULL,
PRIMARY KEY CLUSTERED ([RoleId] ASC),
UNIQUE NONCLUSTERED ([RoleName] ASC)
);
 
CREATE TABLE [dbo].[webpages_UsersInRoles] (
[UserId] INT NOT NULL,
[RoleId] INT NOT NULL,
PRIMARY KEY CLUSTERED ([UserId] ASC, [RoleId] ASC),
CONSTRAINT [fk_UserId] FOREIGN KEY ([UserId]) REFERENCES [dbo].[UserProfile] ([UserId]),
CONSTRAINT [fk_RoleId] FOREIGN KEY ([RoleId]) REFERENCES [dbo].[webpages_Roles] ([RoleId])
);

6. One additional posting about “Using SimpleMembership With ASP.NET WebPages“.

ASP.NET MVC 4, VS 2012 and the Usage of jQuery UI

It took really some time to get the ASP.NET MVC jQuery sample on ASP.NET running.

At the time of writing, the sample was based on MVC 3, while I was working with MVC 4. Well, not a big deal, just change the name of some .css and .js files. But that doesn’t made it work. Starting the app, there was always an error indicating the datepicker function was unkown. And of course, the datepicker was not shown.

The solution was, as almost always, quite simple. For whatever reason, the _Layout.cshtml file generated by VS 2012 when creating an ASP.NET MVC 4 project, contains the following line at the bottom:

@Scripts.Render("~/bundles/jquery")

Removing this line made the jQuery UI parts work. Of course one should not forget to include the jQuery script and .css files into the header section of the layout file or move that line up there.

ASP.NET MVC 4 jQuery Validation Globalization

Going thru the ASP.NET MVC 4 intro on www.asp.net/mvc/tutorials/mvc-4/getting-started-with-aspnet-mvc4/adding-a-model, I thought that I couldn’t believe what I saw.

In this intro, a MVC Web application is built, having a page to enter movie data, including a date and a price. The price is a decimal value.

Now on my machine, the culture is en-US, while the UI culture is de-DE. Saving a price of 9.78 (where the point is the decimal separator), the app writes 978 into the database. And trying to save a date in German format (dd.MM.yyyy) leads to an “invalid date format” error on the client. On the other hand, the date entered in en-US format (MM/dd/yyyy), was displayed in German format after reading.

The kind of problem is not new to me. Working with UI apps (and not just in that case), one always has to consider the culture settings. What causes my surprise was the fact that still there seems to be no built-in support to handle this issue. Even ASP.NET MVC 4 is not able to handle this itself, making sure the client side validator validates the values using the correct culture settings 🙁

Well, I looked around a little bit, and found a solution. It doesn’t make me happy, but it works.

First, I extended the system.web section of the web.config to enable ASP.NET to set the UI culture and culture for a Web page automatically, based on the values that are sent by a browser:

<globalization enableClientBasedCulture="true" 
  culture="auto:en-US" 
  uiCulture="auto:en"/>

And then I extended the view with this code:

<script src="~/Scripts/globalize.js" type="text/javascript">
</script>
<script src="~/Scripts/globalize.culture.de-DE.js" type="text/javascript">
</script>
<script src="~/Scripts/globalize.culture.en-US.js" type="text/javascript">
</script>

<script>
  $.validator.methods.number = function (value, element) {
    return this.optional(element) ||
        !isNaN(Globalize.parseFloat(value));
  }

  $.validator.methods.date = function (value, element) {
    return this.optional(element) ||
        Globalize.parseDate(value);
  }

  $(document).ready(function () {
    Globalize.culture('@System.Threading.Thread.CurrentThread.CurrentCulture');
  });
</script>

<script>
  jQuery.extend(jQuery.validator.methods, {
    range: function (value, element, param) {
      //Use the Globalization plugin to parse the value        
      var val = Globalize.parseFloat(value);
      return this.optional(element) || (
          val >= param[0] && val <= param[1]);
    }
  });
</script>

Update: Please have a look at the comments below. Dan shared his solution for the situation when the user is in a browser that has native datepicker/number support and an unknown culture (i.e. you don’t want to account for and load ALL globalize.js culture files. Thanks, Dan!

Since this code is needed by several views, I put it into a partial view and included it into the Scripts section using

@Html.Partial("_PartialViewName");

In this context I think it’s worth it to mention that the link to the jQuery Globalization plugin https://github.com/nje/jquery-glob, which is mentioned in the Web several times, works, but the new location, where it should reside now (https://github.com/jquery/jquery-global, is not valid. I found the required files on https://github.com/jquery/globalize and copied the required files from the lib directory.