-1

I'm encountering an issue with my API where I receive the error

Object reference not set to an instance of an object

when hitting the API multiple times. The API works fine the first time, but fails with this error subsequently. Here's the relevant code and configuration:

Controller (MenuController):

namespace SignIn2.Controllers
{
    public class MenuController : ApiController
    {
        private readonly IMenuRepository menuRepository;

        public MenuController()
        {
        }

        public MenuController(IMenuRepository menuRepository)
        {
            if (menuRepository == null)
            {
                throw new ArgumentNullException(nameof(menuRepository));
            }

            this.menuRepository = menuRepository;
        }

        [HttpGet]
        [Route("api/menu")]
        public IHttpActionResult GetMenuData([FromBody] JObject data)
        {
            try
            {
                int roleId = data["role_id"].ToObject<int>();
                var menuData = menuRepository.GetMenuData(roleId);

                var menuResponse = new MenuResponse
                {
                    MessageCode = "200",
                    MessageName = "Menu fetch successfully",
                    Data = menuData
                };

                return Ok(menuResponse);
            }
            catch (Exception ex)
            {
                // Log the exception details
                System.Diagnostics.Debug.WriteLine($"Exception in GetMenuData: {ex.Message}");
                return InternalServerError(ex); // Return an appropriate response to the client
            }   
        }
    }
}

Repository (MenuRepository):

namespace SignIn2.Data
{
    public interface IMenuRepository
    {
        List<Datum> GetMenuData(int roleId);
    }
}

Repository implementation:

namespace SignIn2.Data
{
    public class MenuRepository : IMenuRepository
    {
        private readonly SignInDbContext dbContext;

        public MenuRepository(SignInDbContext dbContext)
        {
            this.dbContext = dbContext;
        }

        public List<Datum> GetMenuData(int roleId)
        {
            var accessibleProjects = GetUserProjects(roleId);
            var allProjects = dbContext.lu_project.ToList();
            var allMenus = dbContext.lu_menu.ToList();

            var projects = allProjects
                .Where(p => accessibleProjects.Contains(p.project_id) && p.fk_status_id == 1)
                .Select(p => new Datum
                {
                    ProjectName = p.project_name,
                    ProjectIcon = p.icon,
                    Menu = BuildMenuTree(allMenus, p.project_id)
                })
                .ToList();

            return projects;
        }

        private List<int> GetUserProjects(int roleId)
        {
            // some logics
            return projectIds;
        }

        private List<Menu> BuildMenuTree(List<lu_menu> allMenus, int projectId, int? parentMenuId = null)
        {
            return allMenus
            // logic for get menu
        }

        private List<SubMenu> BuildSubMenuTree(List<lu_menu> allMenus, int projectId, int parentMenuId)
        {
            return allMenus
            //    Logic for get sub menu
        }
    }
}

Database context SignInDbContext:

namespace SignIn2.Data
{
    public class SignInDbContext : DbContext
    {
        public DbSet<lu_project> lu_project { get; set; }
        public DbSet<lu_menu> lu_menu { get; set; }
        public DbSet<map_role_menu> map_role_menu { get; set; }

        public SignInDbContext() : base("name=SignInDbContext")
        {
            this.Database.Log = s => System.Diagnostics.Debug.WriteLine(s);
        }        
    }
}

Unity resolver (UnityResolver):

namespace SignIn2.DependencyResolution
{
    public class UnityResolver : IDependencyResolver
    {
        private readonly IUnityContainer container;

        public UnityResolver(IUnityContainer container)
        {
            this.container = container;
        }

        public object GetService(Type serviceType)
        {
            try
            {
                var service = container.Resolve(serviceType);

                if (service == null)
                {
                    // Log the serviceType that couldn't be resolved
                    System.Diagnostics.Debug.WriteLine($"Failed to resolve service: {serviceType.FullName}");
                }

                return service;
            }
            catch (Exception ex)
            {
                // Log the exception
                System.Diagnostics.Debug.WriteLine($"Exception while resolving service: {ex.Message}");
                System.Diagnostics.Debug.WriteLine($"Service Type: {serviceType.FullName}");
                System.Diagnostics.Debug.WriteLine($"Exception Stack Trace: {ex.StackTrace}");
                return null;
            }
        }

        public IEnumerable<object> GetServices(Type serviceType)
        {
            try
            {
                var services = container.ResolveAll(serviceType);

                if (services == null || !services.Any())
                {
                    // Log the serviceType that couldn't be resolved
                    System.Diagnostics.Debug.WriteLine($"Failed to resolve services: {serviceType.FullName}");
                }

                return services;
            }
            catch (Exception ex)
            {
                // Log the exception
                System.Diagnostics.Debug.WriteLine($"Exception while resolving services: {ex.Message}");
                return new List<object>();
            }
        }

        public IDependencyScope BeginScope()
        {
            return this;
        }

        public void Dispose()
        {
            container.Dispose();
        }
    }
}

Application startup:

namespace SignIn2
{
    public class WebApiApplication : System.Web.HttpApplication
    {
        protected void Application_Start()
        {
            GlobalConfiguration.Configure(WebApiConfig.Register);

            // Create a Unity container
            var container = new UnityContainer();

            // Register the dependencies
            container.RegisterType<SignInDbContext>(new HierarchicalLifetimeManager());
   
            container.RegisterType<IUserRepository, UserRepository>();
            container.RegisterType<IroleRepository, RoleRepository>();        
            container.RegisterType<IMenuRepository, MenuRepository>();

            // Get the HttpConfiguration instance from GlobalConfiguration
            HttpConfiguration config = GlobalConfiguration.Configuration;
            
            config.DependencyResolver = new UnityResolver(container);
        }
    }
}

Issue details: I have a controller that communicates with a repository to fetch menu data based on a role.

The error occurs on subsequent API calls, but the first call works fine. The issue seems related to the GetMenuData method in MenuController.

The error suggests that an object reference is not initialized properly.

What I've tried:

  • I have checked for null references and ensured that the data parameter in the GetMenuData method is not null.

  • I have verified that the menuRepository is being initialized correctly in the controller constructor.

  • I have examined the GetMenuData method in the repository, but I'm unable to identify the source of the error.

Questions

Could the issue be related to the Unity container configuration?

Are there any common pitfalls in ASP.NET Web API that might lead to this error?

Could the error be caused by a race condition or concurrency issue?

Are there any additional log outputs or error stack traces that might provide more insight?

Environment

  • ASP.NET Web API
  • Entity Framework
  • Unity IoC Container

Please provide suggestions on how to solve this issue.

Note: I did not mention some repository that is not related to this API

  • The full, classic, legacy **ASP.NET** (Windows only), or ASP.NET **Core** ?? You've tagged both - but not mentioned "Core" at all in your question.... those are very similar - but not the same - we need to know **which one** you're using .... – marc_s Aug 12 '23 at 07:13
  • Which particular line throws? – Wiktor Zychla Aug 12 '23 at 07:29
  • in controller -: var menuData = menuRepository.GetMenuData(roleId); after this line code go to catch but roleId is passing properly like 1st attempt. – Vikas Patel Aug 12 '23 at 07:33
  • My guess is the `HierarchicalLifetimeManager` doesn't work here. Try to register the db context without any lifetime managers (`container.RegisterType();`). – Wiktor Zychla Aug 13 '23 at 12:13
  • Thanks for help, I got solution i was not disposing in repository public void Dispose() { GC.SuppressFinalize(this); throw new NotImplementedException(); } after use this it is working fine.... – Vikas Patel Aug 16 '23 at 05:32

0 Answers0