ASP.NET MVC - 控制器之间共享会话状态 [英] ASP.NET MVC - Sharing Session State Between Controllers

查看:156
本文介绍了ASP.NET MVC - 控制器之间共享会话状态的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我仍然不太熟悉反转控制(尽管我现在正在学习),所以如果这是我的问题的解决方案,只需让我知道,我会回到了解它。

I am still mostly unfamiliar with Inversion of Control (although I am learning about it now) so if that is the solution to my question, just let me know and I'll get back to learning about it.

我有一对控制器需要一个Session变量,自然没有什么特别的事情发生,因为Session如何工作在第一位,但这让我想知道什么最干净的方式在两个独立的控制器之间共享相关对象是。在我的具体情况下,我有一个UploadController和一个ProductController,它们可以相互配合来上传图像文件。当文件由UploadController上传时,有关上传的数据将存储在会话中。发生这种情况之后,我需要访问ProductController中的Session数据。如果我为Session变量创建一个get / set属性,其中包含两个控制器中的上传信息,我可以访问这些数据,但是同时我会违反各种DRY,更不用说创建一个最好是混淆设计,其中一个对象被两个完全断开的对象共享和修改。

I have a pair of controllers which need to a Session variable, naturally nothing too special has happen because of how Session works in the first place, but this got me wondering what the cleanest way to share related objects between two separate controllers is. In my specific scenario I have an UploadController and a ProductController which work in conjunction with one another to upload image files. As files are uploaded by the UploadController, data about the upload is stored in the Session. After this happens I need to access that Session data in the ProductController. If I create a get/set property for the Session variable containing my upload information in both controllers I'll be able to access that data, but at the same time I'll be violating all sorts of DRY, not to mention creating a, at best, confusing design where an object is shared and modified by two completely disconnected objects.

你建议什么?

确切的上下文:

文件上传查看将文件发布到UploadController.ImageWithpreview(),然后读取已发布的文件,并将其复制到临时目录。保存文件后,另一个类生成上传图像的缩略图。然后,将原始文件和生成的缩略图的路径返回,并使用JsonResult返回到javascript回调,该回调可以更新页面上可以为已保存或已取消的表单中的某些动态内容。无论上传的图像是保存还是被跳过,我需要从临时目录中移动或删除它们和生成的缩略图。为了方便这一点,UploadController在会话维护的队列对象中跟踪所有上传文件及其缩略图。

A file upload View posts a file to UploadController.ImageWithpreview(), which then reads in the posted file and copies it to a temporary directory. After saving the file, another class produces a thumbnail of the uploaded image. The path to both the original file and the generated thumbnail are then returned with a JsonResult to a javascript callback which updates some dynamic content in a form on the page which can be "Saved" or "Cancelled". Whether the uploaded image is saved or it is skipped, I need to either move or delete both it and the generated thumbnail from the temporary directory. To facilitate this, UploadController keeps track of all of the upload files and their thumbnails in a Session-maintained Queue object.

返回到视图:在表单填充已生成的上传图像的缩略图后,该表单发回到ProductsController,其中标识所选文件(目前我将文件名存储在一个隐藏的字段中,我意识到这是一个可怕的漏洞),然后从temp目录复制到一个永久的位置。理想情况下,我想简单地访问我在会话中存储的队列,以便窗体不需要像现在那样包含图像位置。这是我如何设想我的解决方案,但我会热切听任何意见或批评。

Back in the View: after the form is populated with a generated thumbnail of the image that was uploaded, the form posts back to the ProductsController where the selected file is identified (currently I store the filename in a Hidden field, which I realize is a horrible vulnerability), and then copied out of the temp directory to a permanent location. Ideally, I would like to simply access the Queue I have stored in the Session so that the form does not need to contain the image location as it does now. This is how I have envisioned my solution, but I'll eagerly listen to any comments or criticisms.

推荐答案

几个解决方案浮现在脑海中。您可以使用映射到请求中的SessionState类,并获取/设置信息(我从内存中执行此操作,因此这不太可能进行编译,这意味着要传达这一点):

