Пример #1
0
        /// <summary>
        /// Checks a parameter for any <see cref="SendAsHeaderAttribute"/> attributes.
        /// </summary>
        /// <param name="requestBuilder">A request builder instance.</param>
        /// <param name="attrs">The parameters attributes.</param>
        /// <param name="argument">The parameters actual value.</param>
        /// <returns>The request builder instance.</returns>
        internal static HttpRequestBuilder CheckParameterForSendAsHeader(
            this HttpRequestBuilder requestBuilder,
            IEnumerable <Attribute> attrs,
            object argument)
        {
            void AddHeader(string name, string format, object arg)
            {
                if (string.IsNullOrEmpty(format) == false)
                {
                    requestBuilder.AddHeader(
                        name,
                        string.Format(format, arg.ToString()));
                }
                else
                {
                    requestBuilder.AddHeader(
                        name,
                        arg.ToString());
                }
            }

            foreach (var attr in attrs.OfType <SendAsHeaderAttribute>())
            {
                if (typeof(IEnumerable <string>).IsAssignableFrom(argument.GetType()) == true)
                {
                    foreach (var item in (IEnumerable <string>)argument)
                    {
                        AddHeader(attr.Name, attr.Format, item);
                    }
                }
                else
                {
                    AddHeader(attr.Name, attr.Format, argument);
                }
            }

            return(requestBuilder);
        }
Пример #2
0
        /// <summary>
        /// Adds the method headers to a <see cref="HttpRequestBuilder"/>.
        /// </summary>
        /// <param name="requestBuilder">A <see cref="HttpRequestBuilder"/> instance.</param>
        /// <param name="method">The <see cref="MethodInfo"/>.</param>
        /// <param name="names">A list of keys.</param>
        /// <param name="values">A list of values.</param>
        /// <returns>The <see cref="HttpRequestBuilder"/> instance.</returns>
        public static HttpRequestBuilder AddMethodHeaders(
            this HttpRequestBuilder requestBuilder,
            MethodInfo method,
            IEnumerable <string> names,
            IEnumerable <object> values)
        {
            var headerAttrs = method
                              .GetCustomAttributes <AddHeaderAttribute>()
                              .Union(
                method.DeclaringType.GetCustomAttributes <AddHeaderAttribute>());

            if (headerAttrs.Any() == true)
            {
                foreach (var attr in headerAttrs)
                {
                    requestBuilder.AddHeader(
                        attr.Header,
                        attr.Value.ExpandString(names, values));
                }
            }

            return(requestBuilder);
        }
