2016-08-29 2 views
2

J'essaye de créer une aide HTML qui permettra à tout le texte d'une utilisation d'être consommé et non écrit sur la page finale.HtmlHelper pour consommer html/text inside en utilisant

Le rasoir:

<div> 
    <p> 
     Before Inline 
    </p> 

    @using (Html.IncludeInlineScript("testScript")) 
    { 
     <script type="text/javascript"> 
      alert("hello world"); 
     </script> 
    } 

    <p> 
     After Inline 
    </p> 
</div> 

Le code HTML résultant:

<div> 
    <p> 
     Before Inline 
    </p> 

     <script type="text/javascript"> 
      alert("hello world"); 
     </script> 
<!-- Top of Dispose --> 
<!-- Bottom of Dispose --> 

    <p> 
     After Inline 
    </p> 
</div> 

L'extension Helper Méthode:

public static ScriptWrapper IncludeInlineScript(this HtmlHelper helper, string scriptName) 
{ 
    return new ScriptWrapper(helper); 
} 

Le Wrapper:

public class ScriptWrapper : IDisposable 
{ 
    private HtmlHelper _helper; 
    private TextWriter _originalWriter; 
    private StringBuilder _scriptContents; 

    public ScriptWrapper(HtmlHelper helper) 
    { 
     _helper = helper; 
     _originalWriter = _helper.ViewContext.Writer; 

     _scriptContents = new StringBuilder(); 
     _helper.ViewContext.Writer = new StringWriter(_scriptContents); 
    } 

    public void Dispose() 
    { 
     _originalWriter.WriteLine("<!-- Top of Dispose -->"); 
     _helper.ViewContext.Writer.Flush(); 
     _helper.ViewContext.Writer = _originalWriter; 
     _originalWriter.WriteLine("<!-- Bottom of Dispose -->"); 
    } 
} 

Le problème ici est que, malgré le réglage du ViewContext.Writer à un nouveau TextWriter, il écrit toujours à l'écrivain d'origine. Clairement la disposition est invoquée dans le bon ordre comme le haut de la disposition est après le script. Pendant le débogage après que le nouvel éditeur a été défini, le bloc <script> ne figure pas dans le flux, mais au moment de la disposition, le <script> est maintenant contenu dans le programme d'origine.

Le moteur de rasoir conserve-t-il une copie locale de l'enregistreur et ignore le fait qu'il a été réglé sur une instance différente? Cela semble être un bug pour moi.

Répondre

0

Dans le cas où quelqu'un veut un travail, puisque je suis impatient, j'ai trouvé un moyen de faire ce travail. C'est moins qu'idéal, mais ça fait l'affaire. Si vous modifiez le ScriptWrapper être:

public class ScriptWrapper : IDisposable 
{ 
    private HtmlHelper _helper; 
    private string _originalString; 
    private StringBuilder _sb; 

    public ScriptWrapper(HtmlHelper helper) 
    { 
     _helper = helper; 
     _sb = ((StringWriter) _helper.ViewContext.Writer).GetStringBuilder(); 
     _originalString = _sb.ToString(); 
     _sb.Clear(); 
    } 

    public void Dispose() 
    { 
     var contents = _sb.ToString(); 
     _sb.Clear(); 
     _sb.Append(_originalString); 
    } 
} 

Vous pouvez obtenir le résultat souhaité de consommer quoi que ce soit dans l'instruction using(...).

Je serais cependant encore curieux de savoir s'il y a un moyen de le faire sans pirater une telle solution.

0

Dans l'original (la question), il est tentant de penser que parce que le balisage est dans le bloc à l'aide, en quelque sorte ScriptWrapper consomme le balisage

<script type="text/javascript"> 
    alert("hello world"); 
</script> 

mais comme vous avez découvert, il est pas être consommé par le ScriptWrapper en aucune façon. Vous espérez que ce balisage sera "redirigé" ailleurs, à l'auteur que vous créez, mais ce n'est pas le cas. Au lieu de cela, l'auteur que vous créez est également utilisé pour écrire dans le flux de réponse, ce qui est utilisé par le ViewContext.Writer, quel que soit l'auteur. Donc, plutôt que de faire consommer le balisage par ScriptWrapper, Razor l'interprète comme un balisage comme n'importe quoi d'autre dans la vue et l'écrit, après l'avoir interprété, dans le flux de réponse. Du point de vue de Razor, ce balisage est destiné à la sortie, pas à ScriptWrapper. Le simple fait de l'enfermer dans un bloc utilisant ne fait pas moins du balisage une partie de la vue globale. Vous répondez que vous réussissez parce que vous ne redirigez pas le balisage vers un autre emplacement (qui ne fonctionne pas), mais parce que vous modifiez ce qui finit dans le flux de réponse, effaçant ainsi le balisage du flux de réponse.

Je dirais que votre solution n'est pas un hack mais une façon correcte d'aborder cela, étant donné ce que vous voulez accomplir.

+0

Ce que vous avez dit serait correct si le TextWriter que j'ai créé a écrit cette valeur dans son constructeur de chaîne. Au lieu de cela l'auteur d'origine a obtenu la valeur en dépit de ne plus être attaché à ViewContent. Je pense toujours que c'est un défaut dans le cadre MVC5. – VulgarBinary