Reputation: 13373
Basically we are in a major hacky situation. We have a few web pages that is linked to from an other site. However, the requirement is that this site has the same layout as the site that linked to us. This was originally done by requesting the original page, scraping the layout, and wrapping out content in their layout.
This was rather simple in Web Forms as we could simply create a subclassed Page, that overrides the Render method and then wrapped anything we produced in the external sites layout. However, now this project is being rewritten in ASP.NET MVC.
How can we get acccess to the HTML result created by the MVC actions, modify them according to our needs and output the modified result to the browser?
Upvotes: 2
Views: 2545
Reputation: 13373
After having tried tugberk's solution which was insufficient I ended up creating a custom view result:
public class WrappedViewResult : ViewResult
{
private readonly object model;
public WrapInDtuViewResult()
{
}
public WrapInDtuViewResult(object model)
{
this.model = model;
}
public override void ExecuteResult(ControllerContext context)
{
if (string.IsNullOrWhiteSpace(this.ViewName))
{
this.ViewName = context.RouteData.Values["action"].ToString();
}
ViewEngineResult result = this.FindView(context);
context.Controller.ViewData.Model = model;
ViewDataDictionary viewData = context.Controller.ViewData;
TempDataDictionary tempData = context.Controller.TempData;
var writer = new StringWriter();
ViewContext viewContext = new ViewContext(context, result.View, viewData, tempData, writer);
result.View.Render(viewContext, writer);
var content = writer.ToString();
Scraping scraping = new Scraping();
if (AppSettings.UseScraping)
{
content = scraping.Render(content);
}
else
{
content = "<html><head><script src='/Scripts/jquery-1.7.1.min.js' type='text/javascript'></script></head><body>" + content + "</body></html>";
}
context.HttpContext.Response.Write(content);
}
}
Upvotes: 2
Reputation: 58494
You can use ActionFilterAttribute.OnResultExecuted Method
You can see more sample on ActionFilters here:
EDIT
There is a great blog post on this topic:
To sum it up, you need to tweak your output. As far as I understand you need to use RegEx to get the portion you need to tweak out of the full HTML and you can do that like below:
This is a Helper class:
public class HelperClass : Stream {
//Other Members are not included for brevity
private System.IO.Stream Base;
public HelperClass(System.IO.Stream ResponseStream)
{
if (ResponseStream == null)
throw new ArgumentNullException("ResponseStream");
this.Base = ResponseStream;
}
StringBuilder s = new StringBuilder();
public override void Write(byte[] buffer, int offset, int count) {
string HTML = Encoding.UTF8.GetString(buffer, offset, count);
//In here you need to get the portion out of the full HTML
//You can do that with RegEx as it is explain on the blog pots link I have given
HTML += "<div style=\"color:red;\">Comes from OnResultExecuted method</div>";
buffer = System.Text.Encoding.UTF8.GetBytes(HTML);
this.Base.Write(buffer, 0, buffer.Length);
}
}
This is you filter:
public class MyCustomAttribute : ActionFilterAttribute {
public override void OnActionExecuted(ActionExecutedContext filterContext) {
var response = filterContext.HttpContext.Response;
if (response.ContentType == "text/html") {
response.Filter = new HelperClass(response.Filter);
}
}
}
You need to register this on Global.asax file Application_Start
method like below:
protected void Application_Start() {
//there are probably other codes here but I cut them out to stick with point here
GlobalFilters.Filters.Add(new MyCustomAttribute());
}
Upvotes: 9
Reputation: 842
Use this blog:
public class OutputCache : ActionFilterAttribute
{
public int Duration { get; set; }
public CachePolicy CachePolicy { get; set; }
public override void OnActionExecuted(ActionExecutedContext filterContext)
{
// Client-side caching?
if (CachePolicy == CachePolicy.Client || CachePolicy == CachePolicy.ClientAndServer)
{
if (Duration <= 0) return;
HttpCachePolicyBase cache = filterContext.HttpContext.Response.Cache;
TimeSpan cacheDuration = TimeSpan.FromSeconds(Duration);
cache.SetCacheability(HttpCacheability.Public);
cache.SetExpires(DateTime.Now.Add(cacheDuration));
cache.SetMaxAge(cacheDuration);
cache.AppendCacheExtension("must-revalidate, proxy-revalidate");
}
}
}
Upvotes: 0