OAuth 2.0 with Google

After getting Basic Authentication and Authorization working I thought it would be neat to add login via Google which involves using OAuth 2.0. To get started I used NuGet to update all the OWIN related packages in my project. I ran across some people who had issues with older versions of OWIN so I recommend getting the latest to avoid any potential problems.

Some third parties require SSL when using their auth services so I decided to go a head and change my application to use SSL. I hit a couple of issues during this part of the process that I want to point out. The first is that when you change to SSL IIS Express defaults to using port 44300. I missed this the first try and it took a good bit of searching before I spotted the problem. Even after reverting all my changes I could not get my site to load without errors. A reboot got my reverted site working which I am assuming was a configuration issue with IIS Express that got reset on reboot.

To enable SSL select the project in Solution Explorer and press F4 to bring up the properties window (which has different options that the project properties you get if you right-click the project and click properties). Set the SSL Enabled property to true. Copy the SSL URL to use when updating the project.ContactsPropertiesSsl

Back in the Solution Explorer right-click on the project and click properties. On the Web tab under the Servers section paste the SSL URL from above into the Project Url and save.ContactsProjectPropertiesSslUrl

When running the first time after enabling SSL Visual Studio will prompt asking if you would like to trust the self-signed certificate that IIS Express generated. I chose to trust in order to avoid warnings from the browser.

OAuthTrustIISSSL

The last change need in the project is in the Statup.Auth.cs found in the App_Start folder. In the ConfigureAuth function add the following code using your own ClientId and ClientSecret.

app.UseGoogleAuthentication(new GoogleOAuth2AuthenticationOptions()
{
    ClientId = "Your Client ID",
    ClientSecret = "Your Client Secret"
});

If you don’t have a client ID and client secret head to the Google Developers Console. The first step in the process is to Click the Create Project button.

GoogleDevelopersConsoleEnter a project name and project ID. The refresh button on the project ID field will randomly generate project IDs in case the one you want is already in use. When finished click Create.
GoogleDevelopersConsoleNewProjectAfter the project creation process finishes click on the name of your project. Next click on the APIs & auth section and then click the Consent screen option. This set of options determines what the user sees when Google prompts a user for consent to use information from their Google account. The minimum needed is email address and product name. For a live application I would recommend filling out as much as possible to give the user the best experience. When done click Save.GoogleDevelopersConsoleAPIsAndAuthConsentScreenIn the same APIs & auth section click the APIs option. Search for Google+ API. Click the name Google+ API and on the next screen click Enable API.GoogleDevelopersConsoleAPIsAndAuthApisGooglePlusAgain in the APIs & auth section click on Credentials option and then in the OAuth section fo the page click Create new Client ID.
GoogleDevelopersConsoleAPIsAndAuthCredentialsThe following dialog will show. Select the appropriate Application type which is Web application for this example. For Authorized JavaScript origins use the value from Project Url listed above which in my case is https://localhost:44300/. For Authorized redirect URIs the base URI is the same but with an added level. For MVC 5 the redirect should be set to https://localhost:44300/signin-google changing the base URI as needed of course. Click Create Client ID and you will be returned to the previous page that will now list the Client ID and Client Secret needed in Statup.Auth.cs.
GoogleDevelopersConsoleAPIsAndAuthCredentialsCreateClientId

Now the login page will have a button for Google which will allow users to create an account and associate it with their Google account. After the association users will be able to login with their Google account.LoginWithGoogle

 

From this point adding Microsoft, Facebook or Twitter would just be a matter of adding the desired options to ConfigureAuth Startup.Auth.cs and going to each service and requesting API access.

Basic Authentication and Authorization

When I created my contact application I did so with authentication set to Individual User Accounts as seen below.
vs2013NewAspProject

 

By choosing an authentication option during project creation Visual Studio takes care of a lot of the work involved with getting authentication and authorization up and running. For individual user accounts the default data store is SQL and Visual Studio sets up the need classes and data using entity framework to create a database and the needed tables to store authentication data. An AccountController and associated views are also created to handle user creation and login.

I am not going to cover everything that Visual Studio created automatically. I will be walking you through the other changes are needed to start using authentication and authorization with all the bits Visual Studio has provided.

The first step is to add AuthorizeAttribute to the FilterConfig which is found in the App_Start folder.

public class FilterConfig
{
    public static void RegisterGlobalFilters(GlobalFilterCollection filters)
    {
        filters.Add(new HandleErrorAttribute());
        filters.Add(new AuthorizeAttribute());
    }
}

Now that the AuthorizeAttribute is added to the applications filters any page that is requested by a user that is not authorized will be redirected to a login page to authenticate.

With authorization and authentication now in play any controller action that should allow anonymous usage will need to have the AllowAnonymous attribute added. The following example is using AllowAnonymous on the index action of the home controller.

public class HomeController : Controller
{
    [AllowAnonymous]
    public ActionResult Index()
    {
        return View();
    }
}

That is all there is to get the very basics going. This is a big subject, but Visual Studio and .Net do a lot of work to make getting basics up and going simple.

Adding Paging

As the number of contacts grows it is overwhelming to see in single page. To address this I am going to add paging to the contact list and only show 10 contacts per page.

To generate a large set of realistic date I am using Mockaroo. They offers data in CSV, Tab-Delimited, SQL, Excel, JSON and DBUnit XML with up to 1,000 rows of data per generation for free. The data Mockaroo is way better than the crazy stuff I was coming up with. If you need more than 1,000 rows at a time they do have a pay option.

For paging I am going to take advantage of the PagedList.Mvc NuGet package. Using the package manager console it can be installed with the Install-Package PagedList.Mvc command as seen in the following screenshotPackageManager-PagedListMvc.

To start using PagedList.Mvc I need the following changes to ContactsController. Add new using for PagedList and the index action needs a page parameter. As part of this change I also refactored the contact query to the GetContacts function so the Index action is much less cluttered than before. The function is now shown below but I moved the distinct city query to the GetDistinctCities function.

        
public ActionResult Index(string filterCity, string filterSearch, int? page)
{
    ViewBag.filterCity = filterCity;
    ViewBag.filterSearch = filterSearch;
    ViewBag.city = new SelectList(GetDistinctCities());

    var contacts = GetContacts(filterCity, 
                               filterSearch)
                   .ToPagedList(page ?? 1, 10);

    if (Request.IsAjaxRequest())
    {
        return PartialView("_ContactList", contacts);
    }

    return View(contacts);
}

private IQueryable<Contact> GetContacts(string city, string search)
{
    var contacts = from c in db.Contacts
                   select c;

    if (!string.IsNullOrWhiteSpace(search))
    {
        contacts = contacts.Where(c => c.Name.Contains(search));
    }

    if (!string.IsNullOrWhiteSpace(city))
    {
        contacts = contacts.Where(c => c.City == city);
    }
     return contacts.OrderBy(c => c.Name);
}

Notice that I am now saving the parameter values of the city and search filters to the ViewBag in the index action which will be used when changing pages when a filter is in play.

In GetContacts I had to add an order by statement to the contacts being returned. This is to make sure the list is always in the same order. It will also be a good spot to add different ordering options in the future.

The last change in the Index action was to take the return value from GetContacts and call ToPagedList on it. This function takes a page number and number of items per page and returns a paged list as the name implies. In my case if page is null I am using page 1 and each page will contain 10 items.

In both Index.cshtml and the partial view _ContactList.cshtml the models need to be changed to PagedList.IPagedList. In addition @Html.DisplayNameFor also needs to be changed from model.Name to model.FirstOrDefault().Name. The last step is to add the paged list control to the bottom of the view. Here is the code from the contact list partial view.

@using PagedList.Mvc
@model PagedList.IPagedList<Contacts.Models.Contact>

<p>
    @Html.ActionLink("Create New", "Create")
</p>
<table class="table">
    <tr>
        <th>
            @Html.DisplayNameFor(model => model.FirstOrDefault().Name)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.FirstOrDefault().Address)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.FirstOrDefault().City)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.FirstOrDefault().State)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.FirstOrDefault().ZipCode)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.FirstOrDefault().Country)
        </th>
        <th></th>
    </tr>

    @foreach (var item in Model)
    {
        <tr>
            <td>
                @Html.DisplayFor(modelItem => item.Name)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.Address)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.City)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.State)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.ZipCode)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.Country)
            </td>
            <td>
                @Html.ActionLink("Edit", "Edit", new { id = item.Id }) |
                @Html.ActionLink("Details", "Details", new { id = item.Id }) |
                @Html.ActionLink("Delete", "Delete", new { id = item.Id })
            </td>
        </tr>
    }