Пример #3
0
        /// <summary>
        /// Checks a parameter for attributes.
        /// </summary>
        /// <param name="requestBuilder">The request builder.</param>
        /// <param name="parm">The parameter.</param>
        /// <param name="argument">The parameters value.</param>
        /// <param name="uri">A variable to receive a Uri.</param>
        /// <param name="formUrlContent">A variable to receive the a value indicating whether or not there is form url content.</param>
        /// <param name="contentDisposition">A variable to receive the a value indicating whether or not there is content disposition.</param>
        internal void CheckParameterAttributes(
            HttpRequestBuilder requestBuilder,
            ParameterInfo parm,
            object argument,
            out string uri,
            out bool formUrlContent,
            out bool contentDisposition)
        {
            uri                = null;
            formUrlContent     = false;
            contentDisposition = false;

            var attrs = parm.GetCustomAttributes();

            if (attrs == null ||
                attrs.Any() == false ||
                argument == null)
            {
                return;
            }

/*
 *          if (requestBuilder.IsContentSet == true)
 *          {
 *              return;
 *          }
 */

            var urlAttr = attrs.OfType <UriAttribute>().FirstOrDefault();

            if (urlAttr != null)
            {
                uri = argument.ToString();
            }

            var sendAsAttr = attrs.OfType <SendAsContentAttribute>().FirstOrDefault();

            if (sendAsAttr != null)
            {
                if (typeof(HttpContent).IsAssignableFrom(parm.ParameterType) == true)
                {
                    requestBuilder.SetContent((HttpContent)argument);
                }
                else if (typeof(Stream).IsAssignableFrom(parm.ParameterType) == true)
                {
                    requestBuilder.SetContent(new StreamContent((Stream)argument));
                }
                else
                {
                    string contType   = sendAsAttr.ContentType ?? this.contentType;
                    var    serializer = this.options.GetObjectSerializer(contType);
                    if (serializer == null)
                    {
                        throw new NotSupportedException($"Serializer for {contType} not found");
                    }

                    requestBuilder.SetContent(new StringContent(
                                                  serializer.SerializeObject(argument),
                                                  sendAsAttr.Encoding ?? Encoding.UTF8,
                                                  serializer.ContentType));
                }

                return;
            }

            var formUrlAttr = attrs.OfType <SendAsFormUrlAttribute>().FirstOrDefault();

            if (formUrlAttr != null)
            {
                formUrlContent = true;
                var argType = argument.GetType();
                if (argument is Dictionary <string, string> strStrDictionayArgument)
                {
                    requestBuilder.SetContent(
                        new FormUrlEncodedContent(
                            (Dictionary <string, string>)argument));
                }
                else if (argument is Dictionary <string, object> strObjDictionaryArgument)
                {
                    requestBuilder.SetContent(
                        new FormUrlEncodedContent(
                            ((Dictionary <string, object>)argument)
                            .Select(
                                kvp =>
                    {
                        return(new KeyValuePair <string, string>(
                                   kvp.Key,
                                   kvp.Value?.ToString()));
                    })));
                }
                else if (parm.ParameterType.IsModelObject() == true)
                {
                    var list       = new Dictionary <string, string>();
                    var properties = argument.GetType().GetProperties();
                    foreach (var property in properties)
                    {
                        list.Add(
                            property.Name,
                            property.GetValue(argument)?.ToString());
                    }

                    requestBuilder.SetContent(new FormUrlEncodedContent(list));
                }
                else
                {
                    requestBuilder.AddFormUrlProperty(
                        formUrlAttr.Name ?? parm.Name,
                        argument.ToString());
                }

                return;
            }

            var contentDispAttr = attrs.OfType <SendAsContentDispositionAttribute>().FirstOrDefault();

            if (contentDispAttr != null)
            {
                contentDisposition = true;
                requestBuilder.SetMultipartContent(true);

                if (contentDispAttr.IsName == true)
                {
                    requestBuilder.SetContentDispositionHeader(c => c.Name = (string)argument);
                }
                else if (contentDispAttr.IsFileName == true)
                {
                    requestBuilder.SetContentDispositionHeader(c => c.FileName = (string)argument);
                }
                else if (contentDispAttr.IsFileNameStar)
                {
                    requestBuilder.SetContentDispositionHeader(c => c.FileNameStar = (string)argument);
                }

                return;
            }

            requestBuilder
            .CheckParameterForSendAsQuery(attrs, parm, argument)
            .CheckParameterForSendAsHeader(attrs, argument);
        }
