14

I use TempData in some of my Views/Actions but I'd like to extract that into some class. The problem is if I try to create my class in Controller's constructor, the TempDate there is null. Better yet, I'd like to have my class to be injectable into Controller. So I need to get access to TempData when my class is created.

So how can this TempData be constructed in a separate class?

This is ASP.NET Core 2.0 web app.

1 Answer 1

21

You can access temp data anywhere by simply injecting ITempDataDictionaryFactory where you need it. You can then call its GetTempData which returns an ITempDataDictionary which you can use to access (read or write) the temp data for the current HTTP context:

public class ExampleService
{
    private readonly IHttpContextAccessor _httpContextAccessor;
    private readonly ITempDataDictionaryFactory _tempDataDictionaryFactory;

    public ExampleService(IHttpContextAccessor httpContextAccessor, ITempDataDictionaryFactory tempDataDictionaryFactory)
    {
        _httpContextAccessor = httpContextAccessor;
        _tempDataDictionaryFactory = tempDataDictionaryFactory;
    }

    public void DoSomething()
    {
        var httpContext = _httpContextAccessor.HttpContext;
        var tempData = _tempDataDictionaryFactory.GetTempData(httpContext);

        // use tempData as usual
        tempData["Foo"] = "Bar";
    }
}

Btw. the reason why TempData is null in your controller’s constructor is because the controller context is only injected after the controller has already been created (using property injection). So when the controller’s constructor runs, there simply isn’t any information about the current request yet.

If you do inject your service though, and that service works like the ExampleService above, then it will work even from within the constructor, since it will simply request the necessary information from the DI container itself (the factory and the HTTP context).

Sign up to request clarification or add additional context in comments.

3 Comments

Or you could even do this by injecting only IHttpContextAccessor: ``` public SetMessageOnBrowse(IHttpContextAccessor contextAccessor) { if (contextAccessor == null) throw new ArgumentNullException(nameof(contextAccessor)); var httpContext = contextAccessor.HttpContext; var factory = httpContext.RequestServices.GetService( typeof(ITempDataDictionaryFactory)) as ITempDataDictionaryFactory; _tempData = factory.GetTempData(httpContext); } ```
Retrieving services through context.RequestServices.GetService() is not dependency injection though but is the service locator pattern. There is really no good reason to use this when you are getting services injected anyway. Please avoid using service locator at all costs in ASP.NET Core; there are really only a handful of situation when that’s the only solution (and usually it’s limited to very internal framework stuff).
@poke For those who see the answer and wonder where the HttpContextAccessor comes from, you need to add it in the Startup.cs file in the ConfigureServices method: services.AddHttpContextAccessor();. Then you put it in your controller constructor to inject it into the controller or into your service in its constructor. As far as DI vs service locator patterns and "edge" cases. I find using completely stateless client and microservice is a good place to use this as it keeps up with TempData and out of the program logic.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.