简体   繁体   English

要缓存还是不缓存? 以及如何在asp.net mvc的基础控制器上缓存它?

[英]To Cache or not to cache? And how to cache it on a base controller in asp.net mvc?

I am making my own base controller since I want to pass some data to a master page. 我正在制作自己的基本控制器,因为我想将一些数据传递给母版页。 Now since this is like adding this code to every view in that controller it gets run every time. 现在,因为这就像将此代码添加到该控制器中的每个视图一样,它每次都会运行。

By the time it loads up the first time I think it has hit my code at least twice. 当它第一次加载时,我认为它已经至少击中了我的代码两次。 So I was thinking about caching it. 所以我在考虑缓存它。 But in my book it says don't cache private data since everyone will see it. 但在我的书中它表示不会缓存私人数据,因为每个人都会看到它。

So I am not sure what to do. 所以我不知道该怎么做。

What my couple lines of code does is this. 我的几行代码是做什么的。

  1. Finds the user name and displays it to the user. 查找用户名并将其显示给用户。
  2. Find the users plan and displays that. 找到用户计划并显示该计划。

So I need the userName to find out what their GUID so I can find out what plan they signed up for. 所以我需要userName来找出他们的GUID,以便我可以找出他们注册的计划。

So I don't know how to cache it but not expose it to everyone. 所以我不知道如何缓存它,但不将它暴露给每个人。 Is there away to make it cache just for this user? 有没有让它为这个用户缓存?

Quote Asp.net mvc framework unleasehd pg 330 引用Asp.net mvc框架unleasehd pg 330

Don't Cache Private Data 不要缓存私人数据

Caching a page that contains private user data is extremely dangerous. 缓存包含私有用户数据的页面非常危险。 When a page is cached on the server, the same page is served to all users. 当页面缓存在服务器上时,同一页面将提供给所有用户。 So, if you cache a page that displays a user credit card number, everyone can see the credit card number (not good!). 因此,如果您缓存显示用户信用卡号的页面,则每个人都可以看到信用卡号(不好!)。

The same page is cached for all users even when you require authorization. 即使您需要授权,也会为所有用户缓存相同的页面。 Imagine, for example, that you create a financial services website and the website includes a page that displays all a user's investments. 例如,想象一下,您创建了一个金融服务网站,该网站包含一个显示所有用户投资的页面。 The page displays the amount of money that a user has invested in a set of stocks, bonds, and mutual funds. 该页面显示用户在一组股票,债券和共同基金中投入的金额。

Because this information is private, you require the user to log in before seeing the page. 由于此信息是私有的,因此您需要用户在查看页面之前登录。 In other words, each user must be authorized before the user can view the page. 换句话说,在用户可以查看页面之前,必须授权每个用户。

To improve the performance of the financial services page, you decide to enable caching for the page. 要提高金融服务页面的性能,您决定为页面启用缓存。 You add the OutputCache attribute to the controller action that returns the page. 您将OutputCache属性添加到返回页面的控制器操作。

Don't do that! 不要那样做! If you cache the controller action that returns the financial services pages, the private financial data for the first person to request the page will be shared among every subsequent visitor to the application. 如果您缓存返回金融服务页面的控制器操作,则第一个请求页面的人员的私有财务数据将在应用程序的每个后续访问者之间共享。

In general, adding the OutputCache and Authorize attribute to the same controller action opens a security hole. 通常,将OutputCache和Authorize属性添加到同一个控制器操作会打开一个安全漏洞。 Avoid doing this: 避免这样做:

The best way to answer whether you should cache something or not is the determine if it's actually impacting the performance of your site. 回答是否应缓存某些内容的最佳方法是确定它是否实际影响了您网站的性能。 With actual metrics. 使用实际指标。 Don't guess. 不要猜。 If it's not hurting anything and everything seems responsive, then I would say work on something else until the need arises. 如果它没有伤害任何东西,而且一切看起来都很敏感,那么我会说在其他方面工作直到需要出现。 "Permature optimization is the root of all evil" has been said a time or two :) “过早优化是所有邪恶的根源”已经说过一两次了:)