Пример #4
0
        /// <summary>
        /// Checks the arguments for specific ones.
        /// </summary>
        /// <param name="requestBuilder">A request builder.</param>
        /// <param name="uri">A variable to receive a Uri.</param>
        /// <returns>An array of argument names.</returns>
        private string[] CheckArgsAndBuildRequest(
            HttpRequestBuilder requestBuilder,
            out string uri)
        {
            uri = null;

            var responseAttr = this.MethodInfo.GetMethodOrTypeAttribute <HttpResponseProcessorAttribute>();

            if (responseAttr != null)
            {
                this.responseProcessorType = responseAttr.ResponseProcesorType;
            }

            var formUrlAttrs = this.MethodInfo.GetCustomAttributes <AddFormUrlEncodedPropertyAttribute>();

            if (formUrlAttrs.Any() == true)
            {
                foreach (var attr in formUrlAttrs)
                {
                    requestBuilder.AddFormUrlProperty(attr.Key, attr.Value);
                }
            }

            Type returnType = this.MethodInfo.ReturnType;

            if (returnType.IsAsync(out Type taskType) == true)
            {
                returnType = taskType;
            }

            bool formUrlContent     = false;
            bool contentDisposition = false;

            ParameterInfo[] parms = this.MethodInfo.GetParameters();
            if (parms == null)
            {
                return(new string[0]);
            }

            string[] names = new string[parms.Length];
            for (int i = 0; i < parms.Length; i++)
            {
                names[i] = parms[i].Name;
                Type parmType = parms[i].ParameterType;

                if (parms[i].IsOut == true)
                {
                    var fromHeader = parms[i].GetCustomAttribute <FromHeaderAttribute>();
                    if (fromHeader != null)
                    {
                        this.fromHeaders = this.fromHeaders ?? new Dictionary <int, string>();
                        this.fromHeaders.Add(i, fromHeader.Name);
                    }
                    else
                    {
                        var fromResponse = parms[i].GetCustomAttribute <FromResponseAttribute>();
                        if (fromResponse != null)
                        {
                            this.fromResponses = this.fromResponses ?? new Dictionary <int, Tuple <FromResponseAttribute, Type> >();
                            this.fromResponses.Add(i, Tuple.Create(fromResponse, parmType.GetElementType()));
                        }
                        else
                        {
                            var elemParmType = parms[i].ParameterType.GetElementType();
                            if (elemParmType == typeof(HttpResponseMessage))
                            {
                                this.responseArg = i;
                            }
                            else
                            {
                                this.dataArg     = i;
                                this.dataArgType = parmType;
                            }
                        }
                    }

                    continue;
                }

                if (returnType != typeof(void) &&
                    parmType == typeof(Func <,>).MakeGenericType(typeof(HttpResponseMessage), returnType))
                {
                    this.responseFuncArg = i;
                }
                else if (parmType == typeof(Action <HttpRequestMessage>))
                {
                    this.requestAction = (Action <HttpRequestMessage>) this.Arguments[i];
                }
                else if (parmType == typeof(Action <HttpResponseMessage>))
                {
                    this.responseAction = (Action <HttpResponseMessage>) this.Arguments[i];
                }
                else if (parmType == typeof(CancellationTokenSource))
                {
                    this.cancellationTokenSource = (CancellationTokenSource)this.Arguments[i];
                }
                else if (parmType == typeof(CancellationToken))
                {
                    this.cancellationToken = (CancellationToken)this.Arguments[i];
                }
                else if (parmType == typeof(IUriBuilder))
                {
                    uri = ((IUriBuilder)this.Arguments[i]).BuildUri().ToString();
                }
                else
                {
                    this.CheckParameterAttributes(
                        requestBuilder,
                        parms[i],
                        this.Arguments[i],
                        out string parmUri,
                        out formUrlContent,
                        out contentDisposition);

                    if (parmUri != null)
                    {
                        uri = parmUri;
                    }

                    if (formUrlContent == false &&
                        requestBuilder.IsContentSet == false &&
                        parms[i].ParameterType.IsModelObject() == true)
                    {
                        var serializer = this.options.GetObjectSerializer(this.contentType);
                        if (serializer == null)
                        {
                            throw new NotSupportedException($"Serializer for {this.contentType} not found");
                        }

                        requestBuilder.SetContent(new StringContent(
                                                      serializer.SerializeObject(this.Arguments[i]),
                                                      Encoding.UTF8,
                                                      this.contentType));
                    }
                }
            }

            return(names);
        }
Пример #5
0
        /// <summary>
        /// Builds a request, sends it, and proecesses the response.
        /// </summary>
        /// <param name="httpMethod">The http method.</param>
        /// <param name="baseUri">The base Uri.</param>
        /// <param name="uriPath">The Uri path.</param>
        /// <param name="contentType">The content type.</param>
        /// <param name="timeout">A value representing the request timeout.</param>
        /// <returns>The result of the request.</returns>
        public async Task <object> BuildAndSendRequestAsync(
            HttpMethod httpMethod,
            string baseUri,
            string uriPath,
            string contentType,
            TimeSpan?timeout)
        {
            var requestBuilder = new HttpRequestBuilder()
                                 .SetMethod(httpMethod)
                                 .SetHttpVersion(this.options.HttpVersion);

            var names = this.CheckArgsAndBuildRequest(requestBuilder, out string uri);

            if (string.IsNullOrWhiteSpace(uri) == false)
            {
                baseUri = uri;
            }

            requestBuilder
            .AddMethodHeaders(this.MethodInfo, names, this.Arguments)
            .SetUri(Utility.CombineUri(baseUri, uriPath.ExpandString(names, this.Arguments)));

            Type returnType = this.MethodInfo.ReturnType;

            await requestBuilder.AddAuthorizationHeaderAsync(
                this.MethodInfo,
                names,
                this.Arguments,
                this.options.Services);

            HttpCompletionOption completionOption = HttpCompletionOption.ResponseContentRead;

            if (returnType == typeof(HttpResponseMessage) ||
                returnType == typeof(Task <HttpResponseMessage>) ||
                returnType == typeof(Task <Stream>))
            {
                completionOption = HttpCompletionOption.ResponseHeadersRead;
            }

            if (timeout.HasValue == true)
            {
                this.SetTimeout(timeout.Value);
            }

            var httpRequestSenderFactory = this.options.Services?.GetService <IHttpRequestSenderFactory>();

            var httpClient    = this.options.GetHttpClient();
            var requestSender = httpRequestSenderFactory?.CreateRequestSender(httpClient, this) ??
                                new HttpRequestSender(httpClient, this);

            if (returnType.IsAsync(out Type taskType) == true &&
                taskType != typeof(void))
            {
                Type   asyncType = typeof(AsyncCall <>).MakeGenericType(taskType);
                object obj       = Activator.CreateInstance(asyncType, requestSender, this);
                var    mi        = asyncType.GetMethod("SendAsync", new Type[] { typeof(HttpRequestBuilder), typeof(HttpCompletionOption) });
                return(mi.Invoke(obj, new object[] { requestBuilder, completionOption }));
            }

            var response = await requestSender
                           .SendAsync(
                requestBuilder,
                completionOption)
                           .ConfigureAwait(false);

            return(await this.ProcessResultAsync(
                       response,
                       returnType));
        }
