Solucionado (ver solução)
Solucionado
(ver solução)
8
respostas

System.NullReferenceException // contextAcessor was null

Nesta parte das aulas quando tento adicionar um produto ao carrinho ele passa que contextAcessor "está vazio"?! exatamente no método (?!) GetPedidoId

 public int? GetPedidoId()
        {
            return contextAcessor.HttpContext.Session.GetInt32("pedidoId");
}

código completo do PedidoRepository.cs

using System;
using System.Linq;
using CasaDoCodigo.Models;
using Microsoft.AspNetCore.Http;
using Microsoft.EntityFrameworkCore;
namespace CasaDoCodigo.Repositories
{
    public interface IPedidoRepository
    {
        Pedido GetPedido();
        void AddItem(string codigo);
    }
    public class PedidoRepository : BaseRepository<Pedido>, IPedidoRepository
    {
        private readonly IHttpContextAccessor contextAcessor;
        public PedidoRepository(ApplicationContext contexto, IHttpContextAccessor contextAccessor) : base(contexto)
        {
            this.contextAcessor = contextAcessor;
        }

        public void AddItem(string codigo)
        {
            var produto = contexto.Set<Produto>()
                            .Where(p => p.Codigo == codigo)
                            .SingleOrDefault();
            if (produto == null) 
            {

                throw new ArgumentException("Produto não encontrado");

            }

            var pedido = GetPedido();

            var itemPedido = contexto.Set<ItemPedido>()
                                .Where(i => i.Produto.Codigo == codigo
                                    && i.Pedido.Id == pedido.Id)
                                .SingleOrDefault();
            if (itemPedido == null)
            {
                itemPedido = new ItemPedido(pedido, produto, 1, produto.Preco);
                contexto.Set<ItemPedido>()
                    .Add(itemPedido);

                contexto.SaveChanges();

            }
        }

        public Pedido GetPedido()
        {
            var pedidoId = GetPedidoId();
            var pedido = dbSet
                .Include(p => p.Itens)
                    .ThenInclude(i => i.Produto)
                .Where(p => p.Id == pedidoId)
                .SingleOrDefault();

            if (pedido == null) 
            {
                pedido = new Pedido();
                dbSet.Add(pedido);
                contexto.SaveChanges();
                SetPedidoId(pedido.Id);
            }
            return pedido;
        }

        public int? GetPedidoId()
        {
            return contextAcessor.HttpContext.Session.GetInt32("pedidoId");
        }
        private void SetPedidoId(int pedidoId)
        {
            contextAcessor.HttpContext.Session.SetInt32("pedidoId", pedidoId);
        }
    }
}

Se alguém puder me explicar/mostrar o que fiz de errado?! =P

8 respostas

está faltando algum código para ajudar a elucidar o problema?! se precisar posto as outras classes ^^''

Oi Victor, tudo bem?

Por favor, insira esta linha na sua classe Startup:

public void ConfigureServices(IServiceCollection services)
{
.
.
.

    services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
.
.
.
}

Isso fará a injeção de dependência do parâmetro do tipo IHttpContextAccessor, assim evitando que o parâmetro contextAcessor fique nulo.

Opa Marcelo, obrigado pela ajuda, contudo mesmo adicionando a linha, o erro ainda persiste segue Startup.cs completo:

using System;
using CasaDoCodigo.Repositories;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
namespace CasaDoCodigo
{
    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.AddMvc();
            services.AddDistributedMemoryCache();
            services.AddSession();

            string connectionString = Configuration.GetConnectionString("Default");

            services.AddDbContext<ApplicationContext>(options => options.UseSqlServer(connectionString));

            services.AddTransient<IDataService, DataService>();
            services.AddTransient<IProdutoRepository, ProdutoRepository>();
            services.AddTransient<IPedidoRepository, PedidoRepository>();
            services.AddTransient<ICadastroRepository, CadastroRepository>();
            services.AddTransient<IItemPedidoRepository, ItemPedidoRepository>();
            services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();

        }


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

            app.UseStaticFiles();
            app.UseSession();

            app.UseMvc(routes =>
            {
                routes.MapRoute(
                    name: "default",
                    template: "{controller=Pedido}/{action=Carrossel}/{codigo?}");
            });

            serviceProvider.GetService<IDataService>().InicializaDB();



        }
    }
}

contextAcessor continua retornando como nulo =/ Estou meio perdido já ^^''

Oi Victor, você pode zipar o código do projeto todo e me mandar? Pode usar o e-mail marcelo.oliveira@alura.com.br. Obrigado!

Claro, obrigado pela disponibilidade.

solução!

Oi Victor

O problema era que você estava atribuindo o campo a ele mesmo, e não o parâmetro ao campo. Isso acontece porque você está usando dois nomes diferentes: contextAcessor e contextAccessor (com dois "c"s)

private readonly IHttpContextAccessor contextAcessor;
public PedidoRepository(ApplicationContext contexto, IHttpContextAccessor contextAccessor) : base(contexto)
{
    this.contextAcessor = contextAcessor;
}

Altere o trecho acima para:

        private readonly IHttpContextAccessor contextAccessor;
        public PedidoRepository(ApplicationContext contexto, IHttpContextAccessor contextAccessor) : base(contexto)
        {
            this.contextAccessor = contextAccessor;
        }

Obrigadão Marcelo pela paciência e disponibilidade. Pra variar typos, tenho que tomar mais cuidados.

Excelente, Victor, todo mundo já passou por isso (eu ainda passo, de vez em quando :-)

Fico feliz por ter ajudado. Obrigado por participar do fórum!