Using CacheCow with asp.net MVC kendoUI - kendo-ui

I've been looking into installing CacheCow ( https://github.com/aliostad/CacheCow ) , by just applying the nuget package and then adding:
GlobalConfiguration.Configuration.MessageHandlers.Add(new CacheCow.Server.CachingHandler(GlobalConfiguration.Configuration));
to my global config file. Once i do this though, none of my grids will refresh properly, they all cache old values regardless of new data being made available or not. I've used the header:
[OutputCache(NoStore = true, Duration = 0, VaryByParam = "*")]
public JsonResult _GetProjectList([DataSourceRequest] DataSourceRequest request)
{
return Json(data.ToDataSourceResult(request, ModelState), JsonRequestBehavior.AllowGet);
}
for outputcache at the top, but that doesn't seem to help. Anyone have any experience using cachecow with kendo datasources, and how to get them to work with each other?

You could try this as a solution.
[OutputCache(NoStore = true, Duration = 0, VaryByParam = "*")]
public JsonResult _GetProjectList([DataSourceRequest] DataSourceRequest request)
{
//force the response to not cache the results.
this.Response.Cache.SetCacheability(HttpCacheability.NoCache);
//some code here......
return Json(data.ToDataSourceResult(request, ModelState), JsonRequestBehavior.AllowGet);
}
I had to do this a while ago when I noticed that some of the Kendo widgets weren't updating their datasources correctly. (they did update when I turned off browser caching within the dev tools of the browser).
Although I haven't worked with that particular package hopefully this will work for you.

Related

Sitecore and caching control

