File: System\Web\Services\Protocols\XmlReturnReader.cs
Project: ndp\cdf\src\NetFx20\System.Web.Services\System.Web.Services.csproj (System.Web.Services)
//------------------------------------------------------------------------------
// <copyright file="XmlReturnReader.cs" company="Microsoft">
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// </copyright>                                                                
//------------------------------------------------------------------------------
 
namespace System.Web.Services.Protocols {
    using System.IO;
    using System;
    using System.Xml.Serialization;
    using System.Reflection;
    using System.Collections;
    using System.Web.Services;
    using System.Net;
    using System.Text;
    using System.Security.Policy;
    using System.Security;
    using System.Security.Permissions;
    using System.Web.Services.Diagnostics;
 
    internal class XmlReturn {
        private XmlReturn() { }
        internal static object[] GetInitializers(LogicalMethodInfo[] methodInfos) {
            if (methodInfos.Length == 0) return new object[0];
            WebServiceAttribute serviceAttribute = WebServiceReflector.GetAttribute(methodInfos);
            bool serviceDefaultIsEncoded = SoapReflector.ServiceDefaultIsEncoded(WebServiceReflector.GetMostDerivedType(methodInfos));
            XmlReflectionImporter importer = SoapReflector.CreateXmlImporter(serviceAttribute.Namespace, serviceDefaultIsEncoded);
            WebMethodReflector.IncludeTypes(methodInfos, importer);
            ArrayList mappings = new ArrayList();
            bool[] supported = new bool[methodInfos.Length];
            for (int i = 0; i < methodInfos.Length; i++) {
                LogicalMethodInfo methodInfo = methodInfos[i];
                Type type = methodInfo.ReturnType;
                if (IsSupported(type) && HttpServerProtocol.AreUrlParametersSupported(methodInfo)) {
                    XmlAttributes a = new XmlAttributes(methodInfo.ReturnTypeCustomAttributeProvider);
                    XmlTypeMapping mapping = importer.ImportTypeMapping(type, a.XmlRoot);
                    mapping.SetKey(methodInfo.GetKey() + ":Return");
                    mappings.Add(mapping);
                    supported[i] = true;
                }
            }
            if (mappings.Count == 0)
                return new object[0];
 
            XmlMapping[] xmlMappings = (XmlMapping[])mappings.ToArray(typeof(XmlMapping));
            Evidence evidence = GetEvidenceForType(methodInfos[0].DeclaringType);
 
            TraceMethod caller = Tracing.On ? new TraceMethod(typeof(XmlReturn), "GetInitializers", methodInfos) : null;
            if (Tracing.On) Tracing.Enter(Tracing.TraceId(Res.TraceCreateSerializer), caller, new TraceMethod(typeof(XmlSerializer), "FromMappings", xmlMappings, evidence));
            XmlSerializer[] serializers = null;
            if (AppDomain.CurrentDomain.IsHomogenous)
            {
                serializers = XmlSerializer.FromMappings(xmlMappings);
            }
            else
            {
#pragma warning disable 618 // If we're in a non-homogenous domain, legacy CAS mode is enabled, so passing through evidence will not fail
                serializers = XmlSerializer.FromMappings(xmlMappings, evidence);
#pragma warning restore 618
            }
 
            if (Tracing.On) Tracing.Exit(Tracing.TraceId(Res.TraceCreateSerializer), caller);
 
            object[] initializers = new object[methodInfos.Length];
            int count = 0;
            for (int i = 0; i < initializers.Length; i++) {
                if (supported[i]) {
                    initializers[i] = serializers[count++];
                }
            }
            return initializers;
        }
 
        static bool IsSupported(Type returnType) {
            return returnType != typeof(void);
        }
 
        internal static object GetInitializer(LogicalMethodInfo methodInfo) {
            return GetInitializers(new LogicalMethodInfo[] { methodInfo });
        }
 
        // Asserts full-trust permission-set.
        // Reason: Assembly.Evidence demands SecurityPermission and/or other permissions.
        // Justification: The type returned is only used to get the GetInitializers method.
        [PermissionSet(SecurityAction.Assert, Unrestricted = true)]
        static Evidence GetEvidenceForType(Type type)
        {
            return type.Assembly.Evidence;
        }
    }
 
    /// <include file='doc\XmlReturnReader.uex' path='docs/doc[@for="XmlReturnReader"]/*' />
    public class XmlReturnReader : MimeReturnReader {
        XmlSerializer xmlSerializer;
 
        /// <include file='doc\XmlReturnReader.uex' path='docs/doc[@for="XmlReturnReader.Initialize"]/*' />
        public override void Initialize(object o) {
            xmlSerializer = (XmlSerializer)o;
        }
 
        /// <include file='doc\XmlReturnReader.uex' path='docs/doc[@for="XmlReturnReader.GetInitializers"]/*' />
        public override object[] GetInitializers(LogicalMethodInfo[] methodInfos) {
            return XmlReturn.GetInitializers(methodInfos);
        }
 
        /// <include file='doc\XmlReturnReader.uex' path='docs/doc[@for="XmlReturnReader.GetInitializer"]/*' />
        public override object GetInitializer(LogicalMethodInfo methodInfo) {
            return XmlReturn.GetInitializer(methodInfo);
        }
 
        /// <include file='doc\XmlReturnReader.uex' path='docs/doc[@for="XmlReturnReader.Read"]/*' />
        public override object Read(WebResponse response, Stream responseStream) {
            try {
                if (response == null) throw new ArgumentNullException("response");
                if (!ContentType.MatchesBase(response.ContentType, ContentType.TextXml)) {
                    throw new InvalidOperationException(Res.GetString(Res.WebResultNotXml));
                }
                Encoding e = RequestResponseUtils.GetEncoding(response.ContentType);
                StreamReader reader = new StreamReader(responseStream, e, true);
                TraceMethod caller = Tracing.On ? new TraceMethod(this, "Read") : null;
                if (Tracing.On) Tracing.Enter(Tracing.TraceId(Res.TraceReadResponse), caller, new TraceMethod(xmlSerializer, "Deserialize", reader));
                object returnValue = xmlSerializer.Deserialize(reader);
                if (Tracing.On) Tracing.Exit(Tracing.TraceId(Res.TraceReadResponse), caller);
                return returnValue;
            }
            finally {
                response.Close();
            }
        }
    }
}