作为一个刚刚开始使用MVC的相当有经验的ASP.Net开发人员,我发现自己正在努力将我的思维方式从传统的"服务器控件和事件处理程序"的处理方式转变为更加动态的MVC方式.我想我正在慢慢地到达那里,但有时MVC"魔法"会让我失望.
我目前的情况是创建一个网页,允许用户浏览本地文件,将其上传到服务器并重复此操作,直到他有一个要使用的文件列表.当他对文件列表(将在页面上的网格中显示)感到满意时,他将单击一个按钮来处理文件并提取将存储在数据库中的一些数据.
最后一部分并不是那么重要,现在我正在努力处理像构建文件列表这样简单的事情,并在请求之间保持该列表.在传统方法中,这将非常简单 - 数据将保存在ViewState中.但是在MVC中我需要在控制器和视图之间传递数据,而我并没有完全了解它应该如何工作.
我想我最好发布我的相当不完整的编码尝试来解释这个问题.
为了保存我的文件列表数据,我创建了一个viewmodel,它基本上是一个类型化的文件列表,还有一些额外的元数据:
public class ImportDataViewModel
{
public ImportDataViewModel()
{
Files = new List<ImportDataFile>();
}
public List<ImportDataFile> Files { get; set; }
...
Run Code Online (Sandbox Code Playgroud)
在视图中,我有一个用于浏览和上传文件的表单:
<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>
Run Code Online (Sandbox Code Playgroud)
该视图使用viewmodel作为其模型:
@model MHP.ViewModels.ImportDataViewModel
Run Code Online (Sandbox Code Playgroud)
这会将文件发送到我的操作:
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);
}
Run Code Online (Sandbox Code Playgroud)
此操作返回DataImport页面的视图以及包含文件列表的viewmodel实例.
这可以很好地工作到某一点,我可以浏览文件并上传它,我可以在动作中看到viewmodel数据,然后如果我在视图中放置一个断点并调试"this.Model",一切都是精细.
但是,如果我尝试上传另一个文件,在AddImportFile操作中放置断点时,importData参数为空.因此,视图显然没有将其模型的当前实例传递给操作.
在我经历的MVC示例中,模型实例被"神奇地"传递给action方法作为参数,那么为什么它现在为空呢? …
我现在正在学习很多关于托管和非托管解决方案的知识,我肯定会看到在生产中使用托管解决方案带来很多好处.
我看到推荐的模式是拥有一个开发环境,您可以在其中使用非托管解决方案,导出解决方案的非托管和托管版本,最后将托管解决方案部署到生产环境(可能首先用于测试的暂存环境).
这一切都非常好,干净,但并非没有陷阱.我最近遇到了以下情况:
我们使用上述模式为帐户实体创建和部署托管解决方案,并为客户安装.该解决方案包含用于与遗留系统集成的表单和其他一些内容
草图:
管理部分
场A场B.
场C场D.
在我不知情的情况下,客户继续使用"自定义"菜单自定义帐户表单.他所做的是创建一个新的表单部分,并将我们的托管解决方案中包含的一些自定义字段从原始部分移动到新部分
草图:
非管理部分
场A场B.
管理部分
场C场D.
由于这是一个非托管的更改,它优先于我的托管更改,破坏了对表单布局的破坏,而我做了一些其他更改(删除其他一些字段并更改表单上某些字段的顺序)
我当然尝试重新安装解决方案,同时使用"覆盖自定义"选项,该选项承诺覆盖对实体的非托管自定义,但这不会改变任何内容.
我还尝试删除新部分和作为非托管自定义移动的字段(使用自定义菜单),然后重新安装托管解决方案,希望这将以某种方式"撤消"非托管更改,并且diff机制将检测到有问题的字段仅出现在托管解决方案中,这将导致它们出现在原始位置.但事实证明,它似乎只是在雕刻更多的石头 - 这次告诉系统从表格中删除字段.
真的可以这样吗,一旦你对表单进行了非托管更改,你的托管表单就搞砸了?
有没有办法强制托管表单再次优先?
我当然可以对表单进行一些更多的非托管自定义,将字段放回原来的位置,但这只会推迟问题,直到下次我想要更改托管表单中字段的顺序 - 非托管更改来自上次仍然有优先权.
似乎我唯一的选择是从头开始,或者切换到帐户实体的非托管机制.
如果这看起来很糟糕,我应该使用托管属性来禁止在托管解决方案中对表单进行自定义.如果这是一个自定义实体,我会这样做,但我认为这对于像帐户实体这样的实体来说会有点严格.另一个经验教训可能是永远不会给客户sysadmin/customizer权限......
会喜欢这方面的其他想法和经验.