Пример #6
0
        /// <summary>
        /// Checks a parameter for any <see cref="SendAsQueryAttribute"/> attributes.
        /// </summary>
        /// <param name="requestBuilder">A request builder instance.</param>
        /// <param name="attrs">The parameters attributes.</param>
        /// <param name="parm">The parameter.</param>
        /// <param name="argument">The parameters actual value.</param>
        /// <returns>The request builder instance.</returns>
        internal static HttpRequestBuilder CheckParameterForSendAsQuery(
            this HttpRequestBuilder requestBuilder,
            IEnumerable <Attribute> attrs,
            ParameterInfo parm,
            object argument)
        {
            foreach (var query in attrs.OfType <SendAsQueryAttribute>())
            {
                var name = query.Name.IsNullOrEmpty() == false ? query.Name : parm.Name;

                if (parm.ParameterType.IsGenericType == true)
                {
                    if (parm.ParameterType.GetGenericTypeDefinition() == typeof(IDictionary <,>))
                    {
                        IDictionary <string, string> queryMap = null;
                        if (typeof(IDictionary <string, string>).IsAssignableFrom(parm.ParameterType) == true)
                        {
                            queryMap = (IDictionary <string, string>)argument;
                        }
                        else if (typeof(IDictionary <object, object>).IsAssignableFrom(parm.ParameterType) == true)
                        {
                            queryMap = ((IDictionary <object, object>)argument)
                                       .ToDictionary(key => key.Key.ToString(), value => value.Value.ToString());
                        }
                        else if (typeof(IDictionary <string, object>).IsAssignableFrom(parm.ParameterType) == true)
                        {
                            queryMap = ((IDictionary <string, object>)argument)
                                       .ToDictionary(key => key.Key, value => value.Value.ToString());
                        }
                        else if (typeof(IDictionary <object, string>).IsAssignableFrom(parm.ParameterType) == true)
                        {
                            queryMap = ((IDictionary <object, string>)argument)
                                       .ToDictionary(key => key.Key.ToString(), value => value.Value);
                        }

                        if (query != null)
                        {
                            foreach (var item in queryMap)
                            {
                                var value = parm.ConvertParameterValue(item.Value, query.Format, query.Base64, query.Encoding);
                                requestBuilder.AddQueryString(item.Key, value);
                            }
                        }
                    }
                    else if (typeof(IEnumerable <string>).IsAssignableFrom(parm.ParameterType) == true)
                    {
                        foreach (var item in (IEnumerable <string>)argument)
                        {
                            var value = parm.ConvertParameterValue(item, query.Format, query.Base64, query.Encoding);
                            requestBuilder.AddQueryString(name, value);
                        }
                    }
                }
                else
                {
                    var value = parm.ConvertParameterValue(argument, query.Format, query.Base64, query.Encoding);
                    requestBuilder.AddQueryString(name, value);
                }
            }

            return(requestBuilder);
        }