notExactlyAHero
notExactlyAHero

Reputation: 353

How to use dependency injection in ASP.NET Core 2.0 for IHttpcontextAccessor

I want to set up a service to inject the current HttpContext in a class in my project so it can manage cookies.

I set up the service like this in my Startup.cs class:

public void ConfigureServices(IServiceCollection services)
{
    services.AddHttpContextAccessor();
    services.TryAddSingleton<IActionContextAccessor, ActionContextAccessor>();
    services.AddMvc();
}

How do I use this service in a C# class?

My attempt was like this:

My class to manipulate cookies, I want to inject the current HttpContext.

using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Session;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace grupoveiculos.Infraestrutura.Session
{
    public class Cookie
    {
        private readonly IHttpContextAccessor _accessor;

        public Cookie(IHttpContextAccessor accessor)
        {
            _accessor = accessor;
        }

        public void Set(string chave, string valor, int? dataExpiracao)
        {
            CookieOptions option = new CookieOptions();

            if (dataExpiracao.HasValue)
                option.Expires = DateTime.Now.AddMinutes(dataExpiracao.Value);
            else
                option.Expires = DateTime.Now.AddMilliseconds(10);

            _accessor.HttpContext.Response.Cookies.Append(chave, valor, option);
        }
    }
}

But when I try to instantiate my Cookie class inside the controller, it says that "there's no argument that corresponds to the required formal parameter accessor". The error is very logical, it is expecting the constructor parameter. But I expected IHttpContextAccessor being injected instead of me having to provide a parameter.

In my controller I tried:

[HttpGet]
[Route("SelecionarIdioma")]
public IActionResult SelecionarIdioma(string cultura)
{
    Cookie cookie = new Cookie(); // expecting the accessor parameter
    cookie.Set("idioma", cultura, 60);

    return RedirectToAction("Index", "Grupo");
}

Upvotes: 1

Views: 1870

Answers (3)

Nkosi
Nkosi

Reputation: 247088

This appears to be an XY problem.

There is really no need to access the IHttpContextAccessor just to access the response when you already have access to it within the controller action

You can create an extension method to simplify things

public static void AddCookie(this HttpResponse response, string chave, string valor, int? dataExpiracao) {
    CookieOptions option = new CookieOptions();

    if (dataExpiracao.HasValue)
        option.Expires = DateTime.Now.AddMinutes(dataExpiracao.Value);
    else
        option.Expires = DateTime.Now.AddMilliseconds(10);

    response.Cookies.Append(chave, valor, option);
}

and call it from the controller action.

[HttpGet]
[Route("SelecionarIdioma")]
public IActionResult SelecionarIdioma(string cultura) {
    Response.AddCookie("idioma", cultura, 60); //<-- extension method.    
    return RedirectToAction("Index", "Grupo");
}

Upvotes: 4

Kyle B
Kyle B

Reputation: 2889

There are a few different ways to do this, when you want a class to be able to use dependency injection it needs to be registered, however I believe all the controllers should be registered automatically in an MVC app.

Try injecting it into the controller instead of the Cookie directly.

public class MyController : Controller 
{
    private IHttpContextAccessor _accessor;

    public MyController(IHttpContextAccessor accessor)
    {
        _accessor = accessor;
    }

    [HttpGet]
    [Route("SelecionarIdioma")]
    public IActionResult SelecionarIdioma(string cultura)
    {
        Cookie cookie = new Cookie(_accessor);
    }
}

Upvotes: 1

Ricardo Peres
Ricardo Peres

Reputation: 14535

Try this:

var cookie = new Cookie(this.HttpContext.RequestServices.GetService<IHttpContextAccessor>());

Another way would be to register the Cookie class itself and then inject it on the constructor.

Upvotes: -1

Related Questions