2009-03-04 6 views
0

Je souhaite étendre WebFormViewEngine pour que je puisse effectuer un post-traitement - je veux qu'il soit fait, puis me remettre le code HTML, afin que je puisse y apporter quelques retouches. Cela doit être fait en tant que View/ViewEngine car j'ai besoin d'accéder à ViewData.Extension de WebFormView dans MVC

Malheureusement, il semble qu'il n'y ait aucun moyen de récupérer le code HTML à partir de WebFormView, et aucun moyen de transmettre un HtmlTextWriter personnalisé à WebFormView ou ViewPage.

Sûrement il y a un moyen de faire cela? Non?

Littlecharva

Répondre

2

Vous pouvez utiliser des filtres d'action pour cela. Découvrez this tutorial à asp.net/mvc. Vous voulez utiliser un ResultsFilter. En alternative, vous pouvez remplacer la méthode OnResultExecuted virtuelle du contrôleur.

+0

Merci, cela me rapproche un peu plus de l'endroit où je veux être. Je peux évidemment réaliser ce que je veux en utilisant les Filtres d'Action ou en surchargeant OnResultExecuted, mais je pense que le code que j'écris appartient à ViewEngine, car il sera exécuté sur TOUTES les vues. – littlecharva

+0

Il peut fonctionner sur toutes les vues de CETTE application, mais pas sur toutes les applications. Vous ne voulez pas changer le cadre pour chaque projet. – Matthew

0

D'accord, je n'ai jamais fait cela auparavant, mais je regardé à travers le réflecteur et les ensembles MVC. Il semble que vous puissiez étendre les objets ViewPage et ViewPage et ViewMasterPage à votre objet. Dans votre propre objet, vous pouvez remplacer la méthode de rendu et obtenir un handle pour le HtmlTextWriter. Ensuite, passez-le à la base et laissez-le faire. Quelque chose comme ceci (ceci est non-testé et est seulement théorique, il peut y avoir plus de méthodes que vous devez remplacer.) Je recommande d'utiliser le réflecteur pour voir comment c'est fait maintenant et même comment les autres moteurs de vue comme Spark le font.

public class MyPage : ViewPage 
{ 
    protected override void Render(System.Web.UI.HtmlTextWriter writer) 
    { 
     //Do custom stuff here 
     base.Render(writer); 
    } 
} 
public class MyPage<TModel> : MyPage where TModel : class 
{ 
} 
+0

j'avais utilisé réflecteur et étudié cette voie, le problème est qu'il semble y avoir aucun moyen d'avoir la WebViewEngine instancier mon ViewPage au lieu du défaut. Il semble utiliser un BuildManager, mais il n'y a aucun moyen évident de contrôler le BuildManager. – littlecharva

1

Vous pouvez capturer le receveur de sortie avant que le rendu ne soit rendu en redéfinissant la méthode Render de la classe WebFormView. L'astuce est que le récepteur de sortie n'est pas l'auteur System.IO.TextWriter mais la propriété Writer du viewContext. De plus, vous devez étendre WebFormViewEngine pour renvoyer vos vues.

public class MyViewEngine : WebFormViewEngine 
{ 
    protected override IView CreatePartialView(ControllerContext controllerContext, string partialPath) 
    { 
     return new MyView(partialPath, null); 
    } 

    protected override IView CreateView(ControllerContext controllerContext, string viewPath, string masterPath) 
    { 
     return new MyView(viewPath, masterPath); 
    } 
}  

public class MyView : WebFormView 
{ 
    public MyView(string inViewPath, string inMasterPath) : base(inViewPath, inMasterPath) { } 
    public MyView(string inViewPath) : base(inViewPath) { } 

    public override void Render(ViewContext viewContext, System.IO.TextWriter writer) 
    { 
     //make a switch to custom output receiver 
     var oldWriter = viewContext.Writer; 
     viewContext.Writer = new System.IO.StringWriter(); 
     base.Render(viewContext, null); 
     viewContext.Writer.Close(); 

     //get output html 
     var html = ((System.IO.StringWriter)viewContext.Writer).GetStringBuilder(); 

     //perform processing 
     html.Replace('a', 'b'); 

     //retransmit output 
     viewContext.Writer = oldWriter; 
     viewContext.Writer.Write(html); 
    } 
}