</table>

@Html.PagedListPager(Model,
                     page => Url.Action("Index",
                                        "Contacts",
                                        new { ViewBag.filterCity,
                                              ViewBag.filterSearch,
                                              page }),
                     PagedListRenderOptions.EnableUnobtrusiveAjaxReplacing(
                          new AjaxOptions
                          {
                              HttpMethod = "GET",
                              UpdateTargetId = "contactList"
                          }))

The Url.Action on the PagedListPager is the function that will be called when the user want to changes pages. Index is the action that will be called, Contacts is the controller that the action will be called on. Next is an anonymous type that will be processed to determine what parameters the index action will be called with. It is important that the existing filters are passed to the index action or else when the pager requests a different page it will return all contacts instead of next page of the filtered set of contacts.

The other nice option that the PagedListPager offers is the option to use ajax when requesting a different page. Since the contact page is using ajax when filtering it would be silly not to do the same when paging. To enable ajax just use the PagedListRenderOptions.EnableUnobtrusiveAjaxReplacing with the same AjaxOptions as the filter form.

As a side note I have changed the AjaxOptions on the index view that are used for filtering to match what is shown above for paging. I also removed the accepted verbs from the index action so it only responds to get requests. The request for a new set of data based on a filter change is really more of a get operation than a post operation.

Partial View with AJAX

This is step two of applying filters to my contact list without refreshing the whole page. I will be using the partial view created in last week’s post.

I ran into a bit of trouble getting ajax working. It seems that starting in MVC 5 the jQuery plugin needed to make this form of ajax work is no longer included by default. In order to fix use NuGet and install jQuery.Unobtrusive.Ajax.nuget-jqueryajax

After the NuGet package is installed add a new bundle (or add to an existing bundle) for the jQuery unobtrusive files to the BundleConfig found in the App_Start folder.

bundles.Add(new ScriptBundle("~/bundles/jqueryunob").Include(
            "~/Scripts/jquery.unobtrusive*"));

If a new bundle was added then make sure to render the new bundle in the _Layout.cshtml file in the Views/Shared folder.

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

The next step was to change the index action of contacts controller. The index action now needs to accept both gets and posts which can be accomplished via the AcceptVerbs attribute. The second change needed in the index action is to return a partial view instead of a view if the request is an ajax request.

[AcceptVerbs(HttpVerbs.Get | HttpVerbs.Post)]
public ActionResult Index(string city, string search)
{
    var cityList = new List<string>();
    var cityDistinct = from c in db.Contacts
                       orderby c.City
                       select c.City;

    cityList.AddRange(cityDistinct.Distinct());
    ViewBag.city = new SelectList(cityList);

    var contacts = from c in db.Contacts
                   select c;

    if (!string.IsNullOrWhiteSpace(search))
    {
        contacts = contacts.Where(c => c.Name.Contains(search));
    }

    if (!string.IsNullOrWhiteSpace(city))
    {
        contacts = contacts.Where(c => c.City == city);
    }

    if (Request.IsAjaxRequest())
    {
        return PartialView("_ContactList", contacts);
    }

    return View(contacts);
}

Reusing the index action is only one option to implement the needed changes. Another option would be to add another action to the controller that would return the partial view. In this case the  common query code would be moved to a function.

The last set of changes needed are in the index view. Instead of using Html.BeginForm Ajax.BeginForm should be used. The section of the page that will be replaced via the ajax request needs to be moved to a div with an id. In the example below I added a div with the id of contactList. It is important that the div id match the UpdateTargetId in AjaxOptions.

@model IEnumerable<Contacts.Models.Contact>

@{
    ViewBag.Title = "Index";
}

<h2>Index</h2>

