Using JSON to store application preferences and configuration

Download full source code.

Storing configuration preferences in the database is not a hard task. It usually involves storing the name of the preference, the value and the type in the database. Then when retrieving the data you perform some sort of cast.

The casts tend to be a bit painful, but it works.

This is the call –

 
bool displayWidget = (bool) Convert.ChangeType(_preferenceManager.BadWayToCastToGetPreference("DisplayWidget"), typeof(bool));

And this is the called method –

 
        public object BadWayToCastToGetPreference<T>(string name)
        {
            var preference = Convert.ChangeType(_context.Preferences.SingleOrDefault(p => p.Name == name).Value, typeof(T));
            return preference;
        }

But this quickly falls apart when you want to store a list of something, this requires a custom way of generating a string that represents the list. A common way I’ve seen is to store the values as a pipe delimited list.

For example if you wanted to store three cities
Boston, New York and Seattle
they would become “Boston|New York|Seattle” when stored in the database.

Now you need a write code to turn that back into a list of strings.

The problem gets worse when you want to store some custom types, for example an emergency contact shaped like –

    public class EmergencyContact
    {
        public int Priority { get; set; }
        public string EmailAddress { get; set; }
    }

Or worse if you want to store a list of emergency contacts.

Rather than suffering all that pain, just use Json to serialize and deserialize the values. This makes life a lot easier.

I have a simple method to create the preference object that gets store in the database –

        private Preference CreatePreference(string name, string value, string type)
        {
            var preference = new Preference
            {
                Name = name,
                Value = value,
                Type = type,
                PreferenceID = Guid.NewGuid()
            };
            return preference;
        }

CreatePreference gets called like this for a simple string –

            string defaultEmail = "admin@example.com";
            Preference preference1 = CreatePreference("DefaultEmail", JsonConvert.SerializeObject(defaultEmail), defaultEmail.GetType().ToString());

And it’s the same when storing a more complex type.

            EmergencyContact[] secondaryEmergencyContacts = new[]
            {
                new EmergencyContact{ EmailAddress = "tom@example.com", Priority = 1},
                new EmergencyContact{ EmailAddress = "dick@example.com", Priority = 2},
                new EmergencyContact{ EmailAddress = "harry@example.com", Priority = 3},
            };
            Preference preference6 = CreatePreference("SecondaryEmergencyContacts",
                JsonConvert.SerializeObject(secondaryEmergencyContacts), secondaryEmergencyContacts.GetType().ToString());

To store these preferences in the database, its just simple Entity Framework.

            _context.Preferences.Add(preference1);
            _context.Preferences.Add(preference6);
            _context.SaveChanges();

And then to get the preferences back out of the database you call –

        public T GetPreference<T>(string name)
        {
            var preference =
                JsonConvert.DeserializeObject<T>(_context.Preferences.SingleOrDefault(p => p.Name == name).Value);
            return preference;
        }

Some might complain that it is slower than direct casts, and yes, it probably is. But if you haven’t measured it you shouldn’t optimize it. You can cache always cache preferences. And it is a lot neater than the alternative.

Download full source code.

CastleWindsor chained dependency

Source code is available here.

I recently had a problem where I wanted an MVC controller to use constructor injection of specified dependency and have that dependency load another specified dependency using Windsor.

For example, I have a message of the day controller and it can get messages from either a file or from a database. To support this I have a message of the day service which formats the text it retrieves from a message of the day loader.

But as I said I have two ways of loading the message, so for the sake of this demo I have two services and two loaders.

Controller, service and loader dependencies

Controller, service and loader dependencies

I don’t want my controller to request a named instance, I just want to register the implementations in the installers and let Windsor do the rest.

If the controller is using the database service, I want the database service to use the database loader; if the controller is using the file service, I want the file service to use the file loader.

To support this I added a ContractInstaller as shown here.

    public class ContractInstaller : IWindsorInstaller
    {
        public void Install(IWindsorContainer container, IConfigurationStore store)
        {
            container.Register(
                 Component.For<IMessageLoader>().ImplementedBy<MessageLoaderDatabase>()
                ,Component.For<IMessageLoader>().ImplementedBy<MessageLoaderFile>()

                ,Component.For<IMessageOfTheDayService>().ImplementedBy<MessageOfTheDayServiceDatabase>()
                    .DependsOn(Dependency.OnComponent<IMessageLoader, MessageLoaderDatabase>())

                ,Component.For<IMessageOfTheDayService>().ImplementedBy<MessageOfTheDayServiceFile>()
                    .DependsOn(Dependency.OnComponent<IMessageLoader, MessageLoaderFile>())

                ,Component.For<MessageOfTheDayController>().LifestyleTransient()
                    .DependsOn(Dependency.OnComponent<IMessageOfTheDayService, MessageOfTheDayServiceFile>())
            );
        }
    }

