J'ai le filtre suivant en place sur une action pour capturer la sortie HTML, convertir en une chaîne, effectuez des opérations pour modifier la chaîne et renvoyer un conteneur avec la nouvelle chaîne. Malheureusement, je continue de finir avec une chaîne vide.
private class UpdateFilter : ActionFilterAttribute { 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; string response = responsereader.ReadToEnd(); ContentResult contres = new ContentResult(); contres.Content = response; filterContext.Result = contres; } }
4 Réponses :
Essayez de rembobiner le flux au début en réglant position = 0; code> avant de le lire.
public override void OnActionExecuted(ActionExecutedContext filterContext)
{
stream.Position = 0;
string response = new StreamReader(stream).ReadToEnd();
ContentResult contres = new ContentResult();
contres.Content = response;
filterContext.Result = contres;
}
Cela ne l'a pas réparais, mais cela m'a amené à remarquer que la position est déjà 0. Elle semble donc être vide ... Je me demande pourquoi
Pouvez-vous vérifier que ce flux n'est pas null dans la méthode OnAptionExecté? Je ne suis pas sûr que l'état de la variable de flux est stocké à travers le processus ..
Pourquoi n'essayez-vous pas d'obtenir le flux du filtreContext: P>
public override void OnActionExecuted(ActionExecutedContext filterContext) { var stream = filterContext.HttpContext.Response.Filter; string response = new StreamReader(stream).ReadToEnd(); ContentResult contres = new ContentResult(); contres.Content = response; filterContext.Result = contres; }
Eh bien, je pensais que ce serait la réponse, mais j'ai le même problème. Le flux i obtient de filtrecontext.httpcontext.response.filter a la longueur 0.
J'ai résolu ceci en détournant le httpwriter et l'avoir écrit dans un stringbuilder code> plutôt que la réponse, puis faisant tout ce qui doit être effectué pour la rédaction avant de l'écrire à la sortie.
private class RenderFilter : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
StringBuilder sb = new StringBuilder();
StringWriter sw = new StringWriter(sb);
HtmlTextWriter tw = new HtmlTextWriter(sw);
HttpWriter output = (HttpWriter)filterContext.RequestContext.HttpContext.Response.Output;
filterContext.HttpContext.Items["sb"] = sb;
filterContext.HttpContext.Items["output"] = output;
filterContext.RequestContext.HttpContext.Response.Output = tw;
}
public override void OnResultExecuted(ResultExecutedContext filterContext)
{
string response = filterContext.HttpContext.Items["sb"].ToString();
//response processing
((HttpWriter)filterContext.HttpContext.Items["output"]).Write(response);
}
}
Un avertissement: il n'est pas recommandé d'utiliser des variables d'instance dans des filtres d'action. Vous n'êtes pas garanti d'obtenir une nouvelle instance de l'actionfilterattribute sur chaque demande. J'ai basé mon code sur cette réponse et j'ai eu des ennuis quand il est allé à la production avec des milliers de demandes par seconde - les fils (threads) se sont croisés. Stockez les variables d'instance dans le filtreContext.httpcontext.items comme suggéré dans ce message: Stackoverflow.com/a/8937793/140449
Je pense avoir développé un très bon moyen de le faire.
osclose code> et jouez avec le flux comme vous le souhaitez. LI>
ul>
xxx pré> Vous pouvez ensuite dériver de ceci à un autre attribut pour accéder au flux et obtenir le code HTML: P>
public class MyAttribute : ReadOnlyActionFilterAttribute
{
protected override void OnClose(Stream stream)
{
var html = new HtmlDocument();
html.Load(stream);
// play with html
}
}
La question concerne la mise à jour du résultat, ce n'est pas possible avec votre solution?
@Gaz devrait être assez simple pour modifier pour le faire fonctionner. Il y a tout à fait il y a longtemps, je ne me souviens pas désolé!
@Gaz, cela devrait obtenir le point de vue dans la bonne direction. Le problème est que le flux par défaut dans filtercontext.requestcontext.httpcontext.response code> ne prend pas en charge la lecture. Vous devez donc remplacer le flux avec celui qui permet de lire.