Как получить доступ к TempData в моем собственном служебном классе? Или TempData имеет значение null в конструкторе

Я использую TempData в некоторых своих представлениях/действиях, но я хотел бы извлечь это в какой-то класс. Проблема в том, что если я попытаюсь создать свой класс в конструкторе контроллера, TempDate будет нулевым. Еще лучше, я бы хотел, чтобы мой класс можно было вводить в контроллер. Поэтому мне нужно получить доступ к TempData при создании моего класса.

Так как же можно создать этот TempData в отдельном классе?

Это веб-приложение ASP.NET Core 2.0.


person alvipeo    schedule 11.09.2017    source источник


Ответы (1)


Вы можете получить доступ к временным данным в любом месте, просто внедрив ITempDataDictionaryFactory там, где вам это нужно. Затем вы можете вызвать его GetTempData< /a>, который возвращает ITempDataDictionary, который вы можете использовать для доступа (чтения или записи) к временным данным для текущего контекста HTTP:

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";
    }
}

Кстати. причина, по которой TempData является null в конструкторе вашего контроллера, заключается в том, что контекст контроллера вводится только после того, как контроллер уже создан (с использованием внедрения свойств). Поэтому, когда запускается конструктор контроллера, информации о текущем запросе просто еще нет.

Однако если вы внедрите свой сервис, и этот сервис работает как ExampleService выше, то он будет работать даже внутри конструктора, поскольку он просто запросит необходимую информацию из самого контейнера DI (фабрики и контекста HTTP).

person poke    schedule 11.09.2017
comment
Или вы даже можете сделать это, внедрив только IHttpContextAccessor: ``` public SetMessageOnBrowse(IHttpContextAccessor contextAccessor) { if (contextAccessor == null) throw new ArgumentNullException(nameof(contextAccessor)); вар httpContext = contextAccessor.HttpContext; var factory = httpContext.RequestServices.GetService(typeof(ITempDataDictionaryFactory)) as ITempDataDictionaryFactory; _tempData = factory.GetTempData(httpContext); } ``` - person alvipeo; 12.09.2017
comment
Получение сервисов через context.RequestServices.GetService() не является внедрением зависимостей, а представляет собой шаблон поиска сервисов. На самом деле нет веской причины использовать это, когда вы все равно получаете услуги. Пожалуйста, любой ценой избегайте использования локатора сервисов в ASP.NET Core; на самом деле существует всего несколько ситуаций, когда это единственное решение (и обычно оно ограничивается очень внутренними вещами фреймворка). - person poke; 12.09.2017
comment
@poke Для тех, кто видит ответ и задается вопросом, откуда взялся HttpContextAccessor, вам нужно добавить его в файл Startup.cs в методе ConfigureServices: services.AddHttpContextAccessor();. Затем вы помещаете его в свой конструктор контроллера, чтобы внедрить его в контроллер или в свою службу в его конструкторе. Что касается шаблонов DI и локатора сервисов и пограничных случаев. Я считаю, что использование клиента без сохранения состояния и микросервиса — хорошее место для этого, поскольку он поддерживает TempData и выходит за рамки логики программы. - person Larry Aultman; 01.11.2020