In lines 6 and 7 I register the loaders (IMessageLoader), and in lines 9 and 12 I register the the services (IMessageOfTheDayService) and they in turn depend on the registered loaders.
In line 15 I register the controller (MessageOfTheDayController) and its dependency on IMessageOfTheDayService, in this case it is using MessageOfTheDayServiceFile.
To use the MessageOfTheDayServiceDatabase, change the dependency on line 16.

Be sure to load this before the ControllersInstaller provided by the Windsor nuget or you will get a clash between the MessageOfTheDayController loaded by both installers. To make sure this happens I alter the default Bootstrap method in ContainerBootstrapper to the following.

        public static ContainerBootstrapper Bootstrap()
        {
            var container = new WindsorContainer().Install(
                new ContractInstaller(),
                new ControllersInstaller()
                );

            return new ContainerBootstrapper(container);
        }

Now when you run the app, the controller will be instantiated with the MessageOfTheDayServiceDatabase which in turn will be instantiated with MessageLoaderDatabase.

Entity Framework lazy loading vs explicit loading and the generated SQL

Download the source code here.
If you are using lazy loading with Entity Framework you should check that queries to the database are working as expected.

A lazy load call to something like customer.Orders.FirstOrDefault() will give you a single order, but if you look at the SQL executed you’ll see that all orders for the customer are returned from the database; it is your code that is taking first one from memory. Depending on your application, this may have significant performance implications especially as the amount of data grows.

However, using explicit loading I am able to return just the one order I need.

In this post I’ll show how to use lazy loading and explicit loading, and compare the generated SQL for each.

The CustomerController contains a lazy and explicit Index action method and the OrderController contains an lazy and explicit Details action method.

To view the SQL generated for each query I used glimpse; turn it on by going to http://localhost:63817/glimpse.axd and clicking the “On” button.

Download the source code here.

Lazy Loading

By default lazy loading is enabled in EF. To take advantage of it all you do is mark the related entity as virtual, EF will do the rest.

public class Customer
{
   public int CustomerID { get; set; }
   public string Firstname { get; set; }
   public string Lastname { get; set; }
   public virtual ICollection<Order> Orders { get; set; }
}

When you call customer.Orders EF overrides the Orders virtual method and makes the appropriate call to the database to load all orders for the that customer. The problem is that all orders are loaded even if you only want to the first order.

Open the attached solution and take a look a the Customer IndexLazy action method and its associated view, it shows just the first order for each customer.

The IndexLazy action method loads the customers from the database, but does not load the orders. It is in the view that the orders are lazily loaded when generating the action links to the order details page –

item.Orders.FirstOrDefault().OrderID

Examination of the executed SQL shows that all orders for that customer were returned from the database even though only the first was used.

Explicit Loading

A more efficient approach is shown in the IndexExplicit action method. It disables lazy loading by calling –

db.Configuration.LazyLoadingEnabled = false;

The action method then loads the customers from the database as above. Then the first order for each customer is loaded into the Orders property of the Customer.

   foreach (var customer in customers)
   {
      db.Entry(customer).Collection(c => c.Orders).Query().Take(1).Load();
   }

In this way only one order record for each customer is returned from the database.

The Data

The data model is very simple, an orders table, a customer table and an order items table.
Zero or more order items are associated with an order, and zero or more orders are associated with a customer.

In the provided data, there are two customers, each with four orders made up of varying numbers of order items; take a look at the global.asax.cs to see exactly – note that in this code the way I initialize and seed the database are NOT what you should do for a serious piece of code.

Scroll to the bottom of the page to see the actual data in the tables.

The Execution

Customer page
Firstly go to the customer index which is lazily loaded – http://localhost:63817/Customer/IndexLazy

You’ll see two rows on the page representing the two customers and one order from each.
Here is the sql that was executed using lazy loading.

SELECT
[Extent1].[CustomerID] AS [CustomerID],
[Extent1].[Firstname] AS [Firstname],
[Extent1].[Lastname] AS [Lastname]
FROM [dbo].[Customers] AS [Extent1]

Two customers returned

SELECT
[Extent1].[OrderID] AS [OrderID],
[Extent1].[OrderDate] AS [OrderDate],
[Extent1].[Comment] AS [Comment],
[Extent1].[CustomerID] AS [CustomerID]
FROM [dbo].[Orders] AS [Extent1]
WHERE [Extent1].[CustomerID] = 1 /* @EntityKeyValue1 */

All four orders for customer 1 are returned from the database even though only one is needed

SELECT
[Extent1].[OrderID] AS [OrderID],
[Extent1].[OrderDate] AS [OrderDate],
[Extent1].[Comment] AS [Comment],
[Extent1].[CustomerID] AS [CustomerID]
FROM [dbo].[Orders] AS [Extent1]
WHERE [Extent1].[CustomerID] = 2 /* @EntityKeyValue1 */

All four orders for customer 2 are returned from the database even though only one is needed

Now go to localhost:63817/Customer/IndexExplicit and see the improvements of explicit loading.

SELECT
[Extent1].[CustomerID] AS [CustomerID],
[Extent1].[Firstname] AS [Firstname],
[Extent1].[Lastname] AS [Lastname]
FROM [dbo].[Customers] AS [Extent1]

Two customers returned

SELECT TOP (1)
[Extent1].[OrderID] AS [OrderID],
[Extent1].[OrderDate] AS [OrderDate],
[Extent1].[Comment] AS [Comment],
[Extent1].[CustomerID] AS [CustomerID]
FROM [dbo].[Orders] AS [Extent1]
WHERE [Extent1].[CustomerID] = 1 /* @EntityKeyValue1 */

One order returned for customer 1, this is what we wanted, note the use of TOP (1) ensuring that just one order is retrieved. Compare that to the SQL called for the lazy load.

SELECT TOP (1)
[Extent1].[OrderID] AS [OrderID],
[Extent1].[OrderDate] AS [OrderDate],
[Extent1].[Comment] AS [Comment],
[Extent1].[CustomerID] AS [CustomerID]
FROM [dbo].[Orders] AS [Extent1]
WHERE [Extent1].[CustomerID] = 2 /* @EntityKeyValue1 */

One order returned for customer 2, again here we are getting just the one record we wanted.

Summary of lazy loading vs explicit loading for index page

TaskLazy Loaded RowsExplicit Loaded Rows
Retrieve customers22
Retrieve Steve's orders41
Retrieve James' orders 41

When using EF it is not enough to be aware of the reasons for using iqueryable vs ienumerable, you should look at the usage scenario of the entities you are loading from the database, especially those that are lazily loaded.

Order details page

From the customer index view, navigate to the order details view for both of the customers, it shows the customer, his first order and the first order item on that first order. The order details view can be loaded from two action methods, one uses lazy loading and the other explicit.

Below are the SQL calls using lazy loading.

SELECT TOP (2)
[Extent1].[CustomerID] AS [CustomerID],
[Extent1].[Firstname] AS [Firstname],
[Extent1].[Lastname] AS [Lastname]
FROM [dbo].[Customers] AS [Extent1]
WHERE [Extent1].[CustomerID] = 1 /* @p0 */

returns one customer record

SELECT
[Extent1].[OrderID] AS [OrderID],
[Extent1].[OrderDate] AS [OrderDate],
[Extent1].[Comment] AS [Comment],
[Extent1].[CustomerID] AS [CustomerID]
FROM [dbo].[Orders] AS [Extent1]
WHERE [Extent1].[CustomerID] = 1 /* @EntityKeyValue1 */

returns four order records even though only one is needed

SELECT
[Extent1].[OrderItemID] AS [OrderItemID],
[Extent1].[ItemDescription] AS [ItemDescription],
[Extent1].[Price] AS [Price],
[Extent1].[OrderID] AS [OrderID]
FROM [dbo].[OrderItems] AS [Extent1]
WHERE [Extent1].[OrderID] = 1 /* @EntityKeyValue1 */

returns six order item records even though only one is needed

Here are the SQL calls explicit loading.

SELECT TOP (2)
[Extent1].[CustomerID] AS [CustomerID],
[Extent1].[Firstname] AS [Firstname],
[Extent1].[Lastname] AS [Lastname]
FROM [dbo].[Customers] AS [Extent1]
WHERE [Extent1].[CustomerID] = 2 /* @p0 */