<p>
    @using (Ajax.BeginForm("Index",
                           "Contacts",
                           new AjaxOptions
                           {
                               UpdateTargetId = "contactList"
                           }))
    {
        <p>
            City: @Html.DropDownList("city",
                                     ViewBag.city as SelectList,
                                     "All",
                                     new {@class = "city",
                                          onchange = "$(this.form).submit();"})
            Name: @Html.TextBox("Search")
            <input type="submit" value="Filter"/>
        </p>
    }
</p>
<div id="contactList">
    @{
        Html.RenderPartial("_ContactList");
    }
</div>

One thing to make special note of is the that the onchange for the city drop down list has change from “this.form.submit();” to “$(this.form).submit();”. Without this change the request will not come through as an ajax request and the full page will refresh instead of just the contact list section. I wasted a lot of time trying to track down why a full page request was happening and the issue ended up being the way that the drop down list was submitting the form.

Partial Views

On my contacts list page I want to apply filters without refreshing the whole page. This post is about step one of my first try at accomplishing this goal.

To add a partial view right clicked on the destination folder for the new view and from the Add menu select the View option.AddViewMenu

This brings up the Add View dialog. I am adding a view call _ContactList using the list template since this is going to be a list of contact. Contact is the model the list will be based on and any data access will happen via the ContactDbContext. The last thing to do is check the create as a partial view check box. Clicking add creates a _ContactList.cshtml file.AddViewDialog

The resulting code in _ConactList.cshtml looks like this:

@model IEnumerable<Contacts.Models.Contact>

<p>
    @Html.ActionLink("Create New", "Create")
</p>
<table class="table">
    <tr>
        <th>
            @Html.DisplayNameFor(model => model.Name)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.Address)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.City)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.State)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.ZipCode)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.Country)
        </th>
        <th></th>
    </tr>

@foreach (var item in Model) {
    <tr>
        <td>
            @Html.DisplayFor(modelItem => item.Name)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.Address)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.City)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.State)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.ZipCode)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.Country)
        </td>
        <td>
            @Html.ActionLink("Edit", "Edit", new { id=item.Id }) |
            @Html.ActionLink("Details", "Details", new { id=item.Id }) |
            @Html.ActionLink("Delete", "Delete", new { id=item.Id })
        </td>
    </tr>
}

</table>

As you can see by choosing the contact model Visual Studio was able to build a view that displays all the properties of the contact. Since I chose the list template the view is expecting a list of contacts that it will iterate over that list and create a table from the list of contacts.

In my index view I was able to remove all the code associated with the contact list and replace it with the following code which renders my new partial view.

@{
    Html.RenderPartial("_ContactList");
}

This partial view will allow me to have a consistent view of my contact list any where I may need it. It is also my hope that this partial view will allow me to refresh the list portion of the contact list page when a filter is changed.

Add a Dropdown Filter

On my contacts application I wanted the option to only show contacts from a specific city. To accomplish this I am going to use a dropdown with a distinct list of cities that exist in my contact list.

Below is part of the existing contacts controller with the Index action that gets all contacts and returns a view.

public class ContactsController : Controller
{
    private ContactDbContext db = new ContactDbContext();

    // GET: Contacts
    public ActionResult Index()
    {
        var contacts = from c in db.Contacts
                       select c;
        return View(contacts);
    }
}

Using ContactDbContext, which is a entity framework DbContext for contacts, the database will be queried for a list of distinct cities. The list of distinct cities is then stored as a select list in the view bag.

var cityList = new List<string>();
var cityDistinct = from c in db.Contacts
                   orderby c.City
                   select c.City;

cityList.AddRange(cityDistinct.Distinct());
ViewBag.city = new SelectList(cityList);

ViewBag is a dynamic object and is one way to pass data from a controller to a view. A dynamic object basically allows you to add properties just by setting them. In the above example the with ViewBag.city is adding a city property to the ViewBag and setting it equal to a new SelectList.

The resulting index action now takes a city parameter which is used when querying for contact if it has a value.

public ActionResult Index(string city)
{
    var cityList = new List<string>();
    var cityDistinct = from c in db.Contacts
                       orderby c.City
                       select c.City;

    cityList.AddRange(cityDistinct.Distinct());
    ViewBag.city = new SelectList(cityList);

    var contacts = from c in db.Contacts
                   select c;

    if (!string.IsNullOrWhiteSpace(city))
    {
        contacts = contacts.Where(c => c.City == city);
    }

    return View(contacts);
}

