I have a service method which is getting data from a URL based on the parameters news/blogs.
How to cache the data coming from the URL every 30 minutes?
The user details also get cached for 30 minutes.
Also how do i cache the news,blogs separately if they are coming from the same service URL
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
public class IITNews : IIITNews
{
System.Web.SessionState.HttpSessionState session = HttpContext.Current.Session;
private static DateTime cacheExpiry = DateTime.MinValue;
string loggedinUser = "";
private string cachedResponse = "";
public Stream getNewsBlogsZD(string type, string noOfItems, string devicetype)
{
try
{
if (cacheExpiry > DateTime.Now)
{
if (System.Web.HttpContext.Current.Cache[cachedResponse] != null)
{
logger.Debug(loggedinUser + "Getting the cached data");
}
return new MemoryStream(Encoding.UTF8.GetBytes(cachedResponse));
}
else
{
string loggedInUserNum = GetEmployeeNumber();
string scenarioType = "";
string url = "";
if (type.Trim().ToUpper() == "NEWS")
{
scenarioType = "DisplayNews";
url = ServiceURL + "getWidgetDetails?WName=News&noOfItems=" + Convert.ToInt32(noOfItems.Trim());
}
else if (type.Trim().ToUpper() == "ZD")
{
scenarioType = "DisplayZD";
url = ServiceURL + "getWidgetDetails?WName=ZD&noOfItems=" + Convert.ToInt32(noOfItems.Trim());
}
else if (type.Trim().ToUpper() == "BLOGS")
{
scenarioType = "DisplayBlogs";
url = ServiceURL + "getWidgetDetails?WName=Blogs&noOfItems=" + Convert.ToInt32(noOfItems.Trim());
}
WebClient client = new WebClient();
client.UseDefaultCredentials = true;
client.Encoding = System.Text.Encoding.UTF8;
cachedResponse = client.DownloadString(url);
HttpContext.Current.Cache.Insert("cacheResponse",cachedResponse ,null);
cacheExpiry = DateTime.Now.AddMinutes(30);
return new MemoryStream(Encoding.UTF8.GetBytes(cachedResponse));
}
}
catch (Exception ex)
{
string message=ex.message;
return new MemoryStream(Encoding.UTF8.GetBytes("[]"));
}
}
public stream userdertails
{
//method to fetch user details where no cache is used
}
}
If this is your service, you can cache it on the service and return same data for very same parameters.
If not, you can create some singleton class to hold data in. If the singleton has valid data, return them instead of calling WebService :)
Store the result somewhere, along with a time stamp. Where you store it is up to you. There are a variety of caching systems you can find, there's a database, there's the file system, in-memory static values, instance values, etc., etc.
Possibly the simplest approach would just be a class-level value. Something like this:
private string cachedResponse = "";
private DateTime cacheExpiry = DateTime.MinValue;
Then in your logic you would check for the cache before deciding to query the service. Something like this:
if (cacheExpiry > DateTime.Now)
return new MemoryStream(Encoding.UTF8.GetBytes(cachedResponse));
// the rest of your method to query the service
// then...
cachedResponse = client.DownloadString(url);
cacheExpiry = DateTime.Now.AddMinutes(30);
return new MemoryStream(Encoding.UTF8.GetBytes(cachedResponse));
This is just an example of the logic behind the concept of a cache, of course. If your object instance itself doesn't remain in memory then this object-level cache of course wouldn't do the job. The logic is always the same:
Check if the cache is still valid.
If so, return the cached value.
If not, query the service and store the new value and update the cache expiry and return the newly cached value.
Where you store the cache is up to you and depends on more than what's present in this question.
You can use the MemoryCache Class which enables you to cache objects and set time of them to live in cache.
Related
I'm using asp.net and c# for backend code and html, javascript/jquery on frontend
User clicks "Details" on website to view and edit requests previously created.
jquery/ajax calls method on backend to get infomation about requests.
An object, newWaferRequest, is created which holds this information. The object is returned from ajax call and the site populates a form with that information. The user can then edit the form, add new programs to requests, modify existing requests info etc...
The problem I'm getting is when the user selects "Save pgm", ajax calls backend savePgm method which is supposed to update the Object newWaferRequest previously created, but I'm receiving a nullReferenceException. The exception is pointing to the newWaferRequest object being null. This happens at different times when the user is updating the request. Sometimes the user can update the program and add new programs, with a correct response from backend. Other times the exception occurs.
I must not have a full grasp of how variables are "stored" when using the web. I read multiple post on here and have read about Session and ViewState variables. I've tried saving the Object in a Session with no luck.
This is just showing the beginning of my c# code, I tried using static variables initially. All the objects are in App_code cs files.
public partial class Nbump_Request : System.Web.UI.Page
{
//public static person currentPerson = new person();
//public static requestSearch searchRequest;
//public static waferRequest newWaferRequest;
//public static waferRequestObject newWaferRequestObject;
static person currentPerson = new person();
static requestSearch searchRequest;
static waferRequest newWaferRequest;
static waferRequestObject newWaferRequestObject;
Here is ajax method for existing requests, which creates objects
[WebMethod]
public static string queryRequestExisting(string request_pk)
{
JavaScriptSerializer js = new JavaScriptSerializer();
try
{
newWaferRequest = new waferRequest(request_pk, "EXISTINGREQUEST");
newWaferRequestObject = newWaferRequest.CURRENTREQUEST;
string json = js.Serialize(newWaferRequest);
return json;
}
catch (Exception)
{
return null;
}
}
Here is ajax code for when user saves or updates program information. I added in the code to check and return with the object was null.
public static string savePgmData(Dictionary<string, string> pgm_requests)
{
PgmRequestObject currentPgm;
if (newWaferRequest != null)
{
try
{
//if (!Convert.ToBoolean(pgm_requests["pgmEdit"])) //not performed when request pgm being edited
string rtnMessage;
//create new pgm in waferRequest object
if (pgm_requests["PGMRT_INDEX_PK"] == null)
{
int index = newWaferRequest.addNewPGMRequest() - 1;
currentPgm = (PgmRequestObject)newWaferRequest.PGMREQUESTLIST[index];
string pgmPrimaryKey = currentPgm.PGMRT_INDEX_PK;
rtnMessage = "{\"message\": \"Added and saved new pgm successfully\", \"primaryKey\":\"" + pgmPrimaryKey + "\"}";
}
//get pgm to update at index provided
else if (pgm_requests["pgmRowIndex"] != "-1")
{
int index = Convert.ToInt32(pgm_requests["pgmRowIndex"]);
currentPgm = (PgmRequestObject)newWaferRequest.PGMREQUESTLIST[index];
rtnMessage = "Edited and saved pgm successfully";
}
//save initial pgm
else
{
currentPgm = (PgmRequestObject)newWaferRequest.PGMREQUESTLIST[0];
rtnMessage = "Initial pgm added successfully";
}
currentPgm.updatePGM(pgm_requests["pgmNameList"], pgm_requests["pgmNameText"]);
currentPgm.updateStatus(pgm_requests["pgmStatus"]);
currentPgm.updateWafers(pgm_requests["pgmWfrList"], pgm_requests["pgmWfrNum"]);
currentPgm.updatePriority(pgm_requests["pgmTestOrder"]);
currentPgm.updateFailBinRetest(pgm_requests["pgmFbr"], pgm_requests["pgmFbrBins"]);
//currentPgm.CommitIntoDatabase(); // -- Called on individual requests updates before request saved
return rtnMessage;
}
catch (Exception ex)
{
return "Failed to save program\n\n" + ex.Data + "\n" + ex.Message + "\n" + ex.StackTrace + "\n";
}
}
else
{
return "newWaferRequest object is null\n";
}
}
This is a short snippet of the class for waferRequest. This is located in the app_code and is a cs file. The pgmRequestList contains an array of pgm objects. That is what I update when user selects "Save Program".
public class waferRequest
{
/*The class will hold request information, creation and delete.
*
*/
private waferRequestObject currentRequest;
private ArrayList WaferRequestList = new ArrayList();
private ArrayList PGMRequestList = new ArrayList();
Here is an example of what I tried for Session. I got rid of static variables and modified the methods
[WebMethod(EnableSession=true)]
public static string queryRequestExisting(string request_pk)
{
waferRequest newWaferRequest;
waferRequestObject newWaferRequestObject;
JavaScriptSerializer js = new JavaScriptSerializer();
try
{
newWaferRequest = new waferRequest(request_pk, "EXISTINGREQUEST");
newWaferRequestObject = newWaferRequest.CURRENTREQUEST;
HttpContext.Current.Session["newWaferRequest"] = newWaferRequest;
HttpContext.Current.Session["newWaferRequestObject"] = newWaferRequestObject;
string json = js.Serialize(newWaferRequest);
return json;
}
catch (Exception)
{
return null;
}
}
//snippet of savePgmData with session
public static string savePgmData(Dictionary<string, string> pgm_requests)
{
waferRequest newWaferRequest = HttpContext.Current.Session["newWaferRequest"];
PgmRequestObject currentPgm;
if (newWaferRequest != null)
{
try
{
//if (!Convert.ToBoolean(pgm_requests["pgmEdit"])) //not performed when request pgm being edited
string rtnMessage;
//create new pgm in waferRequest object
if (pgm_requests["PGMRT_INDEX_PK"] == null)
{
int index = newWaferRequest.addNewPGMRequest() - 1;
currentPgm = (PgmRequestObject)newWaferRequest.PGMREQUESTLIST[index];
I am limited to the code I'm allowed to show because of work security. Please let me know if more information is needed.
Also, the code seems to work fine on my local server. The issue is when I put it on the production server or development server -- Both of which I don't have access to make changes on.
In Asp.Net core, a cookie is created when you configure your app to app.UseSession().
By default the cookie is called ".AspNetCore.Session". Its value identifies the session to be used. Currently, I'm saving my session data on a sql server. I need to know the decrypted value of ".AspNetCore.Session" so that I can lookup the session in the database.
Is there a way to decrypt this value? I know ASP.NET must do it behind the scenes somehow.
The session source has everything, but you should need to know it, ISessionStore and IDistributedSessionStore gives you a sessionkey to use.
Rather than make an assumption about the cookie format, what is stopping you from using the store APIs?
I had to extract the private Pad function from Microsoft.AspNetCore.Session, but I was able to get what I needed:
public class DiscussionController : Controller
{
private readonly IDataProtector _dataProtector;
public DiscussionController(IDataProtectionProvider dataProtectionProvider)
{
var protectorPurpose = "whatever purpose you want";
_dataProtector = dataProtectionProvider.CreateProtector(protectorPurpose);
}
public IActionResult Index()
{
HttpContext.Request.Cookies.TryGetValue(".AspNetCore.Session", out string cookieValue);
var protectedData = Convert.FromBase64String(Pad(cookieValue));
var unprotectedData = _dataProtector.Unprotect(protectedData);
var humanReadableData = System.Text.Encoding.UTF8.GetString(unprotectedData);
return Ok();
}
private string Pad(string text)
{
var padding = 3 - ((text.Length + 3) % 4);
if (padding == 0)
{
return text;
}
return text + new string('=', padding);
}
}
The Pad function was taken from: https://github.com/aspnet/AspNetCore/blob/87629bbad906e9507026692904b6bcb5021cdd33/src/Middleware/Session/src/CookieProtection.cs#L61-L69
I am using SESSION for storing user data, thus avoiding unnecessary access to the database. However, each access controller, data FormsAuthentication are renewed and data SESSION no.
What better way to get around this problem?
Put the lives of the great SESSION, or make a Base Controller or each called a ActionResult renew the life of SESSION.
Detail, SESSION I use this to mount a header of my pages.
This code, create SESSION.
public static void UsuarioLogar(string login)
{
CustomMembershipUser usuario = new CustomMembershipUser();
using (var dbUser = new ERPContext())
{
var dados = (from u in dbUser.Usuario
where u.Login == login
select new
{
Nome = u.Nome,
UsuarioID = u.UsuarioID,
EmpresaID = u.EmpresaID,
EmpresaLogada = u.Empresa,
PessoaLogada = u.PessoaLogada
}).FirstOrDefault();
if (dados != null)
{
usuario.UsuarioID = dados.UsuarioID;
usuario.Nome = dados.Nome;
usuario.EmpresaID = dados.EmpresaID;
usuario.EmpresaLogada = dados.EmpresaLogada;
usuario.PessoaLogada = dados.PessoaLogada;
if (usuario.PessoaLogada != null)
usuario.Acesso = "Restrito";
else
usuario.Acesso = "Full";
HttpContext.Current.Session["usuarioLogado"] = usuario;
}
else
{
HttpContext.Current.Session["usuario"] = null;
FormsAuthentication.SignOut();
}
}
}
I would avoid Session, especially when using MVC - it isn't a good fit with the web.
One alternative would be to use IIdentity and set the details in the Application_AuthenticateRequest method.
I am fairly new to c# and am getting an error "Object reference not set to an instance of an object." I am creating an XML packet and sending it to an external device for control. If I put the following code on the form in a click event it works beautifully.
On the btn Click event it looks like this:
SetTestInfoResponse testDataDs = null;
TestInformation testInfo = null;
this.PopulateTestDataXml();
string stringRequestXML = string.Empty;
string stringResponseXML = string.Empty;
//Creates Request packet
stringRequestXML = XMLCommunicationPackets.SetTestInformation (testInfo, testInfo.TestID, testInfo.TestUser, testInfo.TestSampleType, testInfo.TestSampleId, testInfo.TestMethodNumber, testInfo.TestTubeSn, testInfo.TestComments);
//Write set Test Info XML Packet and get response for ack or failure.
stringResponseXML = PluginContext.GetInstance().InstrumentDriverCurrent.GetInstrumentControl().SetCommonParameter(stringRequestXML);
However, If I move my entire function out of the form and try to call it when clicking a button I get the error.
written in a method off the form in a .cs file it reads:
public static SetTestInfoResponse SetTestData()
{
SetTestInfoResponse testDataDs = null;
TestInformation testInfo = null;
string stringRequestXML = string.Empty;
string stringResponseXML = string.Empty;
//Creates Request packet
stringRequestXML = XMLCommunicationPackets.SetTestInformation (testInfo, testInfo.TestID, testInfo.TestUser, testInfo.TestSampleType, testInfo.TestSampleId, testInfo.TestMethodNumber, testInfo.TestTubeSn, testInfo.TestComments);
//Write set Test Info XML Packet and get response for ack or failure.
stringResponseXML = PluginContext.GetInstance().InstrumentDriverCurrent.GetInstrumentControl().SetCommonParameter(stringRequestXML);
The error occurs when building stringRequestXml.
Part of my problem is the PopulateTestData() is a method on the form itself. Its purpose is to take data from txtboxes and cmbboxes and assign them to their respective arguments..
private TestInformation PopulateTestDataXml()
{
TestInformation UiTestData = new TestInformation();
UiTestData.TestID = txtTestId.Text;
UiTestData.TestUser = cmbUsers.SelectedItem.ToString();
UiTestData.TestSampleType = txtSampleType.Text;
UiTestData.TestSampleId = txtSampleId.Text;
UiTestData.TestMethodNumber = Convert.ToInt32(cmbMethod.SelectedItem);
UiTestData.TestTubeSn = txtTubeSerialNum.Text;
UiTestData.TestComments = txtComments.Text;
return UiTestData;
}
Here is the SetTestInformation() method where I am getting the error:
public static string SetTestInformation(TestInformation testInfo, string stringTestId, string stringUser, string stringSampleType, string stringSampleId, int intMethodNumber, string stringTubeSn, string stringComments)
{
try
{
string stringRequestXMLPacket = string.Empty;
string stringType = #"Request";
string stringCommand = #"Set";
string stringArgument = #"TestInformation";
CommunicationPacket requestXMLPacket = new CommunicationPacket(stringRootTag, stringXMLVersion, stringType, stringCommand);
requestXMLPacket.AddCommandArgument(stringArgument);
requestXMLPacket.AddArgumentItem(stringArgument, "sTestId", testInfo.TestID.ToString());
requestXMLPacket.AddArgumentItem(stringArgument, "sUser", testInfo.TestUser.ToString());
requestXMLPacket.AddArgumentItem(stringArgument, "sSampleType", testInfo.TestSampleType.ToString());
requestXMLPacket.AddArgumentItem(stringArgument, "sSampleId", testInfo.TestSampleId.ToString());
requestXMLPacket.AddArgumentItem(stringArgument, "nMethodNumber", testInfo.TestMethodNumber.ToString());
requestXMLPacket.AddArgumentItem(stringArgument, "sTubeSn", testInfo.TestTubeSn.ToString());
requestXMLPacket.AddArgumentItem(stringArgument, "sComments", testInfo.TestComments.ToString());
stringRequestXMLPacket = requestXMLPacket.CreateXMLPacket();
return stringRequestXMLPacket;
}
catch (Exception ex)
{
throw ex;
}
}
Iknow I am having trouble with the variable scope here. I still have to use the method PopulateTestDataXml on the form before I call the setTestData() method. But when I call the Method I have to declare testInfo = null or the parameters for SetTestInformation are not valid ("Does not exist in the current context"). What would I need to pass and how for this to work as a called method on the form btn click? I need to do this as I have alot of deserializing functions written as well to catch error messages in the response xml (these all work fine) and its just too much info on the click event. (And I need to learn).
Thanks
Neither of your examples should work (regardless of where you put them). This is simply incorrect:
TestInformation testInfo = null;
// ...
stringRequestXML = XMLCommunicationPackets.SetTestInformation (testInfo,
testInfo.TestID, ...);
// ^^ BANG!
Your testInfo object is null. When you try and access anything on a null object.. a NullReferenceException is thrown. You need to initialize it first. You're trying to do that in your PopulateTestDataXml method.. which returns the object your after. So change your code to this:
TestInformation testInfo = PopulateTestDataXml(); // assign it
Here is your problem..
public static SetTestInfoResponse SetTestData()
{
SetTestInfoResponse testDataDs = null;
TestInformation testInfo = null;
string stringRequestXML = string.Empty;
string stringResponseXML = string.Empty;
//Creates Request packet
stringRequestXML = XMLCommunicationPackets.SetTestInformation (testInfo, testInfo.TestID, testInfo.TestUser, testInfo.TestSampleType, testInfo.TestSampleId, testInfo.TestMethodNumber, testInfo.TestTubeSn, testInfo.TestComments);
//Write set Test Info XML Packet and get response for ack or failure.
stringResponseXML = PluginContext.GetInstance().InstrumentDriverCurrent.GetInstrumentControl().SetCommonParameter(stringRequestXML);
Are you assigning values for these objects I see they are just declared but never assigned.
SetTestInfoResponse testDataDs = null;
TestInformation testInfo = null;
i don't see you use null objects, so i'm wonder if you set them later, also u said the error happen on
private TestInformation PopulateTestDataXml()
{
TestInformation UiTestData = new TestInformation();
UiTestData.TestID = txtTestId.Text;
UiTestData.TestUser = cmbUsers.SelectedItem.ToString();
UiTestData.TestSampleType = txtSampleType.Text;
UiTestData.TestSampleId = txtSampleId.Text;
UiTestData.TestMethodNumber = Convert.ToInt32(cmbMethod.SelectedItem);
UiTestData.TestTubeSn = txtTubeSerialNum.Text;
UiTestData.TestComments = txtComments.Text;
return UiTestData;
}
after moving it out of your form, which mean possibly it's text box references is broken...
so what you can do, is store a pointer, like in your program.cs where you call your form to show up,
you can create an static object of form, and then put it in your class, then set it in program.cs file like :
Form1 f=new Form();
MyClass.staticFormPointer = f;
and also replace (new Form()), with (f) on the calling method,
your my class is like this:
class MyClass{
public static Form1 staticFormPointer = null;
//your code
.
.
.
// and in your methods you call it like this txtBox1.Text -> staticFormPointer.txtBox1.Text
}
Given the generic handler:
<%# WebHandler Language="C#" Class="autocomp" %>
using System;
using System.Text;
using System.Text.RegularExpressions;
using System.Web;
using System.Web.UI;
public class autocomp : IHttpHandler {
public void ProcessRequest (HttpContext context) {
context.Response.ContentType = "application/json";
context.Response.BufferOutput = true;
var searchTerm = (context.Request.QueryString["name_startsWith"] + "").Trim();
context.Response.Write(searchTerm);
context.Response.Write(DateTime.Now.ToString("s"));
context.Response.Flush();
}
public bool IsReusable {
get {
return false;
}
}
}
How would I server side cache this file for 1 hour based on the name_startsWith query string parameter? With web user controls it's easy:
<%# OutputCache Duration="120" VaryByParam="paramName" %>
But I've been looking around for a while to do the same with a generic handler (ashx) file and can't find any solutions.
With the code you've provided you're telling the end user browser to cache the results for 30 minutes, so you aren't doing any server side caching.
If you want to cache the results server side you're probably looking for HttpRuntime.Cache. This would allow you to insert an item into a cache that is globally available. Then on the page load you would want to check the existence of the cached item, then if the item doesn't exist or is expired in the cache, go to the database and retrieve the objects.
EDIT
With your updated code sample, I found https://stackoverflow.com/a/6234787/254973 which worked in my tests. So in your case you could do:
public class autocomp : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
OutputCachedPage page = new OutputCachedPage(new OutputCacheParameters
{
Duration = 120,
Location = OutputCacheLocation.Server,
VaryByParam = "name_startsWith"
});
page.ProcessRequest(HttpContext.Current);
context.Response.ContentType = "application/json";
context.Response.BufferOutput = true;
var searchTerm = (context.Request.QueryString["name_startsWith"] + "").Trim();
context.Response.Write(searchTerm);
context.Response.Write(DateTime.Now.ToString("s"));
}
public bool IsReusable
{
get
{
return false;
}
}
private sealed class OutputCachedPage : Page
{
private OutputCacheParameters _cacheSettings;
public OutputCachedPage(OutputCacheParameters cacheSettings)
{
// Tracing requires Page IDs to be unique.
ID = Guid.NewGuid().ToString();
_cacheSettings = cacheSettings;
}
protected override void FrameworkInitialize()
{
base.FrameworkInitialize();
InitOutputCache(_cacheSettings);
}
}
}
For multiple query string parameters
public class test : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
OutputCachedPage page = new OutputCachedPage(new OutputCacheParameters
{
Duration = 120,
Location = OutputCacheLocation.Server,
VaryByParam = "name;city"
});
page.ProcessRequest(HttpContext.Current);
context.Response.ContentType = "application/json";
context.Response.BufferOutput = true;
var searchTerm = (context.Request.QueryString["name"] + "").Trim();
var searchTerm2 = (context.Request.QueryString["city"] + "").Trim();
context.Response.Write(searchTerm+" "+searchTerm2+" ");
context.Response.Write(DateTime.Now.ToString("s"));
}
public bool IsReusable
{
get
{
return false;
}
}
private sealed class OutputCachedPage : Page
{
private OutputCacheParameters _cacheSettings;
public OutputCachedPage(OutputCacheParameters cacheSettings)
{
// Tracing requires Page IDs to be unique.
ID = Guid.NewGuid().ToString();
_cacheSettings = cacheSettings;
}
protected override void FrameworkInitialize()
{
base.FrameworkInitialize();
InitOutputCache(_cacheSettings);
}
}
}
IIS does not use Max Age to cache anything as it is not HTTP PROXY.
That is because you are not setting Last Modified Date Time of some dependent file. IIS needs a cache dependency (file dependency, so that it can check the last update time) and compare it with cache. IIS does not work as HTTP Proxy, so it will not cache items for 30 seconds, instead IIS only updates cache based on some sort of date time or some cache variable.
You can add cache dependency two says, File Dependency and Sql Cache Dependency.
How dynamic caching works in IIS, lets say you have an html file. IIS considers a static html text as cachable file and it will gzip it and put cached copy in its cache. If last update time for static html is older then cache time, then it will use cache. If the file was modified, IIS will find that last update time of html is greater then cache time, so it will reset the cache.
For dynamic content, you have to plan your caching accordingly. If you are serving a content based on some row stored in SQL table, then you should keep track of last update time on that row and add cache dependency on IIS along with SQL to query the last update time of item you are trying to cache.
To cache file, such as .js, .css or other you need to put it to the context.cache. Example:
public void ProcessRequest(HttpContext context)
{
var cachedResult = context.Cache.Get(context.Request.Path);
if (cachedResult != null && cachedResult.GetType() == typeof(VueFileRequestResult))
{
RequestedFileResponce(context, cachedResult as VueFileRequestResult);
return;
}
// SOME ACTIONS WITH NON-CACHED FILE
var fileContent = System.IO.File.ReadAllBytes(filePath);
var result = new VueFileRequestResult(contentType.GetDescription(), fileContent);
RequestedFileResponce(context, result);
var expirationDate = DateTime.Now.AddYears(1);
var dependency = new CacheDependency(filePath);
context.Cache.Add(context.Request.Path, result, dependency, expirationDate, TimeSpan.Zero, CacheItemPriority.Low, null);
return;
}