If you do choose to cache data, I'm unsure what you mean that everyone will be allowed to see it? 如果您确实选择缓存数据,我不确定您的意思是每个人都可以看到它? If you mean the ASP.NET Caching framework ( HttpContext.Current.Cache ) then this lives in your server memory and is completely volatile (it would be wiped out at any time if memory pressure hits it). 如果您的意思是ASP.NET缓存框架( HttpContext.Current.Cache ),那么它将存在于您的服务器内存中并且完全不稳定(如果内存压力达到它,它将随时被删除)。 So make sure you keep that in mind and always check for null. 因此,请务必记住这一点并始终检查是否为空。 To use it, you can simply use Cache.Insert() and it has a couple overloads to customize your caching preferences. 要使用它,您可以简单地使用Cache.Insert() ,它有一些重载来自定义您的缓存首选项。

Now if you are talking about caching something with browser cookies that is another story. 现在,如果您正在谈论使用浏览器cookie缓存某些内容,这是另一个故事。 Cookies are indeed stored in the browser, and unless you specify HttpOnly for the cookie, it can be read via javascript (which is only a problem if you have an XSS vulnerability somewhere -- because a malicious user can use javascript to "phone-home" users' private cookie data.) So don't put anything private into a cookie unless absolutely necessary, and if you do, you should specify HttpOnly and take appropriate steps to protect your users. Cookie确实存储在浏览器中,除非你为cookie指定HttpOnly,它可以通过javascript读取(如果你有某个XSS漏洞,这只是一个问题 - 因为恶意用户可以使用javascript来“回家” “用户的私人cookie数据。”因此,除非绝对必要,否则不要将任何内容私有放入cookie中,如果这样做,则应指定HttpOnly并采取适当措施保护您的用户。

You should definitely read more about XSS and other common HTTP security issues if security is a big concern for you. 如果安全性是您最关心的问题,那么您肯定应该阅读有关XSS和其他常见HTTP安全问题的更多信息。 (And it should be :) (它应该是:)

UPDATED to address the question edit regarding Output Caching: 更新以解决有关输出缓存的问题编辑:

Ok so you were specifically referring to Output Caching. 好的,所以你专门提到了输出缓存。 Indeed that book mentions a security hole that I believe was patched before MVC 1 was released. 事实上,这本书提到了一个安全漏洞, 我认为在MVC 1发布之前已经修补了这个漏洞。 The Authorize attribute should be smart enough to correctly handle Output Cacheing when these 2 attributes are used in conjunction. 当这两个属性结合使用时,Authorize属性应足够智能以正确处理输出缓存。 Perhaps that book was written during a preview release and is no longer relevant. 也许这本书是在预览版中编写的,不再相关。

I am quoting the following from Steve Sanderson (author of Pro ASP.NET MVC Framework) 我引用了Steve Sanderson(Pro ASP.NET MVC框架的作者)的以下内容

Update: Since the Beta release, the [Authorize] filter now does some clever trickery to co-operate with ASP.NET output caching. 更新:自Beta版本发布以来,[Authorize]过滤器现在可以使用一些聪明的技巧来与ASP.NET输出缓存协作。 Specifically, it registers a delegate using HttpCachePolicy.AddValidationCallback(), so that it can intercept future cache hits and tell ASP.NET output caching not to use the cache when [Authorize] would reject the request. 具体来说,它使用HttpCachePolicy.AddValidationCallback()注册一个委托,以便它可以拦截未来的缓存命中并告诉ASP.NET输出缓存在[Authorize]拒绝请求时不使用缓存。 This solves the problem of ASP.NET output caching bypassing the [Authorize] filter. 这解决了绕过[Authorize]过滤器的ASP.NET输出缓存问题。 If you're going to write your own authorization filter, be sure to derive it from AuthorizeAttribute so you can inherit this useful behaviour. 如果您要编写自己的授权过滤器,请务必从AuthorizeAttribute派生它,以便继承此有用的行为。

Note that this doesn't stop ASP.NET output caching from bypassing any of your other action filters, and it doesn't add any support for partial caching. 请注意,这不会阻止ASP.NET输出缓存绕过任何其他操作筛选器,并且它不会为部分缓存添加任何支持。 If that's a problem for you then consider using [ActionOutputCache] (below) instead. 如果这对您来说是个问题,那么请考虑使用[ActionOutputCache](下面)。

It would be worthwhile to read his article (and his book, for that matter): http://blog.codeville.net/2008/10/15/partial-output-caching-in-aspnet-mvc/ 阅读他的文章(和他的书,就此而言)是值得的: http//blog.codeville.net/2008/10/15/partial-output-caching-in-aspnet-mvc/

Your Controller classes only have a life cycle that stretches from action-request to view-rendered. 您的Controller类只有一个从action-request延伸到view-rendered的生命周期。 Do you really need to cache that data ? 你真的需要缓存这些数据吗? Just expose the data in your Model object. 只需公开Model对象中的数据即可。 The queries don't sound complex enough and on top of that most RDBMS vendors tend to do a lot of query caching themselves. 查询听起来不够复杂,而且大多数RDBMS供应商倾向于自己进行大量的查询缓存。

HTTP is a stateless protocol meaning that after a request your web server forgets everything about said request. HTTP是一种无状态协议,这意味着在请求之后,您的Web服务器会忘记所述请求的所有内容。 To circumvent this statelessness asp.net offers the Application and Session objects. 为了规避这种无状态,asp.net提供了Application和Session对象。 Application is globally available to all requests and Session is bound to a single IP. 应用程序全局可用于所有请求,并且会话绑定到单个IP。 Putting any data in there is usually a last resort though or part of schemes to cache data that truly have a heavy load time. 将任何数据放在那里通常是最后的手段或部分方案来缓存真正具有大量加载时间的数据。

The flow in ASP.NET MVC is roughly ASP.NET MVC中的流程大致如此

  • URL is requested 请求URL
  • Controller is called 控制器被调用
  • Action is called 行动被召唤
  • Action calls Model for data (username/userplan) 动作调用数据模型(用户名/用户计划)
  • Action sets the data in the viewmodel Action在viewmodel中设置数据
  • Action calls the desired view with the data in the viewmodel Action使用viewmodel中的数据调用所需的视图
  • View is rendered. 视图已呈现。

Setting the data on the viewmodel is already 'private' so I am not sure where the need for caching comes from. 在viewmodel上设置数据已经是“私有的”,所以我不确定缓存需求来自何处。 Perhaps I am misunderstanding the question ? 也许我误解了这个问题?

Edit 编辑

Ok first forgive me if my post was a bit presumptuous. 好的,首先请原谅我,如果我的帖子有点冒昧。 I do think your code doesn't have to go in the constructor of your base constructor at all. 我认为你的代码根本不需要进入基础构造函数的构造函数。 You don't pass your controller to the view after all. 毕竟,您不会将控制器传递给视图。

A good practice is to pass in typed ViewModels. 一个好的做法是传入类型化的ViewModel。 Say this is your definition in your site.master 说这是您在site.master中的定义

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<MyNS.BaseViewDataModel>" %>

And this the definition of say your Help page View: 这个定义说你的帮助页面查看:

<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<MyNS.HelpViewDataModel>" %>

You can then create a BaseViewDataModel 然后,您可以创建BaseViewDataModel

namespace MyNS
{
    public class BaseViewDataModel

And your HelpViewDataModel 和你的HelpViewDataModel

namespace MyNS
{
    public class HelpViewDataModel : BaseViewDataModel 
    {

Then in your help controller's appropiate action 然后在你的帮助控制器的适当行动

[AcceptVerbs(HttpVerbs.Get)]
public ActionResult Index()
{
    var viewDataModel = new HelpViewDataModel ();
            viewDataModel.HelpText = "something";
            ..
            ..
    return View(viewDataModel);
}

You can now instantiate your user guid and user plan in BaseViewDataModel's constructor and it will only be called for actions that actually instantiate a BaseViewDataModel subclass. 您现在可以在BaseViewDataModel的构造函数中实例化您的用户指南和用户计划,并且只会为实际实例化BaseViewDataModel子类的操作调用它。

And your views are type safe which is huge productivity gain since we typed the views we can now actually call 而且您的视图是类型安全的,因为我们输入了我们现在可以实际调用的视图,因此可以大幅提高生产力

<%= this.Model.HelpText %>

In the Help's View. 在帮助视图中。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM