Why is the HttpContext.Cache count always zero? - asp.net-mvc

I set up a few pages with OutputCache profiles and confirmed that they are being cached by using multiple browsers and requests to retrieve the page with a timestamp which matched across all requests. When I try to enumerate the HttpContect.Cache it is always empty.
Any ideas what is going on here or where I should be going for this information instead?
Update:
It's not client cache because multiple browsers are seeing the same response. Here is a bit of code to explain what's happening.
Web.Config caching settings
<system.web>
<caching>
<outputCacheSettings>
<outputCacheProfiles>
<clear/>
<add name="StaticContent" duration="1200" varyByParam="none"/>
<add name="VaryByParam" duration="1200" varyByParam="*"/>
</outputCacheProfiles>
</outputCacheSettings>
</caching>
...
</system.web>
**Action Method With Caching
[OutputCache(CacheProfile = "StaticContent")]
public ActionResult Index()
{
return View(new CollaborateModel());
}
Code to enumerate the cache, yep it's rough, an this is defined in a controller action method
var sb = new StringBuilder();
foreach (KeyValuePair<string, object> item in HttpContext.Cache)
{
sb.AppendFormat("{0} : {1}<br />", item.Key, item.Value.ToString());
}
ViewData.Add("CacheContents", sb.ToString());
The HttpContext.Cache is where the count is always null, even though the cache seems to be working fine.

That's probably because the page has been cached downstream on the client browser and not on the server.

Instead of using the HttpCache I ended up rolling my own caching model for holding datasets in my Data Access layer. If I was looking up the AD profile of a given username and converting it to a DTO then I just put that profile in a rolling collection of profile DTOs that I would check before polling AD for the information.

Related

Runtime Error using Redis Cache Session State Provider

So I have an MVC application in which I am trying to use Azure's Redis Cache for my Session State Provider. With everything coded and configured and all, when I publish it, the index page loads fine. The only button to hit is 'Next', which is supposed to add a session state variable with a value, and then move on to the appropriate page. But when I click 'Next' I get a runtime error. If I simply comment out the sessionState block in Web.config and publish it like that, I can move on to the 'next' page just fine. So I'm wondering what is wrong with my use of the provider and why it's not working?
Web.Config block:
<system.web>
<compilation debug="false" targetFramework="4.5.2" />
<httpRuntime targetFramework="4.5.2" />
<sessionState mode="Custom" customProvider="MySessionStateStore">
<providers>
<add
type="Microsoft.Web.Redis.RedisSessionStateProvider"
name="MySessionStateStore"
host = "[Host name from Azure]"
port = "[Port # from Azure]"
accessKey = "[Key from Azure]"
ssl = "false"
throwOnError = "true"
retryTimeoutInMilliseconds = "5000"
databaseId = "0"
applicationName = ""
connectionTimeoutInMilliseconds = "5000"
operationTimeoutInMilliseconds = "1000"
/>
</providers>
</sessionState>
</system.web>
POST function when I hit the 'Next' button:
<HttpPost()>
<ValidateAntiForgeryToken()>
Async Function Index(ByVal obj As Type) As Task(Of ActionResult)
If ModelState.IsValid Then
Session("VarName") = obj
Return RedirectToAction("nextPage", "[controller]")
End If
Return View()
End Function
Note I am not using any cookies, nor am I trying to use the Redis Cache for anything else. The non-SSL port IS Enabled in Azure (yes, bad, I know - that will change).
I hope that's enough to go on to be able to help - if not, let me know. Thank you!
OK, well, figures that after posting this I'd find the answer!
So there is this very small note at the bottom of one of the articles I could find on Redis Session State Provider: https://msdn.microsoft.com/en-us/library/azure/dn690522.aspx
"Note that data stored in the cache must be serializable, unlike the data that can be stored in the default in-memory ASP.NET Session State Provider. When the Session State Provider for Redis is used, be sure that the data types that are being stored in session state are serializable."
The Type that I was trying to put into the session variable was a custom type. I had to add the "Serializable" attribute to my class!
Once I published it as serializable, then voila!

MVC Blank JsonResult

I'm returning a JsonResult as part of an Orchard CMS Site (MVC 4) and it suddenly stopped working (specifics below).
Here is an example from my controller:
public JsonResult GetStartDate()
{
//a previous version of this question was different here
var startDate = _Settings.DateOpen.GetValueOrDefault(DateTime.MaxValue);
if (startDate < DateTime.Now)
startDate = DateTime.Now;
var start = new
{
year = startDate.Time.Year,
month = (startDate.Time.Month - 1)
};
return Json(start, JsonRequestBehavior.AllowGet);
}
It should be returning actual data. I have verified that the action is being hit and that "start" contains the correct data before being passed into the Json method.
If I navigate directly to the URL, I get a blank white screen.
Inspecting the result of an AJAX request shows that the call fails, the response body is an empty string , the status is "parsererror" and the actual error throws is "SyntaxError: Unexpected end of input."
POST requests work for some reason, this issue only applies to GETs.
This problem is with all JSON GETs, not just any specific method.
What could be affecting the data between the Json method and the client receiving the response?
By default all MVC methods are cached. This can lead to issues during the change/debug cycle. For starters you can turn off caching during development using the decorator below.
[OutputCache(NoStore = true, Duration = 0)]
public ActionResult MyMethod()
You may want to wrap all methods with a caching scheme that is defined in the web.config. This allows caching to be controlled via one configuration change which comes in handy during development.
<system.web>
<caching>
<outputCacheSettings>
<outputCacheProfiles>
<clear />
<add varyByParam="*" duration="0" name="MyCachePlan" />
</outputCacheProfiles>
</outputCacheSettings>
</caching>
</system.web>
And use the following decorator:
[OutputCache(CacheProfile = "MyCachePlan")]
public ActionResult MyMethod()

