From 9f64cb19169a4ec8758dc854ded3e62668d1b421 Mon Sep 17 00:00:00 2001 From: Scott Lovegrove Date: Tue, 8 Mar 2016 17:48:47 +0000 Subject: [PATCH 1/4] Added Portable Class Library version This is so url requests could be created from other types of clients. --- .../HttpValueCollection.cs | 236 ++++++++++++++++++ ...geResizer.FluentExtensions.Portable.csproj | 90 +++++++ .../Properties/AssemblyInfo.cs | 7 + ImageResizer.FluentExtensions.sln | 10 +- .../ImageUrlBuilder.cs | 10 +- 5 files changed, 349 insertions(+), 4 deletions(-) create mode 100644 ImageResizer.FluentExtensions.Portable/HttpValueCollection.cs create mode 100644 ImageResizer.FluentExtensions.Portable/ImageResizer.FluentExtensions.Portable.csproj create mode 100644 ImageResizer.FluentExtensions.Portable/Properties/AssemblyInfo.cs diff --git a/ImageResizer.FluentExtensions.Portable/HttpValueCollection.cs b/ImageResizer.FluentExtensions.Portable/HttpValueCollection.cs new file mode 100644 index 0000000..3aea741 --- /dev/null +++ b/ImageResizer.FluentExtensions.Portable/HttpValueCollection.cs @@ -0,0 +1,236 @@ +using System; +using System.Collections; +using System.Collections.ObjectModel; +using System.Linq; +using System.Net; +using System.Text; + +namespace ImageResizer.FluentExtensions.Portable +{ + public sealed class HttpUtility + { + public static HttpValueCollection ParseQueryString(string query) + { + if (query == null) + { + throw new ArgumentNullException("query"); + } + + if ((query.Length > 0) && (query[0] == '?')) + { + query = query.Substring(1); + } + + return new HttpValueCollection(query, true); + } + + public static string UrlEncode(string value) + { + return WebUtility.UrlEncode(value); + } + } + + public sealed class HttpValue + { + public HttpValue() + { + } + + public HttpValue(string key, string value) + { + this.Key = key; + this.Value = value; + } + + public string Key { get; set; } + public string Value { get; set; } + } + + public class HttpValueCollection : Collection + { + #region Constructors + + public HttpValueCollection() + { + } + + public HttpValueCollection(string query) + : this(query, true) + { + } + + public HttpValueCollection(string query, bool urlencoded) + { + if (!string.IsNullOrEmpty(query)) + { + this.FillFromString(query, urlencoded); + } + } + + #endregion + + #region Parameters + + public string this[string key] + { + get { return this.First(x => string.Equals(x.Key, key, StringComparison.OrdinalIgnoreCase)).Value; } + set { this.First(x => string.Equals(x.Key, key, StringComparison.OrdinalIgnoreCase)).Value = value; } + } + + #endregion + + #region Public Methods + + public void Add(string key, string value) + { + this.Add(new HttpValue(key, value)); + } + + public void Add(HttpValueCollection collection) + { + foreach (var item in collection) + { + Add(item.Key, item.Value); + } + } + + public bool ContainsKey(string key) + { + return this.Any(x => string.Equals(x.Key, key, StringComparison.OrdinalIgnoreCase)); + } + + public string[] GetValues(string key) + { + return this.Where(x => string.Equals(x.Key, key, StringComparison.OrdinalIgnoreCase)).Select(x => x.Value).ToArray(); + } + + public string[] AllKeys + { + get { return this.Select(x => x.Key).ToArray(); } + } + + public void Remove(string key) + { + var items = this.Where(x => string.Equals(x.Key, key, StringComparison.OrdinalIgnoreCase)) + .ToList(); + foreach (var item in items) + { + this.Remove(item); + } + } + + public override string ToString() + { + return this.ToString(true); + } + + public virtual string ToString(bool urlencoded) + { + return this.ToString(urlencoded, null); + } + + public virtual string ToString(bool urlencoded, IDictionary excludeKeys) + { + if (this.Count == 0) + { + return string.Empty; + } + + StringBuilder stringBuilder = new StringBuilder(); + + foreach (HttpValue item in this) + { + string key = item.Key; + + if ((excludeKeys == null) || !excludeKeys.Contains(key)) + { + string value = item.Value; + + if (urlencoded) + { + // If .NET 4.5 and above (Thanks @Paya) + key = WebUtility.UrlDecode(key); + // If .NET 4.0 use this instead. + // key = Uri.EscapeDataString(key); + } + + if (stringBuilder.Length > 0) + { + stringBuilder.Append('&'); + } + + stringBuilder.Append((key != null) ? (key + "=") : string.Empty); + + if ((value != null) && (value.Length > 0)) + { + if (urlencoded) + { + value = Uri.EscapeDataString(value); + } + + stringBuilder.Append(value); + } + } + } + + return stringBuilder.ToString(); + } + + #endregion + + #region Private Methods + + private void FillFromString(string query, bool urlencoded) + { + int num = (query != null) ? query.Length : 0; + for (int i = 0; i < num; i++) + { + int startIndex = i; + int num4 = -1; + while (i < num) + { + char ch = query[i]; + if (ch == '=') + { + if (num4 < 0) + { + num4 = i; + } + } + else if (ch == '&') + { + break; + } + i++; + } + string str = null; + string str2 = null; + if (num4 >= 0) + { + str = query.Substring(startIndex, num4 - startIndex); + str2 = query.Substring(num4 + 1, (i - num4) - 1); + } + else + { + str2 = query.Substring(startIndex, i - startIndex); + } + + if (urlencoded) + { + this.Add(Uri.UnescapeDataString(str), Uri.UnescapeDataString(str2)); + } + else + { + this.Add(str, str2); + } + + if ((i == (num - 1)) && (query[i] == '&')) + { + this.Add(null, string.Empty); + } + } + } + + #endregion + } +} diff --git a/ImageResizer.FluentExtensions.Portable/ImageResizer.FluentExtensions.Portable.csproj b/ImageResizer.FluentExtensions.Portable/ImageResizer.FluentExtensions.Portable.csproj new file mode 100644 index 0000000..3348c8b --- /dev/null +++ b/ImageResizer.FluentExtensions.Portable/ImageResizer.FluentExtensions.Portable.csproj @@ -0,0 +1,90 @@ + + + + + 11.0 + Debug + AnyCPU + {2D6D2C3F-8E07-4D36-92D2-B547A292C458} + Library + Properties + ImageResizer.FluentExtensions.Portable + ImageResizer.FluentExtensions.Portable + en-US + 512 + {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + Profile259 + v4.5 + + + true + full + false + bin\Debug\ + TRACE;DEBUG;PORTABLE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + Properties\CommonAssemblyInfo.cs + + + AlignmentExpression.cs + + + DropShadowExpression.cs + + + GradientExpression.cs + + + ImageUrlBuilder.cs + + + ImageUrlBuilderExpression.cs + + + MiscExtensions.cs + + + ModifierExtensions.cs + + + NumberExtensions.cs + + + OutputExpression.cs + + + ResizeExpression.cs + + + SimpleFiltersExpression.cs + + + StyleExpression.cs + + + TransformExpression.cs + + + + + + + \ No newline at end of file diff --git a/ImageResizer.FluentExtensions.Portable/Properties/AssemblyInfo.cs b/ImageResizer.FluentExtensions.Portable/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..cca32b8 --- /dev/null +++ b/ImageResizer.FluentExtensions.Portable/Properties/AssemblyInfo.cs @@ -0,0 +1,7 @@ +using System.Reflection; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("Fluent Extensions for Image Resizer (Portable Class Library)")] +[assembly: AssemblyDescription("Portable Class Library Helpers for generating Image Resizer URL api requests.")] \ No newline at end of file diff --git a/ImageResizer.FluentExtensions.sln b/ImageResizer.FluentExtensions.sln index 38c0f2f..0005a27 100644 --- a/ImageResizer.FluentExtensions.sln +++ b/ImageResizer.FluentExtensions.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 2013 -VisualStudioVersion = 12.0.31101.0 +# Visual Studio 14 +VisualStudioVersion = 14.0.24720.0 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{16881C95-E325-4AF5-BA38-048BB9649722}" ProjectSection(SolutionItems) = preProject @@ -27,6 +27,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ImageResizer.FluentExtensio EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ImageResizer.FluentExtensions.Tests", "tests\ImageResizer.FluentExtensions.Tests\ImageResizer.FluentExtensions.Tests.csproj", "{1ABDEC38-BA6A-4D24-A324-0C0D790413C8}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ImageResizer.FluentExtensions.Portable", "ImageResizer.FluentExtensions.Portable\ImageResizer.FluentExtensions.Portable.csproj", "{2D6D2C3F-8E07-4D36-92D2-B547A292C458}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -49,6 +51,10 @@ Global {1ABDEC38-BA6A-4D24-A324-0C0D790413C8}.Debug|Any CPU.Build.0 = Debug|Any CPU {1ABDEC38-BA6A-4D24-A324-0C0D790413C8}.Release|Any CPU.ActiveCfg = Release|Any CPU {1ABDEC38-BA6A-4D24-A324-0C0D790413C8}.Release|Any CPU.Build.0 = Release|Any CPU + {2D6D2C3F-8E07-4D36-92D2-B547A292C458}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2D6D2C3F-8E07-4D36-92D2-B547A292C458}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2D6D2C3F-8E07-4D36-92D2-B547A292C458}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2D6D2C3F-8E07-4D36-92D2-B547A292C458}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/src/ImageResizer.FluentExtensions/ImageUrlBuilder.cs b/src/ImageResizer.FluentExtensions/ImageUrlBuilder.cs index 98ef4fb..4aacac1 100644 --- a/src/ImageResizer.FluentExtensions/ImageUrlBuilder.cs +++ b/src/ImageResizer.FluentExtensions/ImageUrlBuilder.cs @@ -1,8 +1,14 @@ using System; using System.Collections.Generic; -using System.Collections.Specialized; using System.Linq; + +#if PORTABLE +using NameValueCollection = ImageResizer.FluentExtensions.Portable.HttpValueCollection; +using HttpUtility = ImageResizer.FluentExtensions.Portable.HttpUtility; +#else +using System.Collections.Specialized; using System.Web; +#endif namespace ImageResizer.FluentExtensions { @@ -69,7 +75,7 @@ public ImageUrlBuilder SetParameter(string parameterName, string parameterValue) if (string.IsNullOrEmpty(parameterValue)) throw new ArgumentNullException("parameterValue"); - configuration.Set(parameterName, parameterValue); + configuration[parameterName] = parameterValue; return this; } From 73eec4c7b8708a506634599c3dd703ced5ea4e77 Mon Sep 17 00:00:00 2001 From: Scott Lovegrove Date: Tue, 8 Mar 2016 17:53:21 +0000 Subject: [PATCH 2/4] Added PORTABLE to release mode --- .../ImageResizer.FluentExtensions.Portable.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ImageResizer.FluentExtensions.Portable/ImageResizer.FluentExtensions.Portable.csproj b/ImageResizer.FluentExtensions.Portable/ImageResizer.FluentExtensions.Portable.csproj index 3348c8b..ddd899e 100644 --- a/ImageResizer.FluentExtensions.Portable/ImageResizer.FluentExtensions.Portable.csproj +++ b/ImageResizer.FluentExtensions.Portable/ImageResizer.FluentExtensions.Portable.csproj @@ -29,7 +29,7 @@ pdbonly true bin\Release\ - TRACE + TRACE;PORTABLE prompt 4 From c5f6b68d89c64baa20ff3c8e4d02187f019c1168 Mon Sep 17 00:00:00 2001 From: Scott Lovegrove Date: Tue, 8 Mar 2016 18:43:13 +0000 Subject: [PATCH 3/4] Fix Collection behaviour --- src/ImageResizer.FluentExtensions/ImageUrlBuilder.cs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/ImageResizer.FluentExtensions/ImageUrlBuilder.cs b/src/ImageResizer.FluentExtensions/ImageUrlBuilder.cs index 4aacac1..6234df9 100644 --- a/src/ImageResizer.FluentExtensions/ImageUrlBuilder.cs +++ b/src/ImageResizer.FluentExtensions/ImageUrlBuilder.cs @@ -75,7 +75,15 @@ public ImageUrlBuilder SetParameter(string parameterName, string parameterValue) if (string.IsNullOrEmpty(parameterValue)) throw new ArgumentNullException("parameterValue"); - configuration[parameterName] = parameterValue; + if (configuration.ContainsKey(parameterName)) + { + configuration[parameterName] = parameterValue; + } + else + { + configuration.Add(parameterName, parameterValue); + } + return this; } From 42ce265f1f043014084d9e6d405e824438ccfe24 Mon Sep 17 00:00:00 2001 From: Scott Lovegrove Date: Tue, 8 Mar 2016 18:46:44 +0000 Subject: [PATCH 4/4] Another collection update --- .../HttpValueCollection.cs | 12 ++++++++++++ src/ImageResizer.FluentExtensions/ImageUrlBuilder.cs | 9 +-------- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/ImageResizer.FluentExtensions.Portable/HttpValueCollection.cs b/ImageResizer.FluentExtensions.Portable/HttpValueCollection.cs index 3aea741..56b7971 100644 --- a/ImageResizer.FluentExtensions.Portable/HttpValueCollection.cs +++ b/ImageResizer.FluentExtensions.Portable/HttpValueCollection.cs @@ -94,6 +94,18 @@ public void Add(HttpValueCollection collection) } } + public void Set(string key, string value) + { + if (ContainsKey(key)) + { + this[key] = value; + } + else + { + Add(key, value); + } + } + public bool ContainsKey(string key) { return this.Any(x => string.Equals(x.Key, key, StringComparison.OrdinalIgnoreCase)); diff --git a/src/ImageResizer.FluentExtensions/ImageUrlBuilder.cs b/src/ImageResizer.FluentExtensions/ImageUrlBuilder.cs index 6234df9..88d2269 100644 --- a/src/ImageResizer.FluentExtensions/ImageUrlBuilder.cs +++ b/src/ImageResizer.FluentExtensions/ImageUrlBuilder.cs @@ -75,14 +75,7 @@ public ImageUrlBuilder SetParameter(string parameterName, string parameterValue) if (string.IsNullOrEmpty(parameterValue)) throw new ArgumentNullException("parameterValue"); - if (configuration.ContainsKey(parameterName)) - { - configuration[parameterName] = parameterValue; - } - else - { - configuration.Add(parameterName, parameterValue); - } + configuration.Set(parameterName, parameterValue); return this; }