Можно ли скопировать/клонировать HttpContext веб-запроса?

StackOverflow https://stackoverflow.com/questions/1466804

Вопрос

Какой самый простой способ клонировать экземпляр 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"); %>

с большим эффектом, позволяя мне создавать полностью изолированные/инкапсулированные действия, не прибегая к сложному коду.Казалось бы, это предлагает ту же функциональность, но без той же сложности.

Визуализированные представления представляют собой стандартные частичные представления, а действия контроллера такие же, как и любые другие.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top