Можно ли скопировать/клонировать HttpContext веб-запроса?
-
13-09-2019 - |
Вопрос
Какой самый простой способ клонировать экземпляр HttpContext текущего запроса?
Я разрабатываю приложение в Asp.net MVC v1.Я обновил обычные возможности PartialView, чтобы иметь субконтроллеры, которые действуют очень похоже, но имеют свой собственный контекст.Когда вы используете PartialViews, вам необходимо заполнить данные представления для частичного представления в действии контроллера вашего основного представления.Я создал свою собственную функциональность, которая позволяет вызывать действия контроллера из представления.Таким образом я получаю:
- Мне не нужно предоставлять данные подпредставления в действии контроллера моего основного представления.
- методы субконтроллера могут манипулировать более инкапсулированными данными без какого-либо отношения к другим представлениям/контроллерам.
Проблема в том, что каждый запрос субконтроллера использует HttpContext.Поэтому, когда я устанавливаю некоторый HttpContext.Item в субконтроллере, он фактически заполняет HttpContext фактического запроса.
Вот почему я хочу клонировать HttpContext.Я уже использую:
HttpContext subContext = new HttpContext(request, response);
// what happened to Session, User, Items etc. properties?
но это не устанавливает ничего, кроме запроса и ответа.Но мне, вероятно, также понадобятся другие свойства и коллекции...Например, сеанс, элементы, пользователь...и т. д.
Решение 2
Невозможно
Я предполагаю, что настоящее глубокое клонирование невозможно из-за состояния сеанса сервера.При клонировании также потребуется клонировать это значение, которое является внутренним ресурсом, специфичным для веб-сервера, который по своей сути статичен и не может быть клонирован.Например, в этом случае веб-сервер будет иметь несколько объектов сеанса.
Обходной путь
В любом случае.Обходной путь заключался в установке дополнительных значений контекста перед запуском обработки субконтроллера.После завершения обработки я вернул значения к исходным.Так что на самом деле у меня был такой же контекст, как и раньше.
Другие советы
Хотя ответ «Невозможно» является правильным, существует альтернатива, которая намного проще, чем записывать значения в текущий контекст, а затем перезаписывать их обратно в исходное состояние.Решение состоит в том, чтобы полностью создать новый объект HttpContext, основанный на выбранном вами URL-адресе.
// A new request/response is constructed to using a new URL.
// The new response is using a StreamWriter with null stream as a backing stream
// which doesn't consume resources
using (var nullWriter = new StreamWriter(Stream.Null))
{
var newRequestUri = new Uri("http://www.somewhere.com/some-resource/");
var newRequest = new HttpRequest("", newRequestUri.ToString(), newRequestUri.Query);
var newResponse = new HttpResponse(nullWriter);
var newContext = new HttpContextWrapper(new HttpContext(newRequest, newResponse));
// Work with the new context here before it is disposed...
}
Ссылка: https://github.com/maartenba/MvcSiteMapProvider/issues/278#issuecomment-34905271
Платформа ASP.NET MVC намеренно делает зависимости абстрактных классов со всеми виртуальными членами.Это просто говорит о расширяемости.
Контроллеры зависят от HttpContextBase, а не от HttpContext.Возможно, вы также можете сделать так, чтобы ваши субконтроллеры зависели от HttpContextBase, чтобы вы могли обернуть его.Просто мои 2 цента.
я использовал
<% Html.RenderAction("Action", "Controller"); %>
с большим эффектом, позволяя мне создавать полностью изолированные/инкапсулированные действия, не прибегая к сложному коду.Казалось бы, это предлагает ту же функциональность, но без той же сложности.
Визуализированные представления представляют собой стандартные частичные представления, а действия контроллера такие же, как и любые другие.