Вызовите asp.net по умолчанию HttpHandler из пользовательского обработчика - PullRequest
11 голосов
/ 29 марта 2012

Я добавляю маршрутизацию 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 по умолчанию"но не идентифицирует класс и не дает никаких указаний на то, как его можно использовать.

Есть идеи, как мне это сделать?Возможно ли это?

Ответы [ 3 ]

7 голосов
/ 29 марта 2012

Упорство окупается!Это на самом деле работает, и, поскольку эта информация, кажется, практически нигде не доступна, я решил ответить на свой вопрос.Спасибо Роберту за этот пост о создании экземпляров с помощью внутренних конструкторов, это ключ.

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's 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.

1 голос
/ 29 марта 2012

Я использую маршрутизацию в веб-формах, вы можете просто добавить маршрут игнорирования для конкретных файлов .aspx, которые вы хотите. Затем это будет обработано HttpHandler по умолчанию.

http://msdn.microsoft.com/en-us/library/dd505203.aspx

0 голосов
/ 03 ноября 2016

Другой вариант - инвертировать логику, обрабатывая случаи, когда вы НЕ хотите возвращать ответ по умолчанию и переназначать остальные в свой собственный IHttpHandler.Всякий раз, когда myCondition имеет значение false, ответом будет «по умолчанию».Переключатель реализован в виде 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; }
}
...