I am working on this Sitecore project and am using WebApi to perform some service calls. My methods are decorated with CacheOutput information like this:
[HttpGet]
[CacheOutput(ClientTimeSpan = 3600, ServerTimeSpan = 3600)]
I am testing these calls using DHC app on Google Chrome. I am sure that the ClientTimespan is set correctly but the response headers that i am getting back are not what i am expecting. I would expect that Cache-Control would have a max-age of 1hour as set by the ClientTimespan attribute but instead it is set to private.
I have been debugging everything possible and t turns out that Sitecore may be intercepting the response and setting this header value to private. I have also added the service url to the sitecore ignored url prefixes configuration but no help .
Does anyone have an idea how I can make Sitecore NOT change my Cache-Control headers?
This is default MVC behaviour and not directly related to Sitecore / Web API.
You can create a custom attribute that sets the Cache-Control header:
public class CacheControl : System.Web.Http.Filters.ActionFilterAttribute
{
public int MaxAge { get; set; }
public CacheControl()
{
MaxAge = 3600;
}
public override void OnActionExecuted(HttpActionExecutedContext context)
{
context.Response.Headers.CacheControl = new CacheControlHeaderValue()
{
Public = true,
MaxAge = TimeSpan.FromSeconds(MaxAge)
};
base.OnActionExecuted(context);
}
}
Which enables you to add the [CacheControl(MaxAge = n)] attribute to your methods.
Code taken from: Setting HTTP cache control headers in WebAPI (answer #2)
Or you can apply it globally throughout the application, as explained here: http://juristr.com/blog/2012/10/output-caching-in-aspnet-mvc/

MVC3 + Streaming images from the Database is causing very high CPU usage on my server

I have this site that streams images from the database (SQL2008), and I think it's the one causing the very high CPU usage on my server. The CPU usage is at least 60-90%.
I am using MVC3 and below is the code in my Controller that sends the image to the View:
[OutputCache(Duration = 86400, VaryByParam = "GUID")]
public FileStreamResult GetFile(string guid)
{
Guid id = new Guid(guid);
Thumbnail thumbnail = thumbService.GetThumbnailByGUID(id);
Stream stream = new MemoryStream(thumbnail.FileContent.ToArray());
var fsr = new FileStreamResult(stream, "image");
return fsr;
}
The View:
<div style="background:url('#url');background-repeat:no-repeat;background-position:50% top;background-color:#fff;" class="photoThumb">
The #url above is /GetFile/guid
Can anyone tell me what I'm doing wrong?
Thanks
Updates on the answer and another question:
The [OutputCache(Duration = 86400, VaryByParam = "GUID")] from the answer below worked and has improved the performance of the site. The CPU usage has now went down to 8-60% but I also want to make sure that everything is disposed so I want to know if FileStreamResult is doing that for me or should I do it manually?
I'd guess that there is a database hit for each image request, with multiple images per page request - this could lead to high CPU usage. You should try caching the images.
If you decorate your action with
[OutputCache( Duration = 86400, VaryByParam = "id" )]
this should cache the result image for one day, meaning fewer db queries, and hopefully less load on your server.
You can also modify as below.
[OutputCache(Duration = 86400, VaryByParam = "GUID")]
public FileStreamResult GetFile(string guid)
{
Guid id = new Guid(guid);
Thumbnail thumbnail = thumbService.GetThumbnailByGUID(id);
var fsr;
using(Stream stream = new MemoryStream(thumbnail.FileContent.ToArray()))
{
fsr = new FileStreamResult(stream, "image");
}
return fsr;
}
As mentioned in above comment, when your page render FileStreamResult will automatically dispose.

Ajax Crawlable site - Get HTML Snapshot using WaTin

Id like to use Watin to get html snapshots to make my single page ajax app crawlable as per google specifications.
Can somebody please show me code example how to return an html snapshot to googlebot using Watin?
This is what I have so far but honestly Im not even sure where Im going with this I really havent found a single example on the web that would really clear it up:
Controller:
public PartialViewResult Solutions()
{
//Googlebot request
HtmlString htmlSnapshot = (HtmlString)GetHtmlSnapshot(Request.Path);
//return ?????????
//Normal user request
return PartialView("Solutions", null);
}
public PartialViewResult MarketData()
{
return PartialView("MarketData", null);
}
public IHtmlString GetHtmlSnapshot(string uglyUrl)
{
if (uglyUrl.Contains("?_escaped_fragment_="))
{
string prettyUrl = uglyUrl.Replace("?_escaped_fragment=", "");
string decodedUrl = HttpUtility.UrlDecode(prettyUrl);
FireFox firefox = new FireFox();
firefox.GoTo(decodedUrl);
//?????????
}
}

Returning 'other than HTML' formatted errors for AJAX calls to Web API

Investigating the Web API as part of an MVC 4 project as an alternative way to provide an AJAX-based API. I've extended AuthorizeAttribute for the MVC controllers such that, if an AJAX request is detected, a JSON-formatted error is returned. The Web API returns errors as HTML. Here's the AuthorizeAttribute that I'm using with the MVC controllers:
public class AuthorizeAttribute: System.Web.Mvc.AuthorizeAttribute
{
protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
{
base.HandleUnauthorizedRequest(filterContext);
filterContext.Result = new RedirectToRouteResult(
new RouteValueDictionary
{
{ "area", "" },
{ "controller", "Error" },
{ "action", ( filterContext.HttpContext.Request.IsAjaxRequest() ? "JsonHttp" : "Http" ) },
{ "id", "401" },
});
}
}
How could I reproduce this to provide equivalent functionality for the Web API?
I realize that I need to extend System.Web.Http.AuthorizeAttribute instead of System.Web.Mvc.AuthorizeAttribute but this uses an HttpActionContext rather than an AuthorizationContext and so I'm stuck by my limited knowledge of the Web API and the seemingly incomplete documentation on MSDN.
Am I even correct in thinking that this would be the correct approach?
Would appreciate any guidance.
To get the equivalent functionality in a Web API filter you can set the HttpActionContext.Response property to an instance of HttpResponseMessage that has the right redirect status code and location header:
protected override void HandleUnauthorizedRequest(HttpActionContext actionContext) {
var response = new HttpResponseMessage(HttpStatusCode.Redirect);
response.Headers.Location = new Uri("my new location");
actionContext.Response = response;
}
I would very much go with Marcin's answer - at the end of the day, he has written the code!
All I would add is that as Marcin is saying, your best bet is to have a dedicated controller to return the errors as appropriate - rather than setting the response code 401 with JSON content in the attribute.
The main reason is that Web API does the content-negotiation for you and if you want to do it yourself (see if you need to serve JSON or HTML) you lose all that functionality.

Multiple ajax get requests of same route but different query string

I have had this for a couple of days now.
I have a simple search form. When form is submitted the server searches for some data from another server and return data to the screen. When the submit completes it gets some javascript from the server based on the results returned from the search. the javascript then makes multiple concurrent jquery get requests, lets say 4, to the asp.net mvc3 webapp.
I have demonstrated that all the get requests fire at the same time in Firebug but when debugging my app with VS the breakpoints only get hit once the previous request completes.
The actions are the same but the querys are different; ie
/Home/Details/040801
/Home/Details/040802
/Home/Details/040803
So these are different URLs and, from what i found out, FF should treat them differently.
So my questions are:
Am I missing something obvious?
Does IIS have some funny blocking on the same route?
Is it a session cache issue? I am locking lock (lockobject){} on writes to the common session variables.
Im not using ViewBag or TempData.
The page load times, even when everything is cached in the Session, are still noticeably synchronous.
Windows Server 2008 R2
Using IIS 7.5
ASP.NET MVC 3
VS2010 Chrome or FF browser
I have my routes set up as follows:
routes.MapRoute(
"Default", // Route name
"{controller}/{action}", // URL with parameters
new { controller = "Home", action = "Index" } // Parameter defaults
);
routes.MapRoute("Details", "{controller}/{action}/{id}/{booking}", new { id = UrlParameter.Optional, booking = UrlParameter.Optional});
Nothing special there as you can see.
Sample code from one of the blocked routes:
public ActionResult Details(string id, bool booking = false)
{
if (booking)
{
return BookingDetails(id, true);
}
Dictionary<string, FlightDetails> detailDic;
string scenarioInput;
lock (DetailsLock)
{
if (Session["DetailDic"] == null)
{
Session["DetailDic"] = new Dictionary<string, FlightDetails>();
}
detailDic = (Dictionary<string, FlightDetails>)Session["DetailDic"];
}
if (detailDic.ContainsKey(id))
{
return PartialView("Details", detailDic[id]);
}
lock (GuidLock)
{
if (Session["DetailGuids"] == null)
{
Session["DetailGuids"] = new Dictionary<string, string>();
}
scenarioInput = ((Dictionary<string, string>)Session["DetailGuids"])[id];
}
// query results list
string queryText = string.Format("<View><Query><Where><Eq><FieldRef Name=\"Title\" /><Value Type=\"Text\">OUT {0}</Value></Eq></Where></Query></View>", scenarioInput);
ListItemCollection oList;
int counter = 0;
do
{
oList = SharepointHelper.GetListFromSharepoint("ListName", queryText, ClientContext);
counter++;
Thread.Sleep(1000);
} while (oList.Count == 0 && counter <= Timeout);
if (oList.Count == 0)
{
return PartialView("Details", (object)null);
}
var item = oList[0];
FlightDetails flightDetails = CreateFlightDetails(id, scenarioInput, item);
lock (DetailsLock)
{
detailDic.Add(id, flightDetails);
}
return PartialView("Details", flightDetails);
}
when using session object in server-side your async calls wait for session object released by other request. Becuase of this async ajax calls act like sync. You have to use session as readonly in that action.
Add this attribute to action you call if you dont write anything to session.
[SessionState(SessionStateBehavior.ReadOnly)]

Resources