Tengo una capa de acceso a datos, una capa de servicio y una capa de presentación. La capa de presentación es ASP.NET MVC2 RTM (web), y la capa de servicio es WCF (servicios). Es todo .NET 3.5 SP1.Uso de WCF DataContract en MVC SessionState usando el caché de AppFabric
El problema es que en los servicios, los objetos que se devuelven se marcan con el atributo [DataContract]
. La web está utilizando el caché AppFabric Cache (a.k.a Velocity) SessionStateProvider para almacenar el estado de la sesión. Debido a esto, todo lo que almacene en la sesión debe ser serializable.
Aquí viene el problema: los DataContracts no están marcados con [Serializable]
y, por lo que puedo recordar, al introducirlo en una clase ya marcada con [DataContract]
surgen algunos problemas, por lo que no creo que esta sea una solución .
Al principio estaba planeando usar los DataContracts directamente en la capa web, utilizándolos como modelos para las vistas relacionadas con la representación de los DataContracts (probablemente anidados dentro de una clase ViewModel de nivel superior). Pero debido a que el proveedor del estado de la sesión requiere que todos los objetos almacenados en él sean serializables, estoy empezando a replantear esta estrategia. Sin embargo, sería bueno tenerlo, ya que contienen una lógica de validación usando la interfaz IDataErrorInfo
, y la misma lógica de validación podría reutilizarse en MVC como parte del enlace del modelo.
¿Cuál cree que es la mejor manera de permitirme reducir el trabajo necesario?
He pensado en la actualidad de las siguientes maneras:
A. Crear una parte 'ServiceIntegration' en el proyecto web.
Este sería un intermediario entre mis controladores y mi capa de servicio WCF. La parte de Integración de servicio hablaría a la capa de servicio usando DataContracts, y a la capa web usando ViewModels, pero tendría que transformarse entre DataContracts y ViewModels usando un transformador bidireccional.
Además, dado que la validación de IDataErrorInfo no sería reutilizable, también sería necesario crear un Validator por DataContract, que utiliza el transformador para convertir de ViewModel a DataContract, realizar la validación utilizando IDataErrorInfo y devolver sus resultados. Esto entonces se utilizaría métodos de acción dentro de los controladores (por ejemplo if (!MyValidator.IsValid(viewModel)) return View();
)
Diferentes clases requerido: xDataContract, xViewModel, xTransformer, xValidator
B. Crear una parte 'SessionIntegration' en el proyecto web
Este sería un intermediario entre los controladores (o cualquier cosa que acceda a la sesión) y la sesión en sí. Todo lo que requiera acceso a la sesión pasará por esta clase. DataContracts se usará en toda la aplicación, a menos que se almacenen en la sesión. La parte SessionIntegration tendría la responsabilidad de transformar el DataContract en algún formulario de ISerializable, y viceversa. No se necesita ningún Validador adicional debido al uso de la interfaz IDataErrorInfo en el DataContract.
Diferentes clases requeridas: xDataContract, xTransformer, xSerializableForm
Nota: todavía habría ViewModels vueltas en ambos escenarios, sin embargo con (B) que sería capaz de componer ViewModels de DataContracts.
(B) tiene la ventaja de no necesitar un validador adicional.
Antes de salir e implementar (A)/(B) por completo, me gustaría recibir algunos comentarios. Por el momento, estoy empezando a inclinarme hacia (B), sin embargo, (A) podría ser más flexible. De cualquier manera, parece demasiado trabajo para lo que vale. ¿Alguien más ha encontrado este problema, está de acuerdo/en desacuerdo conmigo, y/o tiene alguna otra forma de resolver el problema?
Gracias,
James
Podría usar AutoMapper como parte del Tr ansformer, por lo que los detalles del mapeo pueden no ser una sobrecarga. Mapeo manual de ViewModels a DataContracts y viceversa definitivamente es mucho trabajo para lo que vale, IMHO – jamiebarrow