Created
September 30, 2010 09:58
-
-
Save abergs/604325 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Imports System | |
Imports System.Web | |
Imports System.Web.Mvc | |
Imports System.IO | |
Imports System.Xml | |
Imports System.Text | |
Imports System.Collections.Generic | |
Imports System.Web.Script.Serialization | |
Imports System.Runtime.Serialization | |
Imports System.Reflection | |
Imports System.Reflection.Emit | |
Public Class restResult | |
Inherits ActionFilterAttribute | |
Private _actionParams As [String]() | |
''// for deserialization | |
Public Sub New(ByVal ParamArray parameters As [String]()) | |
Me._actionParams = parameters | |
End Sub | |
''// SERIALIZE | |
Public Overrides Sub OnActionExecuted(ByVal filterContext As ActionExecutedContext) | |
If Not (TypeOf filterContext.Result Is ViewResult) Then | |
Exit Sub | |
End If | |
' // SETUP | |
Dim utf8 As New UTF8Encoding(False) | |
Dim request As HttpRequestBase = filterContext.RequestContext.HttpContext.Request | |
Dim contentType As [String] = If(request.ContentType, String.Empty) | |
Dim view As ViewResult = DirectCast(filterContext.Result, ViewResult) | |
Dim data = view.ViewData.Model | |
' JSON | |
If contentType.Contains("application/json") OrElse request.IsAjaxRequest() Then | |
Using stream = New MemoryStream() | |
Dim js As New JavaScriptSerializer() | |
'Här kan det bli fel, tog bort key . c.... | |
Dim content As [String] = js.Serialize(data) | |
filterContext.Result = New ContentResult() With { _ | |
.ContentType = "application/json", _ | |
.Content = content, _ | |
.ContentEncoding = utf8 _ | |
} | |
End Using | |
ElseIf contentType.Contains("text/xml") Then | |
' MemoryStream to encapsulate as UTF-8 (default UTF-16) | |
' http://stackoverflow.com/questions/427725/ | |
' | |
' MemoryStream also used for atomicity but not here | |
' http://stackoverflow.com/questions/486843/ | |
Using stream As New MemoryStream(500) | |
Using xmlWriter = XmlTextWriter.Create(stream, New XmlWriterSettings() With { _ | |
.OmitXmlDeclaration = True, _ | |
.Encoding = utf8, _ | |
.Indent = True _ | |
}) | |
' knownTypes | |
' maxItemsInObjectGraph | |
' ignoreExtensionDataObject | |
' preserveObjectReference - overcomes cyclical reference issues | |
' dataContractSurrogate | |
' Dim x As New datacontractserializer | |
' Dim x As datacontractSerializer = New datacontractserializer( | |
' Dim ser As New DataContractSerializer(GetType(Person)) | |
Dim ser As New DataContractSerializer(data.[GetType](), Nothing, 65536, False, True, Nothing) | |
ser.WriteObject(stream, data) | |
End Using | |
filterContext.Result = New ContentResult() With { _ | |
.ContentType = "text/xml", _ | |
.Content = utf8.GetString(stream.ToArray()), _ | |
.ContentEncoding = utf8 _ | |
} | |
End Using | |
End If | |
End Sub | |
' DESERIALIZE | |
Public Overrides Sub OnActionExecuting(ByVal filterContext As ActionExecutingContext) | |
If _actionParams Is Nothing OrElse _actionParams.Length = 0 Then | |
Exit Sub | |
End If | |
Dim request As HttpRequestBase = filterContext.RequestContext.HttpContext.Request | |
Dim contentType As [String] = If(request.ContentType, String.Empty) | |
Dim isJson As [Boolean] = contentType.Contains("application/json") | |
If Not isJson Then | |
Exit Sub | |
End If | |
'@@todo Deserialize POX | |
' JavascriptSerialier expects a single type to deserialize | |
' so if the response contains multiple disparate objects to deserialize | |
' we dynamically build a new wrapper class with fields representing those | |
' object types, deserialize and then unwrap | |
Dim paramDescriptors As ParameterDescriptor() = filterContext.ActionDescriptor.GetParameters() | |
Dim complexType As [Boolean] = paramDescriptors.Length > 1 | |
Dim wrapperClass As Type | |
If complexType Then | |
Dim parameterInfo As New Dictionary(Of String, Type) | |
For Each p As ParameterDescriptor In paramDescriptors | |
parameterInfo.Add(p.ParameterName, p.ParameterType) | |
Next | |
wrapperClass = BuildWrapperClass(parameterInfo) | |
Else | |
wrapperClass = paramDescriptors(0).ParameterType | |
End If | |
Dim json As [String] | |
Using sr = New StreamReader(request.InputStream) | |
json = sr.ReadToEnd() | |
End Using | |
' then deserialize json as instance of dynamically created wrapper class | |
Dim serializer As New JavaScriptSerializer() | |
Dim result = GetType(JavaScriptSerializer).GetMethod("Deserialize").MakeGenericMethod(wrapperClass).Invoke(serializer, New Object() {json}) | |
' then get fields from wrapper class assign the values back to the action params | |
If complexType Then | |
For i As Int32 = 0 To paramDescriptors.Length - 1 | |
Dim pd As ParameterDescriptor = paramDescriptors(i) | |
filterContext.ActionParameters(pd.ParameterName) = wrapperClass.GetField(pd.ParameterName).GetValue(result) | |
Next | |
Else | |
Dim pd As ParameterDescriptor = paramDescriptors(0) | |
filterContext.ActionParameters(pd.ParameterName) = result | |
End If | |
End Sub | |
Private Function BuildWrapperClass(ByVal parameterInfo As Dictionary(Of String, Type)) As Type | |
Dim assemblyName As New AssemblyName() | |
assemblyName.Name = "DynamicAssembly" | |
Dim appDomain__1 As AppDomain = AppDomain.CurrentDomain | |
Dim assemblyBuilder As AssemblyBuilder = appDomain__1.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run) | |
Dim moduleBuilder As ModuleBuilder = assemblyBuilder.DefineDynamicModule("DynamicModule") | |
Dim typeBuilder As TypeBuilder = moduleBuilder.DefineType("DynamicClass", TypeAttributes.[Public] Or TypeAttributes.[Class]) | |
For Each entry As KeyValuePair(Of String, Type) In parameterInfo | |
Dim paramName As [String] = entry.Key | |
Dim paramType As Type = entry.Value | |
Dim field As FieldBuilder = typeBuilder.DefineField(paramName, paramType, FieldAttributes.[Public]) | |
Next | |
Dim generatedType As Type = typeBuilder.CreateType() | |
' object generatedObject = Activator.CreateInstance(generatedType); | |
Return generatedType | |
End Function | |
End Class |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment