使用 AppFabric 缓存在 MVC SessionState 中使用 WCF DataContract
我有一个数据访问层、一个服务层和一个表示层。表示层是 ASP.NET MVC2 RTM(Web),服务层是 WCF(服务)。都是.NET 3.5 SP1。
问题在于,在服务中,返回的对象是用 [DataContract]
属性标记的。 Web 使用 AppFabric Cache(又名 Velocity)SessionStateProvider 来存储会话状态。因此,我在会话中存储的任何内容都必须是可序列化的。
问题来了:DataContracts 没有标记为 [Serializable]
并且据我所知,通过将其引入到已经标记为 [DataContract]
的类中问题出现了,所以我不认为这是一个解决方案。
我最初计划在 Web 层中使用 DataContracts,将它们用作与渲染 DataContracts 相关的视图的模型(可能嵌套在更高级别的 ViewModel 类中)。但由于会话状态提供程序要求存储在其中的所有对象都是可序列化的,我开始重新考虑这个策略。不过,如果有的话那就太好了,因为它们包含使用 IDataErrorInfo 接口的验证逻辑,并且可以在 MVC 中重复使用相同的验证逻辑作为模型绑定的一部分。
您认为减少所需工作量的最佳方法是什么?
我目前想到了以下不同的方法:
A.在 Web 项目中创建一个“ServiceIntegration”部分。
这将是我的控制器和 WCF 服务层之间的中间人。 ServiceIntegration 部分将使用 DataContracts 与服务层通信,并使用 ViewModels 与 Web 层通信,但必须使用双向 Transformer 在 DataContracts 和 ViewModels 之间进行转换。
此外,由于 IDataErrorInfo 验证无法重复使用,因此还需要为每个 DataContract 创建一个验证器,该验证器使用 Transformer 从 ViewModel 转换为 DataContract,使用 IDataErrorInfo 执行验证并返回其结果。然后,这将在控制器的操作方法中使用(例如 if (!MyValidator.IsValid(viewModel)) return View();
)
需要不同的类:xDataContract、xViewModel、xTransformer、xValidator< /em>
B.在 Web 项目中创建“SessionIntegration”部分
这将是控制器(或访问会话的任何内容)和会话本身之间的中间人。任何需要访问会话的内容都将通过此类。 DataContracts 将在整个应用程序中使用,除非它们被存储到会话中。 SessionIntegration 部分将负责将 DataContract 转换为某种 ISerialized 形式,然后再转换回来。由于在 DataContract 上使用了 IDataErrorInfo 接口,因此不需要额外的验证器。
需要不同的类:xDataContract、xTransformer、xSerializedForm
注意:在这两种情况下仍然存在 ViewModel,但是使用 (B),我可以从 DataContract 组成 ViewModel。
(B) 的优点是不需要额外的验证器。
在我开始完全实施 (A)/(B) 之前,我想要一些反馈。目前,我开始倾向于(B),但是,(A)可能更灵活。不管怎样,对于它的价值来说,这似乎是太多的工作。还有其他人遇到过这个问题吗?您同意/不同意我的观点,和/或您有其他解决问题的方法吗?
谢谢,
詹姆斯
I have a Data Access Layer, a Service Layer, and a Presentation Layer. The Presentation Layer is ASP.NET MVC2 RTM (web), and the Service Layer is WCF (services). It's all .NET 3.5 SP1.
The problem is that in the services, the objects being returned are marked with the [DataContract]
attribute. The web is using the AppFabric Cache (a.k.a Velocity) SessionStateProvider to store session state. Due to this, anything I store in the session must be serializable.
Here comes the problem: the DataContracts aren't marked with [Serializable]
and as far as I can remember, by introducing it onto a class already marked with [DataContract]
some issues arise, and so I don't believe this is a solution.
I was initially planning on using the DataContracts right in the web layer, using them as models to views related to rendering the DataContracts (probably nested inside a higher level ViewModel class). But due to the session state provider requiring all objects stored inside it to be serializable, I'm starting to rethink this strategy. It would be nice to have though, since they contain validation logic using the IDataErrorInfo
interface, and the same validation logic could be re-used in MVC as part of model binding.
What do you believe is the best way to allow me to reduce the work needed?
I've currently thought of the following different ways:
A. Create a 'ServiceIntegration' part in the web project.
This would be a middle man between my controllers and my WCF service layer. The ServiceIntegration part would speak to the service layer using DataContracts, and to the Web layer using ViewModels, but would have to transform between the DataContracts and ViewModels using a two-way Transformer.
Also, since the IDataErrorInfo Validation wouldn't be re-usable, it would be necessary to create a Validator per DataContract too, that uses the Transformer to convert from ViewModel to DataContract, perform validation using IDataErrorInfo and return its results. This would then be used inside action methods of Controllers (e.g. if (!MyValidator.IsValid(viewModel)) return View();
)
Different classes required: xDataContract, xViewModel, xTransformer, xValidator
B. Create a 'SessionIntegration' part in the web project
This would be a middle-man between the controllers (or anything accessing the session) and the session itself. Anything requiring access to the session would go through this class. DataContracts would be used in the entire application, unless they are being stored into the session. The SessionIntegration part would take the responsibility of transforming the DataContract to some ISerializable form, and back. No additional Validator is needed because of the use of of IDataErrorInfo interface on the DataContract.
Different classes required: xDataContract, xTransformer, xSerializableForm
Note: there would still be ViewModels around in both scenarios, however with (B) I'd be able to compose ViewModels from DataContracts.
(B) has the benefit of not needing an extra validator.
Before I go off and implement (A)/(B) fully, I'd like some feedback. At the moment, I'm starting to lean towards (B), however, (A) might be more flexible. Either way, it seems like way too much work for what it's worth. Has anyone else come across this problem, do you agree/disagree with me, and/or do you have any other way of solving the problem?
Thanks,
James
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
如果不采用 A 或 B 的完整路线,您是否可以创建一个通用的 ISerialized 包装对象并将其放入您的 SessionState 中?
Without going the full blown route of A or B, could you just make a generic ISerializable wrapper object and put those in your SessionState?
作为所提供答案的扩展,我添加了这两种方法来简化存储/检索数据。
这使得从会话中设置/获取值变得更容易:
为了使其更容易,请添加扩展方法:
并按如下方式使用:
As an extension to the provided answer, I added these two methods to ease storing/retrieving the data.
This makes it a little easier to set/get values from the session:
To make it even easier, add extension methods:
And use as below: