In my ASP.net MVC application, I've got several views that I'd like to set to save in the browser's cache. I've got the methods built to do it, but here's my issue.
The menu in my site is different between logged in and logged off visitors. If the logged in page is cached, then even when the user logs off the menu remains in the logged in mode. It's actually not, but on that visitor's browser it is.
How can I go about clearing/expiring that cache so the visitor's browser updates when I need it to, yet still be able to make use of browser cache?
Thanks in advance!
For HTML pages it's difficult. I turned off client caching for that same reason, and tried to make the server caching as efficient as possible. I now use OutputCache with VaryByCustom set to the login status.
We ran some load tests on that system and the only bottleneck is the bandwidth that this generates.
And on a side note: I used donut-caching for the login status. But I was not able to get it to work with dynamic compression (to reduce the bandwidth bottleneck mentioned above)
See also this question
You can do it with an AutoRefresh attribute on your action method. Here are some examples:
[AutoRefresh(ControllerName = "Home", ActionName = "About", DurationInSeconds = 10)]
public ActionResult Index1()
{
}
AutoRefresh(ActionName = "About", DurationInSeconds = 15)]
public ActionResult Index2()
{
}
[AutoRefresh(RouteName = "ByFavoriteRoute", DurationInSeconds = 30)]
public ActionResult Index3()
{
}
[AutoRefresh(DurationInSeconds = 45)]
public ActionResult Index4()
{
}
Related
I'm trying to redirect page on previous page when i click on currency menu. In this menu set selected currency in cookies and redirect to Request.UrlReferrer.ToString() so Request page automatic read cookies and apply currency.
Here is my code
public ActionResult Index(string currency)
{
HttpCookie cookie = new HttpCookie("Cookie");
cookie.Values["CODE"] = currency;
cookie.Values["sym"] = Currencies[currency];
cookie.Values["Name"] = CurrenciesName[currency];
string currencyname = GetCurrencySymbol(currency);
this.ControllerContext.HttpContext.Response.Cookies.Add(cookie);
return Redirect(Request.UrlReferrer.ToString());
//return RedirectToRoute(Request.UrlReferrer.ToString());
}`
for example page1 have some item with amount in USD now user change currency then i send request to CurrencyController with above Action then return to same page1.
Above code working fine in all browsers but not working in IE 11.
give me some idea where I'm doing wrong.
Thanks
First and foremost, you should never rely on UrlReferrer. Its value comes from an HTTP header that is not guaranteed to be sent, and even if it is sent, it can be tampered with. By using it in the way you are, you're opening yourself up to CSRF and man-in-middle attacks.
The correct way to do something like this is to pass along the URL you want to return to. For example, if a user is on a URL like /foo/ and then clicks a link where you want to redirect them back to /foo/ afterwards, then the URL of the link should be something like: /bar/?returnUrl=/foo/.
Then, the action responding to /bar/ would do something like:
public ActionResult Bar(string returnUrl)
{
// do something
if (Url.IsLocalUrl(returnUrl))
{
return Redirect(returnUrl);
}
// redirect to default
}
The Url.IsLocalUrl check is to make sure that the return URL is a path on the current site, again, to prevent malicious attacks.
how can I set about c # MVC viewing files with absolute path (eg. www.mysite.it/namefile.pdf) only for authenticated users ? for authentication use the method FormsAuthentication.Authenticate(). thanks for the support.
I think that the more properly way to do that is:
www.mysite.it/f={filename}
And in your controller you use the [Authorize] to check if user is authenticated. If the user is authenticated you allow him to view, or download, the file.
The following code can help you to understand:
//Ensure that the user is authenticated
[Authorize]
public class HomeController : Controller
{
string DefaultFileFolder = "C:/Files";
public ActionResult Index(string f)
{
//File request
if (!String.IsNullOrWhiteSpace(f))
{
var filePath = System.IO.Path.Combine(DefaultFileFolder, f);
var mimeType = "text/plain";
return File(filePath, mimeType);
}
return View();
}
}
As far as I know the only way to do this is to route requests for static content through ASP.NET. Normally you don't do this as IIS by itself is far more efficient at serving these types of resources.
From this excellent article, you can force static content requests to go through ASP.NET by:
On IIS 7 this is done either by setting
runAllManagedModulesForAllRequests=”true” or removing the
"managedHandler" preCondition for the UrlRoutingModule.
Depending on your needs, you may wish to do something more in line with what Richard suggested. Something like this perhaps?
i want to cache my page and use this type of caching
[OutputCache(Duration = 21600, VaryByParam = "none")]
public ActionResult Index()
{
//some codes
return View();
}
but i 'm confused this type of cache will stored on IIS or on client browser?
how can i cache my page on user browser not on the server?
Default asp.net cache pages everywhere it can (server, proxy, client). You can change this by attribute
[Output(Location=OutputCacheLocation.Any)]
You can set the Location property to any one of the following values:
OutputCacheLocation·Any
OutputCacheLocation·Client
OutputCacheLocation.Downstream
OutputCacheLocation.Server
OutputCacheLocation.None
OutputCacheLocation.ServerAndClient
I started using OutputCache for my website.
The problem that I encounter is that when a user update an item I need to reset the cache for that item.
I did that using:
var urlToRemove = Url.Action("Details", "Dress", new {id = model.Id});
Response.RemoveOutputCacheItem(urlToRemove);
In Edit action I also set to TempData the update success message and I display it on the next request. The problem is that the message remains in the cached response.
Do you know how can I avoid caching in an action. Something like:
[OutputCache(Duration = 3600, VaryByParam = "id")]
public ViewResult Details(int id)
{
if(NotificationHelper.HasNotifications)
Response.DoNotCache();
.....
I cannot use the same trick ... because the page is added to the cache after its rendered. So I cannot exclude an action from cache in its body.
What you are describing is sometimes referred as "Donut Hole Caching" because you want to cache everything except some bit of dynamic content in the middle.
Here is are a couple resources you might want to look at:
http://www.devtrends.co.uk/blog/donut-output-caching-in-asp.net-mvc-3
https://github.com/janjongboom/Moth/wiki/Server-side-caching
I don't know if there is an easy way to do what you are asking. However, my experience with messages and OutputCache is don't put them in the response. I ended up making sure there were no messages that are ever displayed on a cached page. If I absolutely had to have a message on a cached page I would set up an ajax call that would grab the messages once the response reached the client.
what about this?
class CustomOutputCacheAttribute : OutputCacheAttribute
{
public override void OnActionExecuted(ActionExecutedContext filterContext)
{
if (filterContext.HttpContext.Response.StatusCode >= 400)
{
this.Location = System.Web.UI.OutputCacheLocation.None;
this.Duration = -1;
}
filterContext.HttpContext.Response.Cache.SetOmitVaryStar(true);
base.OnActionExecuted(filterContext);
}
}
I am storing user objects in session, pulling them out in the controllers, and sometimes write some data into them. but when to users post at the same time, the sessions get mixed fro some reason.
Does anyone have any idea how that is possible ?
typical post:
[HttpPost]
public ActionResult Index(QuestionModel model, FormCollection collection)
{
var person = ((Person)Session["Person"]);
if (!ModelState.IsValid)
{
ModelState.Clear();
ModelState.AddModelError("", Global.Global.error);
return View(new QuestionModel(person.page, (CultureInfo)Session["culture"]));
}
person.page = model.Page;
while (person.Answers.Count > model.Page - 1)
{
person.Answers.RemoveAt(person.Answers.Count - 1);
}
var answer = new Answer() { answer = model.ChosenAnswer, Question = "Q" + person.page };
person.Answers.Add(answer);
if (!CheckForNextPage(person.page)) { person.hasFinishedQuestions = true; return RedirectToRoute("Result"); }
person.page++;
return View(new QuestionModel(person.page, (CultureInfo)Session["culture"]));
}
I echo the session id on every page, and when a couple of users are using the website they get each others session + sessionid ...
#update: 3 experienced developers have been looking for the problem for 2 days, still no solution. already removed about 95% off the code, still same issue. server posts back responses from another session
This is not possible.
So this is my guess:
You are testing this wrongly, you are using different tabs from the same browser.
Some people don't know that this doesn't create a different session.
Try testing this on 2 different browsers (i.e. firefox and chrome) as they will not share the session (as the session id is normally stored in a cookie).
Please report back if this was the case.
We "solved" it. We didn't actually solve it, but we copied all the sources to a new project, recompiled, and everything worked. Untill this day, we still don't know why, and how that error happened ...