DonutOutputCache not working for an image

I have an ASP.NET MVC controller action like the following:
[HttpGet]
[DonutOutputCache(CacheProfile = "banner")]
public async Task<ActionResult> Banner(string name, string size = "lg")
{
// snipped - work out which banner to show today.
return File(thePathToSomeBannerImageFile, "image/jpeg");
}
And the configuration file looks like:
<caching>
<outputCacheSettings>
<outputCacheProfiles>
...
<add name="banner" duration="31536000" varyByParam="*" />
...
</outputCacheProfiles>
</outputCacheSettings>
</caching>
Since adding DonutOutputCache the image that I used to render to my browser now won't load. I can see in the Fiddler trace that a largish binary file is getting to the browser, but I can't seem to get it to render.
Removing the DonutOutputCache makes the image appear again.
I've tried clearing the cache etc. Any ideas?
Ah, just figured it out from this link: Doesn't work w/ Files?.
Basically DonutOutputCache uses ContentResult internally which works only with text-based content. Since I'm returning a binary response in a FileResult it messes stuff up. Fortunately it works side-by-side with the built in OutputCache, so I could modify my action as follows and it works as expected. I really only needed DonutOutputCache for other bits of my site that are text-based. I tripped myself up trying to just have one caching attribute to rule them all.
[HttpGet]
[OutputCache(CacheProfile = "banner")]
public async Task<ActionResult> Banner(string name, string size = "lg")
{
}

Can not set Session variables in MVC 3

I know that my question is basic one yet i need some responses because i have tried many solutions on the net and i still get the some error.
I have a gridPanel in the first view. If i click a button in this view, the selected rows will be displayed in another view. I need to send information with these rows to the server so i can load some extra data in the action proper to the click button.
To perform that, i should use Session instead of TempData or ViewBag/ViewData because i don't know when the user will click the button. Please correct me if i'm mistaken.
My code is like that: In the client side with AJAX i call an action method to set the session variables:
Ext.Ajax.request({ url: 'Examples/SetSelectedStations', params: { selectedStations: stationsStr} });
in the SetSelectedStations controller i realised that Session["slectedStations"] is always null and acts like have never been set. this is my controller action:
public ViewResult SetSelectedStations(string selectedStations)
{
Session["slectedStations"] = selectedStations;
string ss = Session["slectedStations"] as string;
// Here ss is null !!!!!!
return View();
}
Should i define Session["slectedStations"] in other place? Is there a special configuration in the web.confg file?
Please notice that the sessionState in my web.config is like that:
<sessionState mode="Custom" customProvider="PgSessionStateStoreProvider">
<providers>
<clear />
<add name="PgSessionStateStoreProvider" type="NauckIT.PostgreSQLProvider.PgSessionStateStoreProvider" enableExpiredSessionAutoDeletion="true" expiredSessionAutoDeletionInterval="1800000" enableSessionExpireCallback="false" connectionStringName="AspSQLProvider" applicationName="WebSite1" />
</providers>
</sessionState>

MVC RedirectToAction calls Session_Start() in global.asax

I am calling RedirectToAction method to call action method from another controller but it clears all session data
I debugged in global.asax and found out that when ever i call RedirectToAction it calls Session_Start() method.
I don't know how session start is called.
Here is my web config code for form and session tag
for session tag
<sessionState mode="InProc" customProvider="DefaultSessionProvider">
<providers>
<add name="DefaultSessionProvider" type="System.Web.Providers.DefaultSessionStateProvider, System.Web.Providers, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" connectionStringName="DefaultConnection" />
</providers>
</sessionState>
and for form tag
<authentication mode="Forms">
<forms loginUrl="~/ControllerName/ActionName" timeout="2880" />
</authentication>
this "~/ControllerName/ActionName" is same method from wher i am calling "RedirecToAction"
just for info what i am trying is if i found cookies for user he will be redirected to home page from login page directly
both action methods are in different controller and in different Areas.
here is code which uses "RedirecToAction" method
public class LoginController : Controller{
public ActionResult Index()
{
if (Request.Cookies["UserName"] != null && Request.Cookies["Password"] != null)
{
FillLoginSession();//Fills Session with user data ex. Session["User_Id"] = 1;
return RedirectToAction("Index", "Home", new { area = "Home" });
}
}}
and here is action method in another controller to which i am redirecting.
public class HomeController : Controller{
public ActionResult Index()
{
return View();
}}
ok i got solution to this problem.
i was calling this
Response.Cookies.Add(new HttpCookie("ASP.NET_SessionId", ""));
before initializing session from my method.
In my IIS this key "ASP.NET_SessionId" was used to store session in cookies.
as it was cleared it reinitialize everything when ever I redirect to new page.
Forms Authentication and Session State are 2 different and unrelated things.
Although you haven't shown the method that calls RedirectToAction, I suspect that you are not storing anything in session state beforehand. If you don't actually store something in Session State, you will get a new session on every request..
When using cookie-based session state, ASP.NET does not allocate storage for session data until the Session object is used. As a result, a new session ID is generated for each page request until the session object is accessed. If your application requires a static session ID for the entire session, you can either implement the Session_Start method in the application's Global.asax file and store data in the Session object to fix the session ID, or you can use code in another part of your application to explicitly store data in the Session object.
So to reiterate, to eliminate the call to Session_Start, you need to put something in session state before redirecting.
Session["TheKey"] = "TheValue";
return RedirectToAction("TheAction");

Resources