A couple of solutions come to mind. You could use a "SessionState" class that maps into the request and gets/sets the info as such (I'm doing this from memory so this is unlikely to compile and is meant to convey the point):

internal class SessionState
{
  string ImageName
  {
    get { return HttpContext.Current.Session["ImageName"]; }
    set { HttpContext.Current.Session["ImageName"] = value; }
  }
}

然后从控制器执行以下操作:

And then from the controller, do something like:

  var sessionState = new SessionState();
  sessionState.ImageName = "xyz";
  /* Or */
  var imageName = sessionState.ImageName;

或者,您可以创建一个控制器扩展方法:

Alternatively, you could create a controller extension method:

public static class SessionControllerExtensions
{
  public static string GetImageName(this IController controller)
  {
    return HttpContext.Current.Session["ImageName"];
  }

  public static string SetImageName(this IController controller, string imageName)
  {
    HttpContext.Current.Session["ImageName"] = imageName;
  }
}

然后从控制器:

  this.SetImageName("xyz");
  /* or */
  var imageName = this.GetImageName();

这当然是干的。也就是说,我不喜欢这些解决方案之一,因为我喜欢在会话中存储少量数据(如果有的话)。但是,如果您打算将所有这些信息放在一边,而无需加载/从其他来源识别,这是我能想到的最快(最脏)的方法。我相当肯定有一个更优雅的解决方案,但是我没有关于你正在做什么和什么是问题域的所有信息。

This is certainly DRY. That said, I don't particularly like either of these solutions as I prefer to store as little data, if any, in session. But if you're intent is to hold onto all of this information without having to load/discern it from some other source, this is the quickest (dirtiest) way I can think of to do it. I'm quite certain there's a much more elegant solution, but I don't have all of the information about what it is you're trying to do and what the problem domain is.

请记住,在会话中存储信息时,您将不得不通过序列化对对象进行脱水/再水化,您可能没有获得以您的方式执行的性能。

Keep in mind that when storing information in the session, you will have to dehydrate/rehydrate the objects via serialization and you may not be getting the performance you think you are from doing it this way.

希望这有帮助。

编辑:响应其他信息
不确定在哪里您正在寻求部署,但处理图像实时是一个可靠的火灾方式被击中DoS攻击。我的建议如下 - 这是假设这是公开的,任何人都可以上传图片:

In response to additional information Not sure on where you're looking to deploy this, but processing images "real-time" is a sure fire way to be hit with a DoS attack. My suggestion to you is as follows -- this is assuming that this is public facing and anyone can upload an image:

1)允许用户上传图片。该图像进入处理队列,用于应用程序或某些服务的后台处理。此外,图像的名称进入用户的个人处理队列 - 可能是数据库中的表。有关网络应用程序中后台处理的信息可以在安排托管Web服务器中的工作

1) Allow the user to upload an image. This image goes into the processing queue for background processing by the application or some service. Additionally, the name of the image goes into the user's personal processing queue -- likely a table in the database. Information about background processing in a web app can be found @ Schedule a job in hosted web server

2)处理这些图像,并在处理时显示处理图形。您可以在产品页面上有一个ajax请求,用于检查正在处理的图像,并每隔X秒重新加载图像。

2) Process these images and, while processing, display a "processing graphic". You can have an ajax request on the product page that checks for images being processed and trys to reload them every X seconds.

3)当图像被处理假设用户是上传图像的用户,可以选择不进行处理。这可以在显示图像的产品页面上或单独的用户队列视图中使用,从而可以将它们从考虑中删除。

3) While an image is being "processed", the user can opt out of processing assuming they're the one that uploaded the image. This is available either on the product page(s) that display the image or on a separate "user queue" view that will allow them to remove the image from consideration.

所以,你最终得到一些更多的域对象,这些对象是由队列管理的。我是一个强大的倡导者,超过配置,所以产品图像的最终目的地应该是预定义的。例如:

So, you end up with some more domain objects and those objects are managed by the queue. I'm a strong advocate of convention over configuration so the final destination of the product image(s) should be predefined. Something like:

images / products / {id} .jpg或者,如果一个集合,images / products / {id} / {sequence} .jpg。

images/products/{id}.jpg or, if a collection, images/products/{id}/{sequence}.jpg.

然后,您不需要知道表单中的目的地。所有图像都是一样的。

You then don't need to know the destination in the form. It's the same for all images.

然后,队列需要知道临时图像上传的位置以及产品ID的位置。队列工作人员从队列中弹出项目,处理它们并相应地存储它们。

The queue then needs to know where the temp image was uploaded and what the product id was. The queue worker pops items from the queue, processes them, and stores them accordingly.

我知道这听起来比您原来想要的更多结构化,但是认为这有点清洁。

I know this sounds a little more "structured" than what you originally intended, but I think it's a little cleaner.

这篇关于ASP.NET MVC - 控制器之间共享会话状态的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