PageRenderTime 58ms CodeModel.GetById 41ms app.highlight 13ms RepoModel.GetById 1ms app.codeStats 0ms

/WCFWebApi/src/Microsoft.ApplicationServer.Http/Microsoft/ApplicationServer/Http/Description/HttpOperationDescriptionExtensionMethods.cs

#
C# | 204 lines | 143 code | 32 blank | 29 comment | 38 complexity | bb0dcc5c73d44c9cb14a03e45f10cb75 MD5 | raw file
  1// <copyright>
  2//   Copyright (c) Microsoft Corporation.  All rights reserved.
  3// </copyright>
  4
  5namespace Microsoft.ApplicationServer.Http.Description
  6{
  7    using System;
  8    using System.ComponentModel;
  9    using System.Net.Http;
 10    using System.ServiceModel.Description;
 11    using System.ServiceModel.Web;
 12    using System.Text;
 13    using System.Xml;
 14    using Microsoft.Server.Common;
 15
 16    /// <summary>
 17    /// Provides extension methods for <see cref="OperationDescription"/> instances.
 18    /// </summary>
 19    public static class HttpOperationDescriptionExtensionMethods
 20    {
 21        private static readonly Type webGetAttributeType = typeof(WebGetAttribute);
 22        private static readonly Type webInvokeAttributeType = typeof(WebInvokeAttribute);
 23        private static readonly Type descriptionAttributeType = typeof(DescriptionAttribute);
 24
 25        /// <summary>
 26        /// Creates an <see cref="HttpOperationDescription"/> instance based on the given
 27        /// <see cref="OperationDescription"/> instance.
 28        /// </summary>
 29        /// <param name="operation">The <see cref="OperationDescription"/> instance.</param>
 30        /// <returns>A new <see cref="HttpOperationDescription"/> instance.</returns>
 31        public static HttpOperationDescription ToHttpOperationDescription(this OperationDescription operation)
 32        {
 33            if (operation == null)
 34            {
 35                throw Fx.Exception.ArgumentNull("operation");
 36            }
 37
 38            return new HttpOperationDescription(operation);
 39        }
 40
 41        /// <summary>
 42        /// Gets the <see cref="HttpMethod"/> for the given <paramref name="operation"/>.
 43        /// </summary>
 44        /// <param name="operation">The <see cref="HttpOperationDescription"/> instance.</param>
 45        /// <returns>The <see cref="HttpMethod"/>.</returns>
 46        public static HttpMethod GetHttpMethod(this HttpOperationDescription operation)
 47        {
 48            if (operation == null)
 49            {
 50                throw Fx.Exception.ArgumentNull("operation");
 51            }
 52
 53            return new HttpMethod(GetWebMethod(operation));
 54        }
 55
 56        /// <summary>
 57        /// Gets the <see cref="UriTemplate"/> associated with the given <paramref name="operation"/>.
 58        /// </summary>
 59        /// <param name="operation">The <see cref="HttpOperationDescription"/> instance.</param>
 60        /// <returns>The <see cref="UriTemplate"/>.</returns>
 61        public static UriTemplate GetUriTemplate(this HttpOperationDescription operation)
 62        {
 63            // AutoRedirect is default TrailingSlashMode
 64            return GetUriTemplate(operation, TrailingSlashMode.AutoRedirect);
 65        }
 66
 67        /// <summary>
 68        /// Gets the <see cref="UriTemplate"/> associated with the given <paramref name="operation"/>.
 69        /// </summary>
 70        /// <param name="operation">The <see cref="HttpOperationDescription"/> instance.</param>
 71        /// <param name="trailingSlashMode">The <see cref="TrailingSlashMode"/> option to use for the <see cref="UriTemplate"/>.</param>
 72        /// <returns>The <see cref="UriTemplate"/>.</returns>
 73        public static UriTemplate GetUriTemplate(this HttpOperationDescription operation, TrailingSlashMode trailingSlashMode)
 74        {
 75            if (operation == null)
 76            {
 77                throw Fx.Exception.ArgumentNull("operation");
 78            }
 79
 80            TrailingSlashModeHelper.Validate(trailingSlashMode, "trailingSlashMode");
 81
 82            return new UriTemplate(operation.GetUriTemplateStringOrDefault(), trailingSlashMode == TrailingSlashMode.Ignore);
 83        }
 84
 85        internal static string GetDescription(this HttpOperationDescription operation)
 86        {
 87            Fx.Assert(operation != null, "The 'operation' parameter should not be null.");
 88
 89            OperationDescription operationDescription = operation.ToOperationDescription();
 90
 91            object[] attributes = null;
 92            if (operationDescription.SyncMethod != null)
 93            {
 94                attributes = operationDescription.SyncMethod.GetCustomAttributes(descriptionAttributeType, true);
 95            }
 96            else if (operationDescription.BeginMethod != null)
 97            {
 98                attributes = operationDescription.BeginMethod.GetCustomAttributes(descriptionAttributeType, true);
 99            }
100
101            if (attributes != null && attributes.Length > 0)
102            {
103                return ((DescriptionAttribute)attributes[0]).Description;
104            }
105            else
106            {
107                return String.Empty;
108            }
109        }
110
111        private static string GetWebMethod(this HttpOperationDescription operation)
112        {
113            Fx.Assert(operation != null, "The 'operation' parameter should not be null.");
114
115            WebGetAttribute webGet = operation.Behaviors.Find<WebGetAttribute>();
116            WebInvokeAttribute webInvoke = operation.Behaviors.Find<WebInvokeAttribute>();
117            EnsureOneOneWebAttribute(webGet, webInvoke, operation);
118            if (webGet != null)
119            {
120                return HttpMethod.Get.ToString();
121            }
122
123            if (webInvoke == null)
124            {
125                return HttpMethod.Post.ToString();
126            }
127
128            return webInvoke.Method ?? HttpMethod.Post.ToString();
129        }
130
131        private static string GetWebUriTemplate(this HttpOperationDescription operation)
132        {
133            Fx.Assert(operation != null, "The 'operation' parameter should not be null.");
134
135            WebGetAttribute webGet = operation.Behaviors.Find<WebGetAttribute>();
136            WebInvokeAttribute webInvoke = operation.Behaviors.Find<WebInvokeAttribute>();
137            EnsureOneOneWebAttribute(webGet, webInvoke, operation);
138            if (webGet != null)
139            {
140                return webGet.UriTemplate;
141            }
142
143            if (webInvoke != null)
144            {
145                return webInvoke.UriTemplate;
146            }
147
148            return null;
149        }
150
151        private static string GetUriTemplateStringOrDefault(this HttpOperationDescription operation)
152        {
153            Fx.Assert(operation != null, "The 'operation' parameter should not be null.");
154
155            string webUriTemplate = GetWebUriTemplate(operation);
156            if ((webUriTemplate == null) && (GetWebMethod(operation) == HttpMethod.Get.ToString()))
157            {
158                webUriTemplate = MakeDefaultGetUriTemplateString(operation);
159            }
160
161            if (webUriTemplate == null)
162            {
163                webUriTemplate = operation.Name;
164            }
165
166            return webUriTemplate;
167        }
168
169        private static string MakeDefaultGetUriTemplateString(this HttpOperationDescription operation)
170        {
171            Fx.Assert(operation != null, "The 'operation' parameter should not be null.");
172
173            StringBuilder builder = new StringBuilder(XmlConvert.DecodeName(operation.Name));
174            builder.Append("?");
175
176            foreach (HttpParameter parameterDescription in operation.InputParameters)
177            {
178                string decodedName = XmlConvert.DecodeName(parameterDescription.Name);
179
180                builder.Append(decodedName);
181                builder.Append("={");
182                builder.Append(decodedName);
183                builder.Append("}&");
184            }
185
186            builder.Remove(builder.Length - 1, 1);
187            return builder.ToString();
188        }
189
190        private static void EnsureOneOneWebAttribute(WebGetAttribute webGet, WebInvokeAttribute webInvoke, HttpOperationDescription operation)
191        {
192            if (webGet != null && webInvoke != null)
193            {
194                throw Fx.Exception.AsError(
195                    new InvalidOperationException(
196                        Http.SR.MultipleWebAttributes(
197                            operation.Name,
198                            operation.DeclaringContract.Name,
199                            webGetAttributeType.Name,
200                            webInvokeAttributeType.Name)));
201            }
202        }
203    }
204}