0

I have an MVC action with an OutputCache as I need the data to be cached to minimize calls to myService.

[HttpGet]
[OutputCache(Duration = 86400, Location = OutputCacheLocation.ServerAndClient, VaryByParam = "myVariable")]
public JsonResult GetStuffData(string myVariable)
{
    if (Request.IsLocal)
    {
        return myService.CalculateStuff(myVariable)
    }
    else
    {
        return null;
    }
}

I want this only to be accessible from the server it's running on hence the Request.IsLocal.

This works fine, however if someone accesses GetStuffData remotely then it will return null, and null will be cached for a day... making that particular GetStuffData(myVariable) useless for a day.

Similarly, if it was locally called first, then external requests will receive the cached local data.

Is there a way to restrict the entire function to Request.IsLocal instead of just the return value?

So for example, if it's externally accessed you'd just get 404, or Method Not Found etc. But if it was Request.Local you'd be served the cached result.

If it wasn't for the caching this would run perfectly fine, but I'm struggling to find a way to combine Request.IsLocal and caching.

Extra Info that may be relevant:

I call GetStuffData through C# to getcached StuffData by fetching a json object like this... (calling the action directly never resulted in it being cached, so I switched to simulating a webrequest)

HttpWebRequest request = (HttpWebRequest)WebRequest.Create(urlToGetStuffData);
WebResponse response = request.GetResponse();
using (Stream responseStream = response.GetResponseStream()) {
    StreamReader reader = new StreamReader(responseStream, Encoding.UTF8);
    return reader.ReadToEnd();
}
mejobloggs
  • 7,937
  • 6
  • 32
  • 39

1 Answers1

2

You can use custom authorization filter attribute like

public class OnlyLocalRequests : AuthorizeAttribute
{
        protected override bool AuthorizeCore(HttpContextBase httpContext)
        {
            if (!httpContext.Request.IsLocal)
            {
                httpContext.Response.StatusCode = (int)HttpStatusCode.NotFound;
                return false;
            }
            return true;
        }
}

and decorate your action as

[HttpGet]
[OnlyLocalRequests]
[OutputCache(Duration = 86400, Location = OutputCacheLocation.ServerAndClient, VaryByParam = "myVariable")]
public JsonResult GetStuffData(string myVariable)
{}
Dandy
  • 2,177
  • 14
  • 16
  • Looks good but doesn't quite work. If I first access it externally I got 404 (great). If I access it locally, i get the results (great). If I then access it externally, i get the cached result. So still a problem – mejobloggs Oct 21 '15 at 19:51
  • @mejobloggs i have updated the `OnlyLocalRequests` class. – Dandy Oct 21 '15 at 20:39
  • Excellent. Doesn't return a 404 but sends me to the login page when I externally access, but that's perfectly fine. All working – mejobloggs Oct 21 '15 at 23:47