ObjectDisposedException: Cannot access a disposed object

I am working on this application using In-Memory Cache feature in Asp.Net Core and got this error below.
I have dealt with this error multiple times before and it can be hard to debug sometimes because the cause could be different every time. In this one, I was caching some data that way I did not have to keep going to the database every request. To keep this short, I am going to show the piece of code that was causing the issue below.

Problem

As you can see the category object in code below was an IEnumerable type.


viewModelInfo.Categories = _repository.GetAllCategories().Where(x => x.Businesses.Count > 0).Select(x => new SelectListItem
{
Value = x.Name.ToString(),
Text = x.Name
});

“ObjectDisposedException: Cannot access a disposed object. A common cause of this error is disposing a context that was resolved from dependency injection and then later trying to use the same context instance elsewhere in your application. This may occur if you are calling Dispose() on the context, or wrapping the context in a using statement. If you are using dependency injection, you should let the dependency injection container take care of disposing context instances.
Object name: ‘ApplicationDbContext’.”

Solution

Because of lazy-loading here, the query is not fully executed on the linq statement line. Therefore, adding .ToList() will force it to loop through and generate the category list needed.

Just as the error stated, I verify the ApplicationDbContext making sure Dispose() is not being called in there. Then, I place some breakpoints in the action in the controller and step through until I found the cause of my issue. Below is the final piece of code with the fix.


viewModelInfo.Categories = _repository.GetAllCategories().Where(x => x.Businesses.Count > 0).Select(x => new SelectListItem
{
Value = x.Name.ToString(),
Text = x.Name
}).ToList();

Disable A Specific User in ASP.NET Core Identity 2.0

I am writing this post simply to document a used case I had a few days ago. I basically wanted to disable a user instead of deleting the meta data from the system.
Since the project was built with regular ASP.Net Core Identity, It didn’t take too long for me to figure this out.

What’s ASP.Net Core Identity?

It is a simple membership system that add login capability to any asp.net Core applications. ASP.Net Core Identity supports external login providers such as Facebook, Twitter, Microsoft, and Google.
In case you would like to learn more about it, feel free to read this post on identity.

Implementation In ASP.NET Core Identity 2.0

I had to add a new property called “IsActive” as shown in the code snippet below to the “ApplicationUser.cs” class to disable the user in the system.

namespace UserApp.Models
{
 //Add profile data for application users by adding properties to the ApplicationUser class
    public class ApplicationUser : IdentityUser
    {
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public bool IsActive { get; set; }
    }
}

Next, I run migration to add the new column to the AspNetUsers table.

Now that I have the new column added to the table, I need to set the IsActive flag during registration.

