Вызовите по умолчанию asp.net HttpHandler из пользовательского обработчика
Я добавляю маршрутизацию ASP.NET в более старое приложение веб-форм. Я использую пользовательский HttpHandler
для обработки всего. В некоторых ситуациях я хотел бы сопоставить конкретный путь к файлу aspx
, поэтому мне нужно просто передать управление HttpHandler по умолчанию для asp.net.
Самое близкое, что я получил, это
public void ProcessRequest(HttpContext context) {
// .. when we decide to pass it on
var handler = new System.Web.UI.Page();
handler.ProcessRequest(context);
MemoryStream steam = new MemoryStream();
StreamWriter writer = new StreamWriter(stream);
HtmlTextWriter htmlWriter = new HtmlTextWriter(writer);
handler.RenderControl(htmlWriter);
// write headers, etc. & send stream to Response
}
Он ничего не делает, в поток ничего не выводится. Документация MS для System.Web.UI.Page(как IHttpHandler) говорит о том, что "не вызывайте метод ProcessRequest, он используется для внутреннего использования".
От взгляда вокруг кажется, что вы можете сделать это с помощью MVC, например.: MvcHttpHandler, похоже, не реализует IHttpHandler
Существует также эта вещь System.Web.UI.PageHandlerFactory
, которая кажется, что она просто создала обработчик страницы для aspx файла, но она внутренняя, и я не могу использовать ее напрямую.
Эта страница: http://msdn.microsoft.com/en-us/library/bb398986.aspx относится к "обработчику asp.net по умолчанию", но не идентифицирует класс или не дает никаких указаний о том, как его можно было бы использовать.
Любые идеи о том, как я могу это сделать? Возможно ли это?
Ответы
Ответ 1
Стойкость окупается! Это действительно работает, и поскольку эта информация, похоже, доступна почти нигде, я думал, что отвечу на мой собственный вопрос. Благодаря Роберту для этого сообщения о создании экземпляров с помощью внутренних конструкторов это ключ.
http://www.rvenables.com/2009/08/instantiating-classes-with-internal-constructors/
public void ProcessRequest(HttpContext context) {
// the internal constructor doesn't do anything but prevent you from instantiating
// the factory, so we can skip it.
PageHandlerFactory factory =
(PageHandlerFactory)System.Runtime.Serialization.FormatterServices
.GetUninitializedObject(typeof(System.Web.UI.PageHandlerFactory));
string newTarget = "default.aspx";
string newQueryString = // whatever you want
string oldQueryString = context.Request.QueryString.ToString();
string queryString = newQueryString + oldQueryString!="" ?
"&" + newQueryString :
"";
// the 3rd parameter must be just the file name.
// the 4th parameter should be the physical path to the file, though it also
// works fine if you pass an empty string - perhaps that only to override
// the usual presentation based on the path?
var handler = factory.GetHandler(context, "GET",newTarget,
context.Request.MapPath(context,newTarget));
// Update the context object as it should appear to your page/app, and
// assign your new handler.
context.RewritePath(newTarget , "", queryString);
context.Handler = handler;
// .. and done
handler.ProcessRequest(context);
}
... и, как и небольшое чудо, страница aspx обрабатывает и обрабатывает весь процесс без необходимости перенаправления.
Я ожидаю, что это будет работать только в IIS7.
Ответ 2
Я использую Routing в webforms, вы должны просто добавить маршрут игнорирования для определенных файлов .aspx, которые вы хотите. Затем будет обрабатываться HttpHandler по умолчанию.
http://msdn.microsoft.com/en-us/library/dd505203.aspx
Ответ 3
Другой вариант - инвертировать логику, обрабатывая случаи, в которых вы НЕ хотите возвращать ответ по умолчанию и переназначать других на свой собственный IHttpHandler. Всякий раз, когда myCondition является ложным, ответ будет "по умолчанию". Коммутатор реализован как IHttpModule:
public class SwitchModule: IHttpModule
{
public void Init(HttpApplication context)
{
context.PostAuthenticateRequest += app_PostAuthenticateRequest;
}
void app_PostAuthenticateRequest(object sender, EventArgs e)
{
// Check for whatever condition you like
if (true)
HttpContext.Current.RemapHandler(new CustomHandler());
}
public void Dispose()
}
internal class CustomHandler: IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
context.Response.Write("hallo");
}
public bool IsReusable { get; }
}