returns just one customer

SELECT TOP (1)
[Extent1].[OrderID] AS [OrderID],
[Extent1].[OrderDate] AS [OrderDate],
[Extent1].[Comment] AS [Comment],
[Extent1].[CustomerID] AS [CustomerID]
FROM [dbo].[Orders] AS [Extent1]
WHERE [Extent1].[CustomerID] = 2 /* @EntityKeyValue1 */

returns just one order

SELECT TOP (1)
[Extent1].[OrderItemID] AS [OrderItemID],
[Extent1].[ItemDescription] AS [ItemDescription],
[Extent1].[Price] AS [Price],
[Extent1].[OrderID] AS [OrderID]
FROM [dbo].[OrderItems] AS [Extent1]
WHERE [Extent1].[OrderID] = 5 /* @EntityKeyValue1 */

returns just one order item

Summary of lazy loading vs explicit loading for order details page

TaskLazy Loaded RowsExplicit Loaded Rows
Retrieve customers11
Retrieve orders41
Retrieve order items61




Full Data

Customers table

CustomerIDFirstnameLastname
1Lazy SteveSmith
2JamesJones

Orders table

OrderIDOrderDateCommentCustomerID
18/6/2014 12:00:00 AM Steve's first order1
28/7/2014 12:00:00 AMSteve's second order1
38/8/2014 12:00:00 AMSteve's third order1
48/9/2014 12:00:00 AMSteve's fourth order1
58/7/2014 12:00:00 AMJames' first order2
68/8/2014 12:00:00 AMJames' second order2
78/9/2014 12:00:00 AMJames' third order2
88/10/2014 12:00:00 AMJames' fourth order2

Order Item table

OrderItemIDItemDescriptionPriceOrderID
1Ball31
2Watch321
3Book121
4Glasses411
5Pen41
6Chair231
7Laptop4002
8Mouse132
9Bottle12
10Stapler72
11Wires2.52
12Hose413
13Tiles224
14Table495
15Spoons1.995
16Forks2.995
17Cups55
18Plates145
19Knives85
20Bike3406
21Reflectors96
22Tool106
23Tube repair4.996
24Lights116
25Helmet276
26Mouse147
27Keyboard297
28Mouse148
29Keyboard298

Download the source code here.

Arguments model and action methods in ASP.NET MVC Part 2 – using Glimpse

In my previous post I discussed how values sent from the browser are bound to objects in the action methods of a controller.

If binding is not working as expected you need to examine the html element names and the types you are binding to, I showed how the FormCollection can be of help in this regard.

In this post I will show how to use Glimpse to examine how binding is occurring.

I should at this point say that I am one of the contributors to the Glimpse project.

Add the Glimpse Mvc 4 package to your project.

nuget

Start your application; in the browser open glimpse.axd from the root and turn glimpse on by clicking the Turn Glimpse On button.

request

Browse to the page where you want to see how binding is working.

In the example, edit employee 1, John Jones. Make some changes to the employee and add a comment to the reason for edit and save.

You’ll be brought back to the index page listing all employees.

At the bottom of the browser you should have a Glimpse bar showing some statistics about the page.

Open Glimpse fully by clicking the ‘g’ in the right corner and click History on the far right.

Here you will see all the recent requests, we are interested in the most recent POST.

requests

Click inspect on that request, the POST request http://localhost:55809/Employee/Edit?EmployeeID=1. The tabs along the top of Glimpse have been refreshed with data from that request.

Open the Model Binding tab to see how the values from your request have been bound to your types in the action method.

model_binding

Here you can see parameters to the action method, their type and and what they were bound to.

If you see a parameter that has “–” (two dashes) in the Value column, nothing was sent to the action method that could be bound to a parameter on the action method.

Now take a look at the Request tab and the form variables. Note how the keys of the form variables match the parameters in the model binding tab.

request

This is the easiest way I have found to understand how model binding works in MVC and fix problems.

Arguments model and action methods in ASP.NET MVC Part 1

Sending values from an MVC view to a controller works very well when you are binding back to the same model/viewmodel you populated the view with. But when you start trying to do something a little different, it’s not so obvious or straightforward.

The quick answer

The name attribute of the html element must match the argument sent to the action method.

Here are a few examples.

If the type sent to the action method is an Employee (which has strings for Fristname and Lastname) the html input elements should look like

	<input type="text" name="Firstname" value="" />
	<input type="text" name="Lastname" value="" />

If the type sent to the action method is an EmployeeViewModel (this has an Employee type inside, which has strings for Fristname and Lastname) the html input elements should look like

	<input type="text" name="Employee.Firstname" value="" />
	<input type="text" name="Employee.Lastname" value="" />

Note the name attributes are different from the previous example, but that they match the EmployeeViewModel.

That might be enough to solve your problem, if so you can get back to work, if not, read on.

The long answer

The following example is a bit contrived, and don’t use it as an example of how to code MVC models, or viewmodels, but it allows me to show a few ways of achieving some unusual model binding. Full source code is attached.
I’ve followed the standard MVC Index, Create, Edit and Delete approach that comes out of the box with Visual Studio 2012.

I have an Employee –

    public class Employee
    {
        public int EmployeeID { get; set; }
        public string Firstname { get; set; }
        public string Lastname { get; set; }
        public int RoleID { get; set; }
    }

and a Role –

    public class Role
    {
        public int RoleID { get; set; }
        public string Description { get; set; }
    }

For the purpose of this demo I’m using a list to store the employees and roles, you can see them in the FakeData class in the attached source.

The EmployeeViewModel is used to populate the Create and Edit views, it contains an Employee and the SelectList of Roles for the dropdownlist –

    public class EmployeeViewModel
    {
    ...snip...
        public Employee Employee { get; set; }
        public IEnumerable Roles { get; set; }
    ...snip...
    }

The Create View

The Create view follows the standard MVC approach, pass in the EmployeeViewModel, use LabelFor, EditorFor and DropDownListFor.

On the controller side, take the EmployeeViewModel as the argument to the POST Create action method. All the model binding “just works”. This is because the @Html.EditorFor has created html like the following –

<input class="text-box single-line" id="Employee_Firstname" type="text" name="Employee.Firstname" value="" />

Note the name="Employee.Firstname", this matches the EmployeeViewModel.Employee.Firstname, same behaviour applies to Lastname and RoldID.

We stuck with what MVC gave us and everything worked.

The Edit View

With the Edit view we’ll do something different, something you won’t normally do in this scenario, but I want to keep it simple from a code perspective.

The Edit view will take a the EmployeeViewModel to populate the controls, but the POST Edit action method will an EmployeeArgsModel

    public class EmployeeArgsModel
    {
        public int EmployeeID { get; set; }
        public string Firstname { get; set; }
        public string Lastname { get; set; }
        public int RoleID { get; set; }

        public string ReasonForEdit { get; set; }
    }

You’ll note that it has all the properties that the Employee has, and yes, I could have used an Employee instead, but I need to do it this way for demonstration purposes.
I’ve added a string property called ReasonForEdit, this is going to be textbox on the view.

In order for the POST method to get the right parameters and perform model binding the way we are expecting we need to change the way we write the Edit View from how we wrote the Create View.

Why use an arguments model

You could pass in the EmployeeID, Firstname, Lastname, RoleID and ReasonForEdit directly to the action method

    public ActionResult Edit(int employeeID, string firstname, string lastname, int roleID, string reasonForEdit)

But this will quickly become unwieldy. Many parameters would be needed for a search with filtering, sorting, and paging!
Creating a model that captures what you need in a much neater way.

You can combine the usage of an arguments model and simple arguments, there is an example of this in the source code.

The importance of the “name” attribute

For simplicity I’m going to say that you need to match the “name” attribute of your html to the public property on the model the controller takes as an argument. If the controller takes an EmployeeViewModel with an Employee inside it, then the “name”s of your html attributes should be prefixed with “Employee.” and the name of the property.

If you are having trouble working out what names your should be using in the view change your action method to something like –

public ActionResult Edit(FormCollection collectionOfValues)

Use the debugger to check the names of the values passed to the method in the collectionOfValues.

Comparison of Create and Edit views and action methods

The rest of this post deals with the attached source code, please have a look at it before reading on.

The Create view follows the normal MVC approach, the view takes a model and the POST action method takes the same model.

        [HttpPost]
        public ActionResult Create(EmployeeViewModel employeeViewModel)

The Edit view takes a different approach, the view takes the a EmployeeViewModel but the POST action method takes an EmployeeArgeModel.

        [HttpPost]
        public ActionResult Edit(EmployeeArgsModel employeeArgsModel)

Below compares the Razor code and html produced for the two views on a element by element basis, note how the “name” attributes differ.

Firstname

Create View

Razor : @Html.EditorFor(model => model.Employee.Firstname)
binds to EmployeeViewModel.Employee.Firstname property.
HTML : <input id="Employee_Firstname" type="text" value="" name="Employee.Firstname">

Edit View

Razor : @Html.Editor("Employee.Firstname","", "Firstname") 
shows the value in the Employee.Firstname of the Model sent to the view, and binds to Firstname (set in the third argument to Html.Editor) property in the argument to the action method.
HTML : <input id="Firstname" type="text" value="Dave" name="Firstname">

Lastname

Create View

Razor : @Html.EditorFor(model => model.Employee.Lastname) 
binds to EmployeeViewModel.Employee.Lasttname property.
HTML : <input type="text" value="" name="Employee.Lastname" id="Employee_Lastname">

Edit View

Razor : @Html.EditorFor(model => model.Employee.Lastname,"", "Lastname") 
shows the value in the Employee.Lastname of the Model sent to the view and binds to Lastname (set in the third argument to Html.Editor) property in the argument to the action method.
HTML : <input type="text" value="Jones" name="Lastname" id="Lastname">

ReasonForEdit

Edit view

Razor : @Html.TextBox("ReasonForEdit", null)
binds to the ReasonForEdit property in the argument to the action method
HTML : <input type="text" value="" name="ReasonForEdit" id="ReasonForEdit">

Role ID

Create View

Razor : @Html.DropDownListFor(model => model.Employee.RoleID, Model.Roles, "--Select a role --" ) 
binds to EmployeeViewModel.Employee.RoleID property in the argument to the action method.
HTML :

<select name="Employee.RoleID" id="Employee_RoleID" data-val-required="The RoleID field is required." data-val-number="The field RoleID must be a number." data-val="true">
   <option value="">--Select a role --</option>
   <option value="1">Junior Engineer</option>
   <option value="2">Senior Engineer</option>
   <option value="3">Lead Engineer</option>
</select>

Edit View

Razor : @Html.DropDownListFor(model => model.Employee.RoleID, Model.Roles, "--Select a role --", new { Name = "RoleID"} )
binds to the RoleID property in the argument to the action method
HTML :

<select id="Employee_RoleID" data-val-required="The RoleID field is required." data-val-number="The field RoleID must be a number." data-val="true" name="RoleID">
    <option value="">--Select a role --</option>
    <option value="1" selected="selected">Junior Engineer</option>
    <option value="2">Senior Engineer</option>
    <option value="3">Lead Engineer</option>
</select>

Summary

The html elements must be named to match the arguments your action method takes.
If this explanation doesn’t make it clear, I hope the source code will.

ASP.MVC and Web Forms in one web application

I was recently asked to add an ASP.NET MVC 4 application to an existing Web Forms site. The ideal solution was to keep the code bases separate and the apps on a common domain.

But I wasn’t able to achieve this in a way that would satisfy both requirements and produce simple, easy to understand code without changing any of the standard configurations for both apps. There is a post by Scott Hanselman on this topic, but it is from 2011 and requires significant tinkering with the MVC application. I gave it a go, but kept hitting issues with missing dlls, or web.config errors. Unlikely to work without grief, especially with the next release of MVC.

I had to compromise on something. The first option was to combine the two applications into one. Most likely I would create a new MVC 4 app and add the web forms application to it. But this was going to be a hodge-podge of old and new technologies, code and libraries many dating back to .NET 2.0. It would have ruined one of the goals for developing a new app, to move away from legacy code that is becoming harder and harder to maintain.

The second option was to put the apps on two subdomains. This approach seems simple, use a common cookie for both applications and you’ll be logged in to both. I tried this and all worked well. However, there was one snag; the old web forms application makes extensive use of the session and the session would expire if the user spent most of their time on the MVC application without occasionally visiting the web forms app. Their cookie would still be valid, but the data in session would be gone and exceptions would fly!

I came up a quick and dirty solution to keep the lights on, I don’t claim this to be ideal and will work on finding something better. I added global action filter to “ping” a tiny page on the web forms app every time the user loaded an MVC page. It works for now, and I’ll try to find a more elegant solution.