File: System\ServiceModel\Dispatcher\JsonQueryStringConverter.cs
Project: ndp\cdf\src\NetFx35\System.ServiceModel.Web\System.ServiceModel.Web.csproj (System.ServiceModel.Web)
//------------------------------------------------------------
// Copyright (c) Microsoft Corporation.  All rights reserved.
//------------------------------------------------------------
#pragma warning disable 1634, 1691
namespace System.ServiceModel.Dispatcher
{
    using System;
    using System.IO;
    using System.Collections.Specialized;
    using System.Globalization;
    using System.Reflection;
    using System.ServiceModel;
    using System.ServiceModel.Channels;
    using System.ServiceModel.Description;
    using System.Text;
    using System.Web;
    using System.Xml;
    using System.Runtime.Serialization;
    using System.Runtime.Serialization.Json;
 
    public class JsonQueryStringConverter : QueryStringConverter
    {
        DataContractSerializerOperationBehavior dataContractSerializerOperationBehavior = null;
        OperationDescription operationDescription = null;
 
 
        public JsonQueryStringConverter() : base()
        {
        }
 
        internal JsonQueryStringConverter(OperationDescription operationDescription)
            : base()
        {
            if (operationDescription == null)
            {
                throw System.ServiceModel.DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("operationDescription");
            }
            this.operationDescription = operationDescription;
            this.dataContractSerializerOperationBehavior = this.operationDescription.Behaviors.Find<DataContractSerializerOperationBehavior>();
        }
 
        public override bool CanConvert(Type type)
        {
            XsdDataContractExporter exporter = new XsdDataContractExporter();
            return exporter.CanExport(type);
        }
 
        public override object ConvertStringToValue(string parameter, Type parameterType)
        {
            if (parameterType == null)
            {
                throw System.ServiceModel.DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("parameterType");
            }
            switch (Type.GetTypeCode(parameterType))
            {
                case TypeCode.Byte:
                case TypeCode.SByte:
                case TypeCode.Int16:
                case TypeCode.Int32:
                case TypeCode.Int64:
                case TypeCode.UInt16:
                case TypeCode.UInt32:
                case TypeCode.UInt64:
                case TypeCode.Single:
                case TypeCode.Double:
                case TypeCode.Decimal:
                case TypeCode.Boolean:
                    // base.ConvertStringToValue handles parameter == null case. 
                    return base.ConvertStringToValue(parameter, parameterType);
                case TypeCode.Char:
                case TypeCode.String:
                case TypeCode.DateTime:
                    // base.ConvertStringToValue handles parameter == null case. 
                    // IsFirstCharacterReservedCharacter returns false for null strings.
                    if (IsFirstCharacterReservedCharacter(parameter, '"'))
                    {
                        return CreateJsonDeserializedObject(parameter.Trim(), parameterType);
                    }
                    return base.ConvertStringToValue(parameter, parameterType);
                default:
                    {
                        if (parameterType == typeof(Guid))
                        {
                            if (parameter == null)
                            {
                                return default(Guid);
                            }
                            if (IsFirstCharacterReservedCharacter(parameter, '"'))
                            {
                                return CreateJsonDeserializedObject(parameter.Trim(), parameterType);
                            }
                            return base.ConvertStringToValue(parameter, parameterType);
                        }
                        else if (parameterType == typeof(Uri))
                        {
                            if (parameter == null)
                            {
                                return default(Uri);
                            }
                            if (IsFirstCharacterReservedCharacter(parameter, '"'))
                            {
                                return CreateJsonDeserializedObject(parameter.Trim(), parameterType);
                            }
                            return base.ConvertStringToValue(parameter, parameterType);
                        }
                        else if (parameterType == typeof(TimeSpan))
                        {
                            if (parameter == null)
                            {
                                return default(TimeSpan);
                            }
                            if (IsFirstCharacterReservedCharacter(parameter, '"'))
                            {
                                return CreateJsonDeserializedObject(parameter.Trim(), parameterType);
                            }
                            return base.ConvertStringToValue(parameter, parameterType);
                        }
                        else if (parameterType == typeof(byte[]))
                        {
                            if (parameter == null)
                            {
                                return default(byte[]);
                            }
                            if (IsFirstCharacterReservedCharacter(parameter, '['))
                            {
                                return CreateJsonDeserializedObject(parameter.Trim(), parameterType);
                            }
                            return base.ConvertStringToValue(parameter, parameterType);
                        }
                        else if (parameterType == typeof(DateTimeOffset))
                        {
                            if (parameter == null)
                            {
                                return default(DateTimeOffset);
                            }
                            if (IsFirstCharacterReservedCharacter(parameter, '{'))
                            {
                                return CreateJsonDeserializedObject(parameter.Trim(), parameterType);
                            }
                            return base.ConvertStringToValue(parameter, parameterType);
                        }
                        else if (parameterType == typeof(object))
                        {
                            if (parameter == null)
                            {
                                return default(object);
                            }
                            if (IsFirstCharacterReservedCharacter(parameter, '{'))
                            {
                                return CreateJsonDeserializedObject(parameter.Trim(), parameterType);
                            }
                            return base.ConvertStringToValue(parameter, parameterType);
                        }
 
                        if (parameter == null)
                        {
                            return null;
                        }
                        return CreateJsonDeserializedObject(parameter.Trim(), parameterType);
                    }
            }
        }
 
        public override string ConvertValueToString(object parameter, Type parameterType)
        {
            if (parameter == null)
            {
                return null;
            }
            MemoryStream memoryStream = new MemoryStream();
            XmlDictionaryWriter jsonWriter = JsonReaderWriterFactory.CreateJsonWriter(memoryStream, Encoding.UTF8);
            GetDataContractJsonSerializer(parameterType).WriteObject(jsonWriter, parameter);
            jsonWriter.Flush();
            memoryStream.Seek(0, SeekOrigin.Begin);
            return Encoding.UTF8.GetString(memoryStream.GetBuffer(), (int) memoryStream.Position, (int) memoryStream.Length);
        }
 
        object CreateJsonDeserializedObject(string parameter, Type parameterType)
        {
            byte[] byteArray = Encoding.UTF8.GetBytes(parameter);
            XmlDictionaryReader jsonReader = JsonReaderWriterFactory.CreateJsonReader
                (byteArray, 0, byteArray.Length, Encoding.UTF8, XmlDictionaryReaderQuotas.Max, null);
            return GetDataContractJsonSerializer(parameterType).ReadObject(jsonReader);
        }
 
        DataContractJsonSerializer GetDataContractJsonSerializer(Type parameterType)
        {
            if (this.operationDescription == null)
            {
                return new DataContractJsonSerializer(parameterType);
            }
            else if (this.dataContractSerializerOperationBehavior == null)
            {
                return new DataContractJsonSerializer(parameterType, operationDescription.KnownTypes);
            }
            else
            {
                return new DataContractJsonSerializer(parameterType, this.operationDescription.KnownTypes, this.dataContractSerializerOperationBehavior.maxItemsInObjectGraph,
                    this.dataContractSerializerOperationBehavior.IgnoreExtensionDataObject, this.dataContractSerializerOperationBehavior.DataContractSurrogate, false); //alwaysEmitTypeInformation
            }
        }
 
        bool IsFirstCharacterReservedCharacter(string parameter, char reservedCharacter)
        {
            if (parameter == null)
            {
                return false;
            }
            string localParameter = parameter.Trim();
            if (localParameter == string.Empty)
            {
                return false;
            }
            if (localParameter[0] == reservedCharacter)
            {
                return true;
            }
            return false;
        }
    }
}