2011-11-24 93 views
1

我有两个实验性的Web服务。一个是包含在.net Web应用程序中的asmx。另一个是从Web应用程序调用的WCF服务库。asmx json序列化与wcf json序列化

asmx基本上做了我需要的一切,但我认为WCF会更好,除非它没有做任何事情,因为我没有做任何事情后,摆弄asmx服务。

例如,同样的方法在各个不同的行为:

' ASMX 
<WebMethod(BufferResponse:=True, EnableSession:=False)> 
Function Test(aObject as Object) as Object 
    ' object will have been successfully serializaed into a dictionary 
    Dim lResult as SomeObject = new SomeObject(aObject) 
    return lResult ' lResult will be serialized as whatever type it is and will be deserialized by client making ajax call 
End Function 

' WCF 
<OperationContract()> 
<WebInvoke(RequestFormat:=ServiceModel.Web.WebMessageFormat.Json, 
      ResponseFormat:=ServiceModel.Web.WebMessageFormat.Json, 
      BodyStyle:=WebMessageBodyStyle.Wrapped)> 
Function Test(aObject As Object) As Object 
    ' object is serialized as an empty instance of Object 
    ' not very useful 
    Dim lResult as SomeObject = new SomeObject(aObject) ' waste of time with useless object 
    return lResult ' even if lResult could be instantiated the client returns error 500 because 
       ' WCF won't serialize SomeObject as Object 
End Function 

我一直在研究这个问题和关闭了好几个月,因为我有项目之间的时间。我没有试过让WCF做ASMX的工作。有任何想法吗?

回答

1

我看到它的方式是您创建WCF服务到特定的接口合同。

如果您可以只指定任何类型的对象,则没有编程机制来验证管道的任一端是否已正确实现该接口。

我发现WCF在类序列化和反序列化方面通常比ASMX更具限制性,但是从ASMX切换到WCF已经极大地改进了我们的应用程序的稳定性,可维护性和生产力。

话虽如此,没有理由切换到WCF只是因为它是WCF。您需要确切地确定为什么您认为它对您的情况更好,如果是这样,那么您需要使用实际类而不是仅用对象来创建一些测试用例,以验证它能够满足您的需求。

有一点需要考虑:如果您在自己的Silverlight,WPF或WinForms编写的.Net应用程序中使用WCF服务,那么WCF将使您的生活从长远来看变得更容易,因为它可以在管道的两端共享相同的业务对象类代码。

更新与评论

其实信息,你可以只要序列化抽象类,因为它们可以被反序列化的具体实现。您可以通过将抽象类与KnownType属性归因于您想要序列化的每个具体类来完成此操作。

主要问题不是服务接口契约,而是DataContract,它在某个时刻需要具体的类。 This link描述了规则。

您可以创建一个从对象继承的装饰类,并使用已知类型修饰要使用的类。

+0

很好,谢谢。纠正。 –

+0

我们使用ajax/json与Web浏览器中的服务进行交互。我想与WCF一起出于多种原因,但我需要传递对象的能力。这仍然是一个明确的合同。如果我们想传递Object以外的抽象祖先,WCF将不会工作。 –

+1

@MarkLauter:实际上,只要可以反序列化为具体实现,就可以序列化抽象类。您可以通过将抽象类与KnownType属性归因于您想要序列化的每个具体类来完成此操作。主要问题不是服务接口契约,而是DataContract,它需要某个具体的类。此链接描述了这些规则:http://msdn.microsoft.com/en-us/library/ms733127.aspx。你可以创建一个从对象继承而来的catchall类,并且使用已知类型装饰你想要使用的类 –

1

我们添加了一个函数,它返回所有类型,包括每个类型的List(T),它们符合我们所需的条件 - 可以存储在缓存中的对象。只要我们使用IsCacheableAttribute在我们的* .Core程序集中标记ICacheable类型,它们就会返回到列表中,并且我们不需要无法维护的硬编码的KnownType列表。我们还添加了属性d以保存数据,这对于Microsoft .d在浏览器/客户端中的安全性有希望做同样的事情。

Imports System.Reflection 
Imports OurCompany.Cache 
Imports OurApplication.Core 

<DataContract(), KnownType("AllTypes")> 
Public Class Data 

    Private Shared mCacheableType As Type = GetType(ICacheable) 
    Private Shared mIsCachedAttribute As Type = GetType(IsCacheableAttribute) 

    <DataMember()> 
    Public Property d As Object 

    Private Shared Function AllTypes() As IEnumerable(Of Type) 
     Return GetCacheableTypesFromAssembly(GetType(AssemblyKeyClass).Assembly) 
    End Function 

    Private Shared Function GetCacheableTypesFromAssembly(aAssembly As Assembly) As IEnumerable(Of Type) 
     Dim lTypes As List(Of Type) = aAssembly.GetTypes().Where(Function(t) IsCacheable(t)).ToList 
     Dim lTypes2 As List(Of Type) = New List(Of Type) 
     lTypes2.AddRange(lTypes) 
     For Each lType In lTypes2 
      Dim lListType As Type = GetType(List(Of)).MakeGenericType({lType}) 
      lTypes.Add(lListType) 
     Next 
     Return lTypes 
    End Function 

    Private Shared Function IsCacheable(aType As Type) As Boolean 
     Dim lResult As Boolean = False 
     If aType.GetInterfaces.Contains(mCacheableType) Then 
      Dim lAttribute As Object() = aType.GetCustomAttributes(mIsCachedAttribute, True) 
      If lAttribute.Count = 1 Then 
       lResult = DirectCast(lAttribute(0), IsCacheableAttribute).Value 
      End If 
     End If 
     Return lResult 
    End Function 

End Class 

下面是我们用来测试返回各种类型数据的IService方法。对于将数据传递给服务,我们将坚持传递一个字符串并使用JavaScriptSerializer对其进行反序列化。通过这种方式,我们可以保留一些复杂类型的“未知对象到字典”行为。

+0

我们已经放弃了对象到字典的行为,并能够使用已知类型的想法正确地传递正确的复杂类型。 –

0

微小的变化消除了与应用程序名称空间的耦合,并允许我们将此类用作基础库集合的一部分。我们将数据转换为通用类型。这肯定会打败KnownType(GetType(YetAnotherClass))数百次,然后每次我们向系统中添加一个新的json可移植类。

<DataContract(), KnownType("AllTypes")> 
Public NotInheritable Class Data(Of T) 

    Private Shared Function AllTypes() As IEnumerable(Of Type) 
     Return GetSerializableTypesFromAssembly(GetType(T).Assembly) 
    End Function