In my razor view the following adds the new city filter to the UI.

@using (Html.BeginForm("Index", "Contacts", FormMethod.Get))
{
<p>
    City: @Html.DropDownList("city", 
                             ViewBag.city as SelectList, 
                             "All", 
                             new {@class = "city", 
                                  onchange = "this.form.submit();"})
</p>
}

“All” is the label used for the default empty item. The last bit is for HTML attributes and set the class for the drop down to “city” and makes it so the form submits on change of the drop down. This means that when a new city is selected the view will refresh and only show contacts for the newly selected city.

This is the resulting UI:CityFilterUi

Multi-property Custom Validation Attributes

I am going to expand on last week’s Simple Custom Validation Attributes with custom validation attributes that need to look at more than a single property of a model. Again using the contact application example, lets say that if a contact has a country of USA then state and zip code are required.

As before we have class which inherits from ValidationAttribute. IsValid is still overridden, but it is a different overload than the previous example that provides access to the ValidationContext, which in our case is the contact model that is being validated.

using System;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Reflection;

public class ValidCountryRequired : ValidationAttribute
{
    private readonly string _countryProperty;
    private readonly string[] _requriedByCountries;

    public ValidCountryRequired(string countryProperty,
                                string[] requriedByCountries)
    {
        _countryProperty = countryProperty;
        _requriedByCountries = requriedByCountries;
    }

    protected override ValidationResult IsValid(object value,
                                                ValidationContext context)
    {
        PropertyInfo propertyInfo;
        propertyInfo = context.ObjectType.GetProperty(_countryProperty);
        if (propertyInfo == null)
        {
            return new ValidationResult(_countryProperty +
                                        " does not exist");
        }

        var country = propertyInfo.GetValue(context.ObjectInstance, null);

        if (_requriedByCountries.Contains(country.ToString()) &&
            (value == null ||
             String.IsNullOrWhiteSpace(value.ToString())))
        {
            return new ValidationResult(context.DisplayName +
                                        " is requried for contacts from " +
                                        country);
        }

        return null;
    }
}

For this example I have added a constructor that takes the name of the country property in the model being validated and a string array of the countries that need to make sure the state and zip code are filled in. Both parameters are stored in class level variables for use in the IsValid function.

The IsValid function is still where all the work takes place. The overload of IsValid we are working with provides the value of the property being validated and the validation context that validation is running for. The validation context will allow us to access other properties on the model being validated.

The first step to checking a different property than the one being validated is to get the property info from the validation context by using context.ObjectType.GetProperty and passing the property name that was passed in via the constructor. If GetProperty returns null then the context did not contain the property that was expected. In this case a new ValidationResult is returned with a message that the expected country property was not found.

Using the property info for the country property we can call GetValue with context.ObjectInstance to get the contact’s country. If that country is found in the string array of countries that require the property being validated then a check is run to make sure the property has a value and is not blank.

If the property does not have a value then a new ValidationResult is returned with an error message. If the property does have a value then null is returned indicating that the property is valid.

Example usage from my contact model:

[ValidCountryRequired("Country", new[] { "USA" })]
public string State { get; set; }
[Display(Name = "Zip Code")]
[ValidCountryRequired("Country", new[] { "USA" })]
public string ZipCode { get; set; }

One other thing to note is the usage of context.DisplayName when creating the ValidationResult. By using display name in the message the ZipCode property will show as “Zip Code” in the message returned.

Simple Custom Validation Attributes

Last week I did an overview of  Data Annotations. This week I am going to expand on data annotations by giving an example of a very simple custom validation attribute.

Sticking with my contact application theme lets say that I only wanted to allow contacts from a very small list of countries. The .Net framework does not have a built in validation attribute to cover this scenario which means I would need to create my own custom validation attribute to fill this need.

To create a custom validation attribute all you need is a class that inherits from ValidationAttribute and overrides the IsValid function.

using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;

public class ValidCountry : ValidationAttribute
{
    private readonly List<string> validCountries = new List<string>
    {
        "USA",
        "Canada",
        "Mexico"
    }; 

    public override bool IsValid(object value)
    {
        return value != null &&
               !validCountries.Contains((string)value);
    }
}

When validation for a property is performed the IsValid function of all the property’s validation attributes are run. The IsValid function is called with the value of the property being validated which will have to be cast to the type needed for validation. In my country example value is being cast to string and used see if the value is found in a list of valid countries.

Any property with the ValidCountry attribute would not validate unless the property was set to USA, Canada or Mexico. This is a contrived example, but it does give you an idea of how easy it is to add your own custom validation attributes.

Data Annotations

Validation via data annotations in .NET is a great feature that is simple to implement. Here is an example model class that is using data annotations.

using System.ComponentModel.DataAnnotations;

namespace Contacts.Models
{
    public class Contact
    {
        [Required]
        [StringLength(50, MinimumLength = 4)]
        public string Name { get; set; }
        [StringLength(2)]
        public string State { get; set; }
        [Display(Name = "Zip Code")]
        [StringLength(10)]
        public string ZipCode { get; set; }
    }
}

First step in using data annotations is to add a using statement for the System.ComponentModel.DataAnnotations namespace. This namespace allows you to add validation attributes to the properties that require validation and contains helper classes to run validate on attributed models.

In the example above Required, StringLength and Display are all validation attributes. For the most part the attributes are self-explanatory, but be aware most attributes also have options to give you more control of the validation. For example required attribute has an AllowEmptyStrings property that if set to true will allow an empty string to pass validation. String length is another example which has options for minimum and maximum lengths for the property being validated.

This is just a small sample of the built-in attributes that exist. Other built-in attributes range  from credit card and email address validation to file extension and range validation. If a built-in validation does not meet your needs then a custom attribute a can be created by deriving from ValidationAttribue.

MVC has a lot of great functionality built around data annotations. For instance as long as a client has JavaScript turned a form will not allow submission until the model passes all the validation conditions. On the server-side inside of a controller to run validation all it takes is to run ModelState.IsValid.

With winforms the story is not quite as simple, but still pretty straight forward. The following is a simple example of calling validation on a model.

private void ValidationExample()
{
    var contact = new Contact { Name = "Bob", State = "TN" };

    var context = new ValidationContext(contact);
    var errors = new List<ValidationResult>();

    if (!Validator.TryValidateObject(contact, context, errors))
    {
        foreach (ValidationResult result in errors)
        {
            //act on error
        }
    }
}

Validator.TryValidateObject takes the model to be validated, a validation context (created with the model to validate) and an empty list of type ValidationResult. The function call returns false if any properties fail validation. In the example above the validation would fail since name only contains three characters the minimum length is set to four characters.

Duplicate Records from Migration Seed

I am writing a contact management application as a vehicle for my ASP.NET MVC learning using Entity Framework 6. To pre-load some test data I utilize the Seed method found in Migrations\Configuration.cs which gets added when migrations are enabled for a project.

When testing the contact creation process I noticed that I forgot to add a property for contact’s state. Easy enough to fix. I opened up the Contact class, added the missing state property and updated all the related views. Then I ran the app to test my change and was greeted with this error:ContextChanged

Of course the model backing my DbContext has changed since the database was created, I just added a new property to the model. Being new to entity framework workflow I often see this error when I forget to update the database before running the app to try out a change. It is easy to fix by using the package manager console to Add-Migration and then Update-Database.

After updating the database I ran the app to verify my changes. What I saw when my contact list load was that all my seed data had been duplicated. The jest of my seed function was something like this:

context.Contacts.AddOrUpdate(c => c.Id,
    new Contact
    {
        Id = 0,
        Name = "Eric",
        State = "TN"
    },
    new Contact
    {
        Id = 1,
        Name = "Tommy",
        State = "ND"
    });

To track down the duplication issue the first thing I did was to view the data in the database to make sure the table a primary key set. The Id field was an integer identity column and was the primary key. Next I viewed all the records in the table which looked like this:

Id Name State
0 Eric TN
1 Tommy ND
2 Eric TN
3 Tommy ND

The Id lookup I defined as the first parameter to AddOrUpdate seemed to be my issue. From my tests it seems that AddOrUpdate will always perform an add when trying to match on an identity type column. By changing from c => c.Id to c => c.Name no data is duplicated.