2012-03-29 4 views
11

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

Ближайший я получил это

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 doesn't seem to implement IHttpHandler

Существует также эта вещь System.Web.UI.PageHandlerFactory, которая кажется, что она просто создаст обработчик страницы для aspx-файла, но она внутренняя, и я не могу использовать ее напрямую.

Эта страница: http://msdn.microsoft.com/en-us/library/bb398986.aspx относится к «обработчику asp.net по умолчанию», но не идентифицирует класс и не дает никаких указаний на способ его использования.

Любые идеи о том, как я могу это сделать? Является ли это возможным?

ответ

6

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

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

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

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

+0

Я пытаюсь сопоставить другой маршрут с файлом, например. Я хочу, чтобы «/ a/b/c» вызывал «default.aspx? Path = a/b/c» без перенаправления. Я уже игнорирую * .aspx. –

+0

+1 для не слишком высокого уровня. Переадресация не имеет большого значения. Кроме того, ваш ответ отлично подходит для более общих поисковых запросов Google, которые помогут вам перейти на эту страницу. – Thabo

0

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