Capture de la sortie HTML avec un filtre d’action du contrôleur

J’ai le filtre suivant sur une action pour capturer la sortie HTML, la convertir en chaîne, effectuer certaines opérations pour modifier la chaîne et renvoyer un ContentResult avec la nouvelle chaîne. Malheureusement, je continue à me retrouver avec une chaîne vide.

private class UpdateFilter : ActionFilterAtsortingbute { private Stream stream; public override void OnActionExecuting(ActionExecutingContext filterContext) { stream = filterContext.HttpContext.Response.Filter; stream = new MemoryStream(); filterContext.HttpContext.Response.Filter = stream; } public override void OnResultExecuted(ResultExecutedContext filterContext) { StreamReader responsereader = new StreamReader(filterContext.HttpContext.Response.Filter); //empty stream? why? responsereader.BaseStream.Position = 0; ssortingng response = responsereader.ReadToEnd(); ContentResult contres = new ContentResult(); contres.Content = response; filterContext.Result = contres; } } 

J’ai constaté que StreamReader (stream) .ReadToEnd () renvoie une chaîne vide, mais je ne comprends pas pourquoi.

Une idée de comment réparer ça?

EDIT : J’ai changé OnActionExecuted en OnResultExecuted, et maintenant il est appelé après la génération de la vue, mais le stream est toujours vide!

J’ai résolu ce problème en détournant HttpWriter et en l’écrivant dans un SsortingngBuilder plutôt que dans la réponse, puis en faisant le nécessaire pour / avec la réponse avant de l’écrire dans la sortie.

  private class UpdateFilter : ActionFilterAtsortingbute { private HtmlTextWriter tw; private SsortingngWriter sw; private SsortingngBuilder sb; private HttpWriter output; public override void OnActionExecuting(ActionExecutingContext filterContext) { sb = new SsortingngBuilder(); sw = new SsortingngWriter(sb); tw = new HtmlTextWriter(sw); output = (HttpWriter)filterContext.RequestContext.HttpContext.Response.Output; filterContext.RequestContext.HttpContext.Response.Output = tw; } public override void OnResultExecuted(ResultExecutedContext filterContext) { ssortingng response = sb.ToSsortingng(); //response processing output.Write(response); } } 

Essayez de revenir au début du stream en définissant Position = 0; avant de le lire.

 public override void OnActionExecuted(ActionExecutedContext filterContext) { stream.Position = 0; ssortingng response = new StreamReader(stream).ReadToEnd(); ContentResult contres = new ContentResult(); contres.Content = response; filterContext.Result = contres; } 

Je pense avoir développé un très bon moyen de faire cela.

  • Remplacer le filtre de réponse par un filtre personnalisé
  • Ce filtre prend un délégué à une méthode abstraite qui prend un stream
  • Ce délégué, et donc la méthode abstraite, sont appelés à la fermeture du stream, c’est-à-dire lorsque tout le code HTML est disponible.
  • Remplacez la méthode OnClose et jouez avec le stream à votre guise.

 public abstract class ReadOnlyActionFilterAtsortingbute : ActionFilterAtsortingbute { private delegate void ReadOnlyOnClose(Stream stream); public override void OnActionExecuting(ActionExecutingContext filterContext) { filterContext.HttpContext.Response.Filter = new OnCloseFilter( filterContext.HttpContext.Response.Filter, this.OnClose); base.OnActionExecuting(filterContext); } protected abstract void OnClose(Stream stream); private class OnCloseFilter : MemoryStream { private readonly Stream stream; private readonly ReadOnlyOnClose onClose; public OnCloseFilter(Stream stream, ReadOnlyOnClose onClose) { this.stream = stream; this.onClose = onClose; } public override void Close() { this.Position = 0; this.onClose(this); this.Position = 0; this.CopyTo(this.stream); base.Close(); } } } 

Vous pouvez ensuite en déduire un autre atsortingbut pour accéder au stream et obtenir le code HTML:

 public class MyAtsortingbute : ReadOnlyActionFilterAtsortingbute { protected override void OnClose(Stream stream) { var html = new HtmlDocument(); html.Load(stream); // play with html } } 

Pouvez-vous vérifier que le stream n’est pas NULL dans la méthode OnActionExectuted? Je ne suis pas sûr que l’état de la variable de stream soit stocké à travers le processus.

Pourquoi n’essayez-vous pas d’extraire le stream du filterContext:

 public override void OnActionExecuted(ActionExecutedContext filterContext) { var stream = filterContext.HttpContext.Response.Filter; ssortingng response = new StreamReader(stream).ReadToEnd(); ContentResult contres = new ContentResult(); contres.Content = response; filterContext.Result = contres; }