Where do you update the IsActive flag by default?
Find the action method called RegisterAsync in the “AccountController.cs” and

 public async Task RegisterAsync(RegisterViewModel model, string returnUrl = null)
 {
   ViewData["ReturnUrl"] = returnUrl;
   if (ModelState.IsValid)
   {
        var user = new ApplicationUser
        {
                    FirstName = model.FirstName,
                    LastName = model.LastName,
                    IsActive = true
         };
         var result = await _userManager.CreateAsync(user, model.Password);
         if (result.Succeeded)
         {
           _logger.LogInformation("User created a new account with password.");

            var code = await _userManager.GenerateEmailConfirmationTokenAsync(user);
            var callbackUrl = Url.EmailConfirmationLink(user.Id, code, Request.Scheme);
            await _emailSender.SendEmailConfirmationAsync(model.Email, callbackUrl);
            logger.LogInformation("User created a new account with password.");
            return RedirectToAction(nameof(ConfirmRegistration));
         }
         AddErrors(result);
     }

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

Finally, after running the application and register a brand new user I was able to verify the data in the database. In case you need already have some existing users, you’ll simply need to run an update query to set their flag to active. That’s it!!!

How To Use In-Memory Cache In An ASP.NET Core Web API

Before we can dive into the In-Memory Cache implementation, first, What is caching and when you should consider using it?

Well, caching is basically a technique of storing frequently used data in a temporary storage. Caching can significantly improve the performance and scalability of any application by reducing the time and resources required to load fresh contents. Using that technique will definitely make the end user much happier to use the app.

Types of Caching supported by ASP.Net Core

As you might already know ASP.NET Core supports different types of caching such as In-Memory Cache, Distributed Cache and Response Cache. However, in this post I will take the opportunity to introduce you to how to use In-Memory Cache in an ASP.Net Core Web API app.

How data is stored

When using the In-Memory Cache feature, the data is stored in the memory of Web Server where a web application is being hosted at. It’s good to remember that an application can be hosted on single Server or multiple Servers in a Server Farm. For those of you that have a single server, you should be just fine using In-Memory Cache with no issues because it doesn’t require much to get running, however, if those running on multiple servers on a server farm MUST ensure that the sessions are sticky.

Setting cache expiration time

When adding an item to the cache you set an expiration, this can be an absolute time, a sliding window or the combination of both. Choosing which one to use depends on your scenario.

Example of how to implement In-Memory Cache

To keep thing simple and easy to follow I am going to implement a quick sample API to retrieve the states name using state abbreviation as code. In order to get start simple create a new blank WEB API project in Visual Studio and follow the steps below to fill in the required pieces or you can download the full sample code from github here.

Injecting the dependency from the startup.cs.

    public void ConfigureServices(IServiceCollection services)
    {
      services.AddMemoryCache();
      services.AddMvc();
    }

Now that the In-Memory Cache service has been added, I can access the cache from inside the controllers by simply injecting an IMemoryCache parameter in the constructors.

    private readonly IMemoryCache _cache;

    public StatesController(IMemoryCache memoryCache)
    {
      _cache = memoryCache;
    }

Get Method setup

Next, I need to set my cache inside the get action method which is used to get the name of the state that matches the search criteria.

   [HttpGet("{stateCode}")]
   public async Task Get(string stateCode)
   {
      string state = string.Empty;
      if (!_cache.TryGetValue("CashedStatesList", out Dictionary states))
      {
       Console.WriteLine("Loading from database or json file into cache");

        states =
           JsonConvert.DeserializeObject>(
           await System.IO.File.ReadAllTextAsync("StatesList.json"));

        MemoryCacheEntryOptions options = new MemoryCacheEntryOptions
        {
         AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(300), // cache will expire in 300 seconds or 5 minutes
         SlidingExpiration = TimeSpan.FromSeconds(60) // cache will expire if inactive for 60 seconds
        };

        if (states != null)
        _cache.Set("CashedStatesList", states, options);
      }
      else
      {
         Console.WriteLine("***Data Found in Cache...***");
      }

      if (states != null)
      {
         state = states.GetValueOrDefault(stateCode);

         if (string.IsNullOrEmpty(state))
         {
           state = "Not found, please try again.";
         }

      }

      if (string.IsNullOrEmpty(state))
      {
         return NoContent();
      }
      return Ok(state);
  }

Reading from data source

In the code snippet above as you can see the very first if condition is checking against the cache dictionary object to load the states list if exist, otherwise, it will continue and load the states from the json file. To be clear here’s the snippet of code that reads the json file and load the states list.

  states =
           JsonConvert.DeserializeObject>(
           await System.IO.File.ReadAllTextAsync("StatesList.json"));

Set cache expiration

Then, once the data was cached, I set some times to when it will expire which is 5 minutes and if no activity they will expire in 60 seconds. You can set these values according to your requirements.

   MemoryCacheEntryOptions options = new MemoryCacheEntryOptions
   {
     AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(300), // cache will expire in 300 seconds or 5 minutes
     SlidingExpiration = TimeSpan.FromSeconds(60) // cache will expire if inactive for 60 seconds
   };

Then, if you continue reading the code above you will notice where the cache is being set as expected.
Last, as you can see from this simple example, the In-Memory cache is can be very beneficial when hosting an application on a single Server. It stores data on Server and improves application performance. Don’t forget to test your app to not depend solely on cached data.
In case you would like to read more about In-Memory cache, please visit these links below.
Cache in-memory in ASP.NET Core

Quick and Easy Way To Set Authorization Header of HttpClient

Earlier today I was working on this application which requires me to make a few calls to a REST API to get some products back in XML format. In order to accomplish this task, I have instantiated an HttpClient object which to make the call. However, I was getting this security error below saying “Required OAuth credentials not provided”.

 

  900902
  Missing Credentials
  Required OAuth credentials not provided

Solution

Of course the error message is self explanatory, I was missing the authorization token in the header.

string url = "https://api.web.com/search/1.0" + ";
using (var client = new HttpClient())
{
  client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/xml"));
  client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", "my_authorization_token"); ;
  HttpResponseMessage response = client.GetAsync(new System.Uri(url)).Result;
  string responseBody = response.Content.ReadAsStringAsync().Result;
}

Build a Web API with ASP.NET Core

Recently I was tasked to put a simple WEB API together to manage a list of country capitals, so I decided to put this post together as a walk-through on how I did it.

What is a Web API?

ASP.Net Web API is a framework used to build HTTP services. By using HTTP this makes it easy to access WEB API across the internet, pretty much any platform or devices can can consumed WEB API with no problem.

In order to facilitate the client communication ASP.NET WEB API provides support for the following HTTP resources, such as GET, PUT, POST, DELETE verbs. In case you would like a more thorough explanation you can follow the tutorial from Microsoft here.

What WEB API I will be building?

This a WEB API will be use to manage country capitals information. It will be able to store, update, find and delete countries.

First create an ASP.NET Core project and name it “Countries”.
Create ASP.NET WEB API project

Once done simply build and run the app (CTRL+F5 to launch the app) and should see the same result page below.

Example: http://localhost:port/api/values

["value1","value2"]

Now that we have the foundation and know it’s working, let’s add the country model to the project.

Add the following Model for country:

namespace Countries.Models
{
public class Country
{
public long Id { get; set; }
public string Name { get; set; }
public string Capital { get; set; }
}
}

Add Database context

The database context is the main class that coordinates Entity Framework functionality for a given data model. This class is created by deriving from the Microsoft.EntityFrameworkCore.DbContext class.


using Microsoft.EntityFrameworkCore;

namespace Countries.Models
{
public class CountryContext:DbContext
{
public CountryContext(DbContextOptions options): base(options)
{
}

public DbSet Countries { get; set; }
}
}

Register Database Context

Next, Register the DbContext via dependency injection (DI) container in order to make it available for use in the controller. ASP.NET core makes it easier since it provides built-in support for dependency injection.
Also, one of the great feature with ASP.NET Core I’ll use here is the “UseInMemoryDatabase” which will create or use a database with the name specified.

Let’s update the startup class with the following snippet.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Countries.Models;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;

namespace Countries
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}

