English 中文(简体)
ASP.Net MVC和州----如何在请求之间保持状态
原标题:ASP.Net MVC and state - how to keep state between requests

作为一个经验丰富的ASP.Net开发商,我最近才开始使用MVC, 我发现自己在努力改变我的思维方式, 从传统的“服务器控制和事件处理者”做事方式, 变成更动态的MVC方式。我想我正在慢慢到达那里,但有时MVC的“魔术”把我甩掉了。

我目前的设想是创建一个网页,让用户浏览本地文件,上传到服务器上,并在有要处理的文件列表之前重复这个网页。 当他满意文件列表( 将在页面的网格中显示) 时, 他将单击一个按钮来处理文件, 并提取一些存储在数据库中的数据 。

最后一个部分并不那么重要,而现在我正在忙着解决一些无关紧要的事情,比如建立一份文件清单,并且坚持在请求之间排出这份清单。 在传统的做法中,这将是非常简单的 — — 数据将持续在View State。 但在MVC中,我需要将数据传递给控制器和视图之间,而我并不完全理解这应该如何运作。

我猜我最好发表我相当不完整的 编译尝试来解释问题

为了保存我的文件列表数据, 我创建了一个视图模型, 基本上是一个打印的文件列表, 以及一些额外的元数据 :

public class ImportDataViewModel
{
    public ImportDataViewModel()
    {
        Files = new List<ImportDataFile>();
    }

    public List<ImportDataFile> Files { get; set; }
...

在视图中, 我有一个浏览和上传文件的表格 :

<form action="AddImportFile" method="post" enctype="multipart/form-data">
  <label for="file">
    Filename:</label>
  <input type="file" name="file" id="file" />
  <input type="submit" />
  </form>

观景正在使用观景模型作为其模型:

@model MHP.ViewModels.ImportDataViewModel

这将将文件发送到我的动作 :

public ActionResult AddImportFile(HttpPostedFileBase file, ImportDataViewModel importData)
    {

        if (file.ContentLength > 0)
        {
            ImportDataFile idFile = new ImportDataFile { File = file };
            importData.Files.Add(idFile);
        }

        return View("DataImport", importData);
    }

此动作返回 Dataimport 页面的视图以及包含文件列表的查看模型实例 。

这在某个点上很好地工作, 我可以浏览一个文件并上传它, 我可以在动作中看到查看模型的数据, 然后如果我在视图中插入一个断点并调试“ this. model ”, 一切都很好 。

但是,如果我试图上传另一个文件,在 AddimportFile 动作中设置一个断点时, 导入 Data 参数是空的。 因此, 视图显然没有将其模型的当前实例传到动作中 。

在我所经历的MVC样本中, 模型实例被“神奇地”传递到动作方法上, 作为一种参数, 那么为什么它现在是空的呢?

我认为真正的问题是我对MVC的有限理解,而且可能有一个非常简单的解决方案。 总之,如果有人能指示我正确的方向,我将非常感激。

最佳回答

我提出这个问题已有一段时间了,我对MVC的微薄经验和知识使这个问题色彩深刻。 但我还是收到了一些非常有用的投入,这最终导致我找到了一个解决方案,并获得了对MVC的一些洞察力。

首先让我感到沮丧的是, 你可以有一个控制器, 一个强烈的输入对象作为参数, 像这样的参数:

public ActionResult DoSomething(MyClass myObject)...

此对象来自同一控制器:

...
return View(myObject);
...

这让我相信这个物体 活在这两个步骤中, 我不知怎的可以指望 你能把它送到视野, 做一些事情,然后"神奇"把它再次带回控制器。

在阅读了模型的约束性之后,我理解这当然不是事实。 观点是完全死寂的,静态的,除非你把信息储存在某处,否则信息就消失了。

回到问题, 即选择和上传客户端的文件, 以及建立这些要显示的文件的列表, 我意识到一般在MVC请求之间存有三种信息方式:

  1. You can store information in form fields in the view, and post it back to the controller later
  2. You can persist it in some kind of storage, e.g. a file or a database
  3. You can store it in server memory by acessing objects that lives throughout requests, e.g. session variables

In my case, I had basically two types of information to persist: 1. The file metadata (file name, file size etc.) 2. The file content

“ 逐本” 方法很可能是将元数据存储在形式字段中, 文件内容存储在文件或 DB 中。 但也有另一种方法。 由于我知道我的文件非常小, 并且其中只有少数, 并且这个解决方案永远不会被安装在服务器场或类似的服务器场中, 我想探索会话变量的 # 3 选项。 这些文件在会话之后的持久性也并不有趣, 它们被处理和丢弃, 所以我不想将它们存储在我的 DB 中 。

After reading this excellent article: Accessing ASP.NET Session Data Using Dynamics

我确信,我只是创造了文章中描述的沙包类,然后我可以在我的控制器里做以下工作:

    [HttpPost]
    public ActionResult AddImportFile(HttpPostedFileBase file)
    {

        ImportDataViewModel importData = SessionBag.Current.ImportData;
        if (importData == null) importData = new ImportDataViewModel();

        if (file == null)
            return RedirectToAction("DataImport");

        if (file.ContentLength > 0)
        {
            ImportDataFile idFile = new ImportDataFile { File = file };
            importData.Files.Add(idFile);
        }

        SessionBag.Current.ImportData = importData;

        return RedirectToAction("DataImport");
    }

我完全明白,在多数情况下,这是一个糟糕的解决方案。 但对于服务器内存的少数 kb 服务器内存来说,文件占据了所有的文件,而且由于文件的简单性,我认为这对我来说是非常好的。

使用会话Bag的额外好处是,如果用户输入了一个不同的菜单项,然后又返回,文件列表仍然会存在。在选择窗体字段/文件存储选项时,情况并非如此。

最后,我意识到,鉴于使用简便,会话Bag很容易被滥用。 但如果你用它来表达它的意义,即会话数据,我想它可以是一个强大的工具。

问题回答

上传 < / 强 > 上传 < 强 > 上传

1) 也许可以考虑一个带有 HTML 的 AJAX 上传器, 允许您的用户选择多个文件 在 < / em> 之前被发送到服务器 。 这个 BlueImp Jquery AJAX 文件上传器非常惊人, 包含一个非常伟大的 api : < a href="https://github.com/ bluueimp/jQuery- File-Upload > Blueim Jquery 文件上传 。 它允许用户拖放或多选几个文件, 编辑文件命令, 包括/ exclude 等 。 当他们高兴的时候, 他们可以按上传到您的控制器或上传处理服务器的处理器 。

2) 您可以让每个上传都持续到数据库中, 尽管您会重新加载整个页面, 并撰写一些额外的视图模型和剃刀代码, 以实现列表效果。 这很可能无法响应...

维持国家网站格式/MVC < 强 > 。

保持请求之间的状态是某种黑色的魔法和巫术。 进入 ASP. NET MVC 时, 请理解网络应用程序使用请求和回应进行通信。 所以, 请将网络作为无国籍者, 并从中发展起来 。 当您的模型通过控制器发布时, 它会与控制器中的任何变量一起“ 坚固” / 坚固 。 但是, 在它消失之前, 您可以将其内容存储在数据库中, 以便日后检索 。

网络应用程序无法像桌面应用程序一样保持真实状态。 在 HTTP 环境中, 有很多方法可以模拟 Ajax 框架和一些巫术工具。 而模拟状态其实只是虚假的状态模拟。 ASP. NET Web 格式试图通过向开发者隐藏 HTTP 的无国籍性质来尽量模拟状态。 在试图使用您自己的 AJAX 代码与 Web 格式标记代码及其自己的 Ajax 框架同步时, 您可以遇到很多头痛 。

校对:Portnoy

除了所有笑话之外, 如果你得到MVC/HTTP/无政府心态, 这些模式将很容易应用到其他超受欢迎的框架, 如Ruby on Rails, SpringMVC(Java), Django(Python), CakePHP 等...这种知识的简单转让将帮助你成为更好的开发者,

我很高兴你重新学习MVC 3, 我在一些非常大的公司实习过一些实习。 这些公司拥有这些疯狂的大型 ASP.NET Web Form项目, 代码无处不在, 目的只是为了改变数据库中的数字值( - - - ) 。 感觉就像我用剪刀编织婴儿袜子一样。 一个简单的错误动作,一切都崩溃了。 感觉就像在PHP里发展, 你出汗了, 不知道发生了什么事情, 也不知道在什么线上。 几乎不可能调试和更新 。





相关问题
WebForms and ASP.NET MVC co-existence

I am trying to make a WebForms project and ASP.NET MVC per this question. One of the things I ve done to make that happen is that I added a namespaces node to the WebForms web.config: <pages ...

Post back complex object from client side

I m using ASP.NET MVC and Entity Framework. I m going to pass a complex entity to the client side and allow the user to modify it, and post it back to the controller. But I don t know how to do that ...

Create an incremental placeholder in NHaml

What I want to reach is a way to add a script and style placeholder in my master. They will include my initial site.css and jquery.js files. Each haml page or partial can then add their own required ...

asp.net mvc automapper parsing

let s say we have something like this public class Person { public string Name {get; set;} public Country Country {get; set;} } public class PersonViewModel { public Person Person {get; ...

structureMap mocks stub help

I have an BLL that does validation on user input then inserts a parent(PorEO) and then inserts children(PorBoxEO). So there are two calls to the same InsertJCDC. One like this=>InsertJCDC(fakePor)...

ASP.NET MVC: How should it work with subversion?

So, I have an asp.net mvc app that is being worked on by multiple developers in differing capacities. This is our first time working on a mvc app and my first time working with .NET. Our app does not ...

System.Web.Mvc.Controller Initialize

i have the following base controller... public class BaseController : Controller { protected override void Initialize(System.Web.Routing.RequestContext requestContext) { if (...