public IConfiguration Configuration { get; }

// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext(opt => opt.UseInMemoryDatabase("Countries"));
services.AddMvc();
}

// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}

app.UseMvc();
}
}
}

Next, let’s add the controller to put the methods such as the GET, PUT, POST, and DELETE. Let’s use this option to scaffold the different method for the country model.
Adding a controller to the WEB API
Controller creation
As you can see in the controller constructor, it uses dependency injection to inject the DbContext CountryContext into the controller which makes it available to all the methods inside that controller.


using Countries.Models;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace Countries.Controllers
{
[Produces("application/json")]
[Route("api/Countries")]
public class CountriesController : Controller
{
private readonly CountryContext _context;

public CountriesController(CountryContext context)
{
_context = context;
}

// GET: api/Countries
[HttpGet]
public IEnumerable GetCountries()
{
return _context.Countries;
}

// GET: api/Countries/5
[HttpGet("{id}")]
public async Task GetCountry([FromRoute] long id)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}

var country = await _context.Countries.SingleOrDefaultAsync(m => m.Id == id);

if (country == null)
{
return NotFound();
}

return Ok(country);
}

// PUT: api/Countries/5
[HttpPut("{id}")]
public async Task PutCountry([FromRoute] long id, [FromBody] Country country)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}

if (id != country.Id)
{
return BadRequest();
}

_context.Entry(country).State = EntityState.Modified;

try
{
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!CountryExists(id))
{
return NotFound();
}
else
{
throw;
}
}

return NoContent();
}

// POST: api/Countries
[HttpPost]
public async Task PostCountry([FromBody] Country country)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}

_context.Countries.Add(country);
await _context.SaveChangesAsync();

return CreatedAtAction("GetCountry", new { id = country.Id }, country);
}

// DELETE: api/Countries/5
[HttpDelete("{id}")]
public async Task DeleteCountry([FromRoute] long id)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}

var country = await _context.Countries.SingleOrDefaultAsync(m => m.Id == id);
if (country == null)
{
return NotFound();
}

_context.Countries.Remove(country);
await _context.SaveChangesAsync();

return Ok(country);
}

private bool CountryExists(long id)
{
return _context.Countries.Any(e => e.Id == id);
}
}
}