Default CommonAssemblyInfo.cs.

Default CommonAssemblyInfo.cs.

--- src/CommonAssemblyInfo.cs
+++ src/CommonAssemblyInfo.cs
@@ -1,26 +1,22 @@
+using System.Runtime.CompilerServices;
 using System.Reflection;
-using System.Runtime.CompilerServices;
 using System.Runtime.InteropServices;
-[assembly: AssemblyCompany("Mark Rendle")]
-[assembly: AssemblyProduct("Simple.Web")]
+[assembly: AssemblyCompany("Mark Rendle, Ian Battersby, and contributors")]
+[assembly: AssemblyProduct("Simple.Http")]
 [assembly: AssemblyCopyright("Copyright (C) Mark Rendle 2012")]
+[assembly: AssemblyTrademark("ed24ec86facd46e32133f2aa5729e8322cd7ae29")]
 [assembly: ComVisible(false)]
-[assembly: AssemblyVersion("0.0.0.0")]
-[assembly: AssemblyFileVersion("0.0.0.0")]
+[assembly: AssemblyVersion("0.10.0.51924")]
+[assembly: AssemblyFileVersion("0.10.0.51924")]

 [assembly: AssemblyConfiguration("Release")]
-[assembly: AssemblyInformationalVersion("0.0.0.0")]
+[assembly: AssemblyInformationalVersion("0.10.0.51924")]

-[assembly: InternalsVisibleTo("Simple.Web.Autofac.Tests")]
-[assembly: InternalsVisibleTo("Simple.Web.CodeGeneration.Tests")]
-[assembly: InternalsVisibleTo("Simple.Web.ContentTypeHandling.Tests")]
-[assembly: InternalsVisibleTo("Simple.Web.HalJson.Tests")]
-[assembly: InternalsVisibleTo("Simple.Web.JsonFx.Tests")]
-[assembly: InternalsVisibleTo("Simple.Web.JsonNet.Tests")]
-[assembly: InternalsVisibleTo("Simple.Web.Ninject.Tests")]
-[assembly: InternalsVisibleTo("Simple.Web.Razor.Tests")]
-[assembly: InternalsVisibleTo("Simple.Web.Routing.Tests")]
-[assembly: InternalsVisibleTo("Simple.Web.StructureMap.Tests")]
-[assembly: InternalsVisibleTo("Simple.Web.Windsor.Tests")]
-[assembly: InternalsVisibleTo("Simple.Web.Tests")]
-[assembly: InternalsVisibleTo("Simple.Web.Xml.Tests")]
+[assembly: InternalsVisibleTo("Simple.Http.CodeGeneration.Tests")]
+[assembly: InternalsVisibleTo("Simple.Http.ContentTypeHandling.Tests")]
+[assembly: InternalsVisibleTo("Simple.Http.HalJson.Tests")]
+[assembly: InternalsVisibleTo("Simple.Http.JsonNet.Tests")]
+[assembly: InternalsVisibleTo("Simple.Http.Routing.Tests")]
+[assembly: InternalsVisibleTo("Simple.Http.StructureMap.Tests")]
+[assembly: InternalsVisibleTo("Simple.Http.Tests")]
+[assembly: InternalsVisibleTo("Simple.Http.Xml.Tests")]


BugFix

BugFix

    When null was emitted for the value it was failing.
New behavior assigns null to Rev when _rev cannot be found in the value emitted.

--- src/CouchQueryDocument.cs
+++ src/CouchQueryDocument.cs
@@ -13,7 +13,8 @@
         {
             Id = obj["id"].Value<string>();
             Key = obj["key"].Value<string>();
-            Rev = (obj["value"].Value<JObject>())["rev"].Value<string>();
+        	var tmp = obj["value"];
+			Rev = tmp.ToString() == "null" ? null : tmp.Value<JObject>()["_rev"].Value<string>(); //Rev is null if the value emitted is not doc or does not contain _rev
         }
     }
 }


added log out

added log out


Adding priority queue class (for A* path finding)


Add ModuleDefMD.ReadCustomAttribute() method

--- src/DotNet/ModuleDefMD.cs
+++ src/DotNet/ModuleDefMD.cs
@@ -1386,5 +1386,20 @@
 			}
 			return imageStream;
 		}
+
+		/// <summary>
+		/// Reads a <see cref="CustomAttribute"/>
+		/// </summary>
+		/// <param name="caRid">Custom attribute rid</param>
+		/// <returns>A new <see cref="CustomAttribute"/> instance or <c>null</c> if
+		/// <paramref name="caRid"/> is invalid</returns>
+		public CustomAttribute ReadCustomAttribute(uint caRid) {
+			var caRow = TablesStream.ReadCustomAttributeRow(caRid);
+			if (caRow == null)
+				return null;
+			var ctor = ResolveCustomAttributeType(caRow.Type);
+			var value = caRow.Value;
+			return CustomAttributeReader.Read(this, ctor, value);
+		}
 	}
 }


Removed assemly file

Removed assemly file

--- solution/xmisc.backbone.identifiers.concretes/Properties/AssemblyInfo.cs
+++ solution/xmisc.backbone.identifiers.concretes/Properties/AssemblyInfo.cs
@@ -1,34 +0,0 @@
-
-// 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.
-
-using System.Reflection;
-
-[assembly: AssemblyTitle("xmisc.backbone.identifiers.contracts")]
-[assembly: AssemblyDescription("Implementation of backbone identifiers.")]
-#if DEBUG
-[assembly: AssemblyConfiguration("Debug")]
-#else
-[assembly: AssemblyConfiguration("Release")]
-#endif
-[assembly: AssemblyCompany("Reflektiv")]
-[assembly: AssemblyProduct("xmisc.backbone.identifiers.contracts")]
-[assembly: AssemblyCopyright("Copyright (c) 2015 - 2020, Reflektiv")]
-[assembly: AssemblyTrademark("")]
-[assembly: AssemblyCulture("")]
-
-
-[assembly: AssemblyVersion(
-    ThisAssembly.Git.BaseVersion.Major + "." +
-    ThisAssembly.Git.BaseVersion.Minor + "." +
-    ThisAssembly.Git.BaseVersion.Patch)]
-[assembly: AssemblyFileVersion(
-    ThisAssembly.Git.SemVer.Major + "." +
-    ThisAssembly.Git.SemVer.Minor + "." +
-    ThisAssembly.Git.SemVer.Patch)]
-[assembly: AssemblyInformationalVersion(
-    ThisAssembly.Git.SemVer.Major + "." +
-    ThisAssembly.Git.SemVer.Minor + "." +
-    ThisAssembly.Git.SemVer.Patch +
-    ThisAssembly.Git.SemVer.DashLabel)]


SubscriberChanged -> EndpointsChanged

SubscriberChanged -> EndpointsChanged

--- src/Chatham.Kit.ServiceDiscovery.Abstractions/ICacheServiceSubscriber.cs
+++ src/Chatham.Kit.ServiceDiscovery.Abstractions/ICacheServiceSubscriber.cs
@@ -9,6 +9,6 @@
         Task StartSubscription();
         Task StartSubscription(CancellationToken ct);

-        event EventHandler SubscriberChanged;
+        event EventHandler EndpointsChanged;
     }
 }


Add handler for draft apprenticeship updated event

--- src/CommitmentsV2/SFA.DAS.CommitmentsV2.TestSubscriber/GenericHandler.cs
+++ src/CommitmentsV2/SFA.DAS.CommitmentsV2.TestSubscriber/GenericHandler.cs
@@ -94,4 +94,11 @@
             return Log(message, context);
         }
     }
+    class DraftApprenticeshipUpdatedEventHandler : GenericHandler, IHandleMessages<SFA.DAS.CommitmentsV2.Messages.Events.DraftApprenticeshipUpdatedEvent>
+    {
+        public Task Handle(DraftApprenticeshipUpdatedEvent message, IMessageHandlerContext context)
+        {
+            return Log(message, context);
+        }
+    }
 }


The browse for path link should always work

--- src/GitHub.VisualStudio/UI/Views/Controls/RepositoryCloneControl.xaml.cs
+++ src/GitHub.VisualStudio/UI/Views/Controls/RepositoryCloneControl.xaml.cs
@@ -39,7 +39,6 @@
                 d(this.Bind(ViewModel, vm => vm.BaseRepositoryPath, v => v.clonePath.Text));
                 d(this.OneWayBind(ViewModel, vm => vm.BaseRepositoryPathValidator, v => v.pathValidationMessage.ReactiveValidator));
                 d(this.BindCommand(ViewModel, vm => vm.BrowseForDirectory, v => v.browsePathButton));
-                d(this.Bind(ViewModel, vm => vm.CanClone, v => v.browsePathButton.IsEnabled));
                 d(this.BindCommand(ViewModel, vm => vm.CloneCommand, v => v.cloneButton));
                 d(this.OneWayBind(ViewModel, vm => vm.FilterTextIsEnabled, v => v.filterText.IsEnabled));
                 d(this.Bind(ViewModel, vm => vm.FilterText, v => v.filterText.Text));


Adding workaround to compilation for web host

--- src/Microsoft.AspNet.Mvc.Razor/Compilation/CscBasedCompilationService.cs
+++ src/Microsoft.AspNet.Mvc.Razor/Compilation/CscBasedCompilationService.cs
@@ -28,7 +28,11 @@
             string outFile = Path.Combine(_tempDir, Path.GetRandomFileName() + ".dll");
             StringBuilder args = new StringBuilder("/target:library ");
             args.AppendFormat("/out:\"{0}\" ", outFile);
-            foreach (var file in Directory.EnumerateFiles(Directory.GetCurrentDirectory(), "*.dll"))
+
+            string binDir = Path.Combine(Directory.GetCurrentDirectory(), "bin");
+            // In the k-world, CurrentDir happens to be the bin dir
+            binDir = Directory.Exists(binDir) ? binDir : Directory.GetCurrentDirectory();
+            foreach (var file in Directory.EnumerateFiles(binDir, "*.dll"))
             {
                 args.AppendFormat("/R:\"{0}\" ", file);
             }


Improve perf of TryGetAsciiString

Improve perf of TryGetAsciiString

--- src/Microsoft.AspNetCore.Server.Kestrel/Infrastructure/AsciiUtilities.cs
+++ src/Microsoft.AspNetCore.Server.Kestrel/Infrastructure/AsciiUtilities.cs
@@ -8,73 +8,72 @@
         public static unsafe bool TryGetAsciiString(byte* input, char* output, int count)
         {
             var i = 0;
-            int orValue = 0;
-            bool hasZero = false;
+            sbyte* signedInput = (sbyte*)input;
+
+            bool isValid = true;
             while (i < count - 11)
             {
-                orValue |= *input | *(input + 1) | *(input + 2) | *(input + 3) | *(input + 4) | *(input + 5) |
-                    *(input + 6) | *(input + 7) | *(input + 8) | *(input + 9) | *(input + 10) | *(input + 11);
-                hasZero = hasZero || *input == 0 || *(input + 1) == 0 || *(input + 2) == 0 || *(input + 3) == 0 ||
-                    *(input + 4) == 0 || *(input + 5) == 0 || *(input + 6) == 0 || *(input + 7) == 0 ||
-                    *(input + 8) == 0 || *(input + 9) == 0 || *(input + 10) == 0 || *(input + 11) == 0;
+                isValid = isValid && *signedInput > 0 && *(signedInput + 1) > 0 && *(signedInput + 2) > 0 &&
+                    *(signedInput + 3) > 0 && *(signedInput + 4) > 0 && *(signedInput + 5) > 0 && *(signedInput + 6) > 0 &&
+                    *(signedInput + 7) > 0 && *(signedInput + 8) > 0 && *(signedInput + 9) > 0 && *(signedInput + 10) > 0 &&
+                    *(signedInput + 11) > 0;

                 i += 12;
-                *(output) = (char)*(input);
-                *(output + 1) = (char)*(input + 1);
-                *(output + 2) = (char)*(input + 2);
-                *(output + 3) = (char)*(input + 3);
-                *(output + 4) = (char)*(input + 4);
-                *(output + 5) = (char)*(input + 5);
-                *(output + 6) = (char)*(input + 6);
-                *(output + 7) = (char)*(input + 7);
-                *(output + 8) = (char)*(input + 8);
-                *(output + 9) = (char)*(input + 9);
-                *(output + 10) = (char)*(input + 10);
-                *(output + 11) = (char)*(input + 11);
+                *(output) = (char)*(signedInput);
+                *(output + 1) = (char)*(signedInput + 1);
+                *(output + 2) = (char)*(signedInput + 2);
+                *(output + 3) = (char)*(signedInput + 3);
+                *(output + 4) = (char)*(signedInput + 4);
+                *(output + 5) = (char)*(signedInput + 5);
+                *(output + 6) = (char)*(signedInput + 6);
+                *(output + 7) = (char)*(signedInput + 7);
+                *(output + 8) = (char)*(signedInput + 8);
+                *(output + 9) = (char)*(signedInput + 9);
+                *(output + 10) = (char)*(signedInput + 10);
+                *(output + 11) = (char)*(signedInput + 11);
                 output += 12;
-                input += 12;
+                signedInput += 12;
             }
             if (i < count - 5)
             {
-                orValue |= *input | *(input + 1) | *(input + 2) | *(input + 3) | *(input + 4) | *(input + 5);
-                hasZero = hasZero || *input == 0 || *(input + 1) == 0 || *(input + 2) == 0 || *(input + 3) == 0 ||
-                    *(input + 4) == 0 || *(input + 5) == 0;
+                isValid = isValid && *signedInput > 0 && *(signedInput + 1) > 0 && *(signedInput + 2) > 0 &&
+                    *(signedInput + 3) > 0 && *(signedInput + 4) > 0 && *(signedInput + 5) > 0;

                 i += 6;
-                *(output) = (char)*(input);
-                *(output + 1) = (char)*(input + 1);
-                *(output + 2) = (char)*(input + 2);
-                *(output + 3) = (char)*(input + 3);
-                *(output + 4) = (char)*(input + 4);
-                *(output + 5) = (char)*(input + 5);
+                *(output) = (char)*(signedInput);
+                *(output + 1) = (char)*(signedInput + 1);
+                *(output + 2) = (char)*(signedInput + 2);
+                *(output + 3) = (char)*(signedInput + 3);
+                *(output + 4) = (char)*(signedInput + 4);
+                *(output + 5) = (char)*(signedInput + 5);
                 output += 6;
-                input += 6;
+                signedInput += 6;
             }
             if (i < count - 3)
             {
-                orValue |= *input | *(input + 1) | *(input + 2) | *(input + 3);
-                hasZero = hasZero || *input == 0 || *(input + 1) == 0 || *(input + 2) == 0 || *(input + 3) == 0;
+                isValid = isValid && *signedInput > 0 && *(signedInput + 1) > 0 && *(signedInput + 2) > 0 &&
+                    *(signedInput + 3) > 0;

                 i += 4;
-                *(output) = (char)*(input);
-                *(output + 1) = (char)*(input + 1);
-                *(output + 2) = (char)*(input + 2);
-                *(output + 3) = (char)*(input + 3);
+                *(output) = (char)*(signedInput);
+                *(output + 1) = (char)*(signedInput + 1);
+                *(output + 2) = (char)*(signedInput + 2);
+                *(output + 3) = (char)*(signedInput + 3);
                 output += 4;
-                input += 4;
+                signedInput += 4;
             }

             while (i < count)
             {
-                orValue |= *input;
-                hasZero = hasZero || *input == 0;
+                isValid = isValid && *signedInput > 0;
+
                 i++;
-                *output = (char)*input;
+                *output = (char)*signedInput;
                 output++;
-                input++;
+                signedInput++;
             }

-            return (orValue & 0x80) == 0 && !hasZero;
+            return isValid;
         }
     }
 }


Update EquatablesComparer to get most derived implementation of most derived argument type

--- src/NUnitFramework/framework/Constraints/Comparers/EquatablesComparer.cs
+++ src/NUnitFramework/framework/Constraints/Comparers/EquatablesComparer.cs
@@ -61,35 +61,58 @@

         private static MethodInfo FirstImplementsIEquatableOfSecond(Type first, Type second)
         {
-            var pair = new KeyValuePair<Type, MethodInfo>();
+            var mostDerived = default(EquatableMethodImpl);

-            foreach (var xEquatableArgument in GetEquatableGenericArguments(first))
-                if (xEquatableArgument.Key.IsAssignableFrom(second))
-                    if (pair.Key == null || pair.Key.IsAssignableFrom(xEquatableArgument.Key))
-                        pair = xEquatableArgument;
+            foreach (var implementation in GetEquatableImplementations(first))
+            {
+                if (implementation.Argument.IsAssignableFrom(second))
+                {
+                    if (mostDerived.Argument == null)
+                        mostDerived = implementation;
+                    else if (mostDerived.Argument.IsAssignableFrom(implementation.Argument))
+                    {
+                        // Look for method with most-derived of type arg which can be assigned to 'second'
+                        // If there end up being multiple of same type, look for most derived declaring type
+                        if (mostDerived.Argument != implementation.Argument
+                            || mostDerived.Argument.IsAssignableFrom(implementation.Argument))
+                        mostDerived = implementation;
+                    }
+                }
+            }

-            return pair.Value;
+            return mostDerived.Method;
         }

-        private static IList<KeyValuePair<Type, MethodInfo>> GetEquatableGenericArguments(Type type)
+        private static IEnumerable<EquatableMethodImpl> GetEquatableImplementations(Type type)
         {
-            var genericArgs = new List<KeyValuePair<Type, MethodInfo>>();
-
             foreach (Type @interface in type.GetInterfaces())
             {
                 if (@interface.GetTypeInfo().IsGenericType && @interface.GetGenericTypeDefinition().Equals(typeof(IEquatable<>)))
                 {
-                    genericArgs.Add(new KeyValuePair<Type, MethodInfo>(
-                        @interface.GetGenericArguments()[0], @interface.GetMethod("Equals")));
+                    var iMap = type.GetInterfaceMap(@interface);
+                    foreach (var method in iMap.TargetMethods)
+                        yield return new EquatableMethodImpl(method, method.GetParameters()[0].ParameterType, iMap.TargetType);
                 }
             }
-
-            return genericArgs;
         }

         private static bool InvokeFirstIEquatableEqualsSecond(object first, object second, MethodInfo equals)
         {
             return equals != null ? (bool)equals.Invoke(first, new object[] { second }) : false;
         }
+
+        private readonly struct EquatableMethodImpl
+        {
+            public readonly MethodInfo Method { get; }
+            public readonly Type Argument { get; }
+            public readonly Type ImplementingType { get; }
+
+            public EquatableMethodImpl(MethodInfo method, Type arg, Type implType)
+            {
+                ImplementingType = implType;
+                Method = method;
+                Argument = arg;
+            }
+        }
     }
 }


Fixing NRE when setup form is invalid

Fixing NRE when setup form is invalid

--- src/OrchardCore.Modules/OrchardCore.Setup/Controllers/SetupController.cs
+++ src/OrchardCore.Modules/OrchardCore.Setup/Controllers/SetupController.cs
@@ -121,6 +121,8 @@
                 model.TablePrefix = _shellSettings.TablePrefix;
             }

+            model.TimeZones = _clock.GetTimeZones();
+
             if (!ModelState.IsValid)
             {
                 return View(model);


Refactor away early return statements from ClassFixture.Execute(...).

--- src/Fixie/ClassFixture.cs
+++ src/Fixie/ClassFixture.cs
@@ -24,51 +24,55 @@

         public void Execute(Listener listener)
         {
-            foreach (var method in convention.CaseMethods(fixtureClass))
-                Execute(method, listener);
+            foreach (var caseMethod in convention.CaseMethods(fixtureClass))
+                Execute(caseMethod, listener);
         }

         void Execute(MethodInfo caseMethod, Listener listener)
         {
             var @case = new MethodCase(this, caseMethod);

-            object instance;
+            var exceptions = new List<Exception>();
+
+            object instance = null;
+
+            bool instanceCreated = false;

             try
             {
                 instance = Activator.CreateInstance(fixtureClass);
+                instanceCreated = true;
             }
             catch (TargetInvocationException ex)
             {
-                listener.CaseFailed(@case, new[] { ex.InnerException });
-                return;
-            }
-            catch (Exception ex)
-            {
-                listener.CaseFailed(@case, new[] { ex });
-                return;
-            }
-
-            var exceptions = new List<Exception>();
-
-            try
-            {
-                Execute(caseMethod, instance, exceptions);
+                exceptions.Add(ex.InnerException);
             }
             catch (Exception ex)
             {
                 exceptions.Add(ex);
             }

-            try
+            if (instanceCreated)
             {
-                var disposable = instance as IDisposable;
-                if (disposable != null)
-                    disposable.Dispose();
-            }
-            catch (Exception ex)
-            {
-                exceptions.Add(ex);
+                try
+                {
+                    Execute(caseMethod, instance, exceptions);
+                }
+                catch (Exception ex)
+                {
+                    exceptions.Add(ex);
+                }
+
+                try
+                {
+                    var disposable = instance as IDisposable;
+                    if (disposable != null)
+                        disposable.Dispose();
+                }
+                catch (Exception ex)
+                {
+                    exceptions.Add(ex);
+                }
             }

             if (exceptions.Any())


Add support to playCustomLilithGame

Add support to playCustomLilithGame

--- src/GameLauncherFacade.cs
+++ src/GameLauncherFacade.cs
@@ -171,6 +171,7 @@
         private const string sigPlayBossGame = "(Ljava/lang/String;Ljava/lang/String;IIIIIII)Ljava/lang/String;";
         private const string sigPlayMapGame = "(Ljava/lang/String;Ljava/lang/String;II)Ljava/lang/String;";
         private const string sigPlayLilithGame = "(Ljava/lang/String;Ljava/lang/String;IIIILjava/lang/String;I)Ljava/lang/String;";
+        private const string sigPlayCustomLilithGame = "(Ljava/lang/String;Ljava/lang/String;IIIIIILjava/lang/String;I)Ljava/lang/String;";

         private const string coreJarFileName = "mkhx.core-1.0-jar-with-dependencies.jar";
         private const string coreJarVersionFileName = "mkhx.core.version.txt";
@@ -186,7 +187,7 @@
             }
         }

-        public void Initialize(bool tryUpdateCoreJar, string coreJarRemoteBaseUrl = "http://www.mkhx.cc/resources/lib/corejar", string javaHome = null)
+        public void Initialize(bool tryUpdateCoreJar = true, string coreJarRemoteBaseUrl = "http://www.mkhx.cc/resources/lib/corejar", string javaHome = null)
         {
             OnLogging(TraceLevel.Info, string.Format("Initializing GameLauncherFacade...tryUpdateCoreJar = {0}", tryUpdateCoreJar));
             var assemblyDir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
@@ -222,13 +223,21 @@
                     try
                     {
                         var remoteVerUrl = coreJarRemoteBaseUrl + "/" + coreJarVersionFileName;
-                        OnLogging(TraceLevel.Info, string.Format("Downloading version file from {0}...", remoteVerUrl));
-                        var latestVerText = client.DownloadString(remoteVerUrl);
-                        OnLogging(TraceLevel.Info, "Done!");
-                        long latestVer = int.MaxValue;
-                        if (!long.TryParse(latestVerText, out latestVer))
+                        long latestVer = long.MaxValue;
+                        try
                         {
-                            OnLogging(TraceLevel.Warning, string.Format("Server returns an invalid core jar file version: {0}. Force update...", latestVerText));
+                            OnLogging(TraceLevel.Info, string.Format("Downloading version file from {0}...", remoteVerUrl));
+                            var latestVerText = client.DownloadString(remoteVerUrl);
+                            OnLogging(TraceLevel.Info, "Done!");
+                            if (!long.TryParse(latestVerText, out latestVer))
+                            {
+                                OnLogging(TraceLevel.Warning, string.Format("Server returns an invalid core jar file version: {0}. Force update...", latestVerText));
+                            }
+                        }
+                        catch (Exception e)
+                        {
+                            OnLogging(TraceLevel.Error, string.Format("Failed to get remote core jar version: {0}", e));
+                            OnLogging(TraceLevel.Info, "Force update!");
                         }
                         OnLogging(TraceLevel.Info, string.Format("Remote core jar version: {0}", latestVer));
                         if (!jarExists || existingVer < latestVer)
@@ -331,14 +340,25 @@
             return result;
         }

+        public LilithGameResult playCustomLilithGame(string playerDeck, string lilithDeck, int heroLv, int lilithCardAtBuff, int lilithCardHpBuff,
+            LilithGameType gameType, int remainingGuard, int remainingHp, string eventCardNames, int gameCount)
+        {
+            CheckInitialization();
+            object[] args = new object[] { playerDeck, lilithDeck, heroLv, lilithCardAtBuff, lilithCardHpBuff, (int)gameType, remainingGuard, remainingHp, eventCardNames, gameCount };
+            var resultText = jvm.CallStaticMethod<java.lang.String>(facadeClass, "playCustomLilithGame", sigPlayCustomLilithGame, args);
+            var result = JsonConvert.DeserializeObject<LilithGameResult>(resultText);
+            return result;
+        }
+
         public static int Main(string[] args)
         {
-            try
-            {
-                using (var facade = new GameLauncherFacade())
+            using (var facade = new GameLauncherFacade())
+            {
+                try
                 {
                     facade.Logging += (sender, e) => Console.WriteLine("[{0}] {1}", e.Level, e.Message);
-                    facade.Initialize(true);
+                    facade.Initialize();
+                    Console.WriteLine("Testing Arena game...");
                     var result = facade.PlayArenaGame(
                         deck1: "凤凰",
                         deck2: "凤凰",
@@ -355,10 +375,12 @@
                         vc1Text: "Any",         // 玩家1的特殊胜利条件设置，参见http://www.mkhx.cc#help
                         gameCount: 10
                     );
-                    Console.WriteLine(result.ValidationResult);
-                    Console.WriteLine(result.Player1Win);
-                    Console.WriteLine(result.Player2Win);
+                    Console.WriteLine("ValidationResult: {0}", result.ValidationResult);
+                    Console.WriteLine("Player1Win: {0}", result.Player1Win);
+                    Console.WriteLine("Player2Win: {0}", result.Player2Win);
+
                     Console.WriteLine("================");
+                    Console.WriteLine("Testing Boss game...");
                     var bossGameResult = facade.PlayBossGame(
                         playerDeck: "凤凰*10",
                         bossName: "网页版复仇女神",    // 魔神名字参见http://www.mkhx.cc#boss-battle，包括各个版本的不同魔神
@@ -370,19 +392,23 @@
                         guardType: BossGuardType.NormalGuard,
                         gameCount: 20
                     );
-                    Console.WriteLine(bossGameResult.ValidationResult);
-                    Console.WriteLine(bossGameResult.AvgDamage);
-                    Console.WriteLine(bossGameResult.CvDamage);
+                    Console.WriteLine("ValidationResult: {0}", bossGameResult.ValidationResult);
+                    Console.WriteLine("Average Damage: {0}", bossGameResult.AvgDamage);
+                    Console.WriteLine("Damage CV: {0}", bossGameResult.CvDamage);
                     Console.WriteLine("================");
+
+                    Console.WriteLine("Testing Map game...");
                     var mapGameResult = facade.playMapGame(
-                        playerDeck: "精灵法师*10",
+                        playerDeck: "精灵法师*12",
                         mapName: "5-5-3",
                         heroLv: 50,
                         gameCount: 100);
-                    Console.WriteLine(mapGameResult.ValidationResult);
-                    Console.WriteLine(mapGameResult.WinCount);
-                    Console.WriteLine(mapGameResult.AdvWinCount);
+                    Console.WriteLine("ValidationResult: {0}", mapGameResult.ValidationResult);
+                    Console.WriteLine("WinCount: {0}", mapGameResult.WinCount);
+                    Console.WriteLine("AdvWinCount: {0}", mapGameResult.AdvWinCount);
                     Console.WriteLine("================");
+
+                    Console.WriteLine("Testing Lilith game...");
                     var lilithGameResult = facade.playLilithGame(
                         playerDeck: "凤凰*10",
                         lilithName: "困难莉莉丝+陷阱3",       // 莉莉丝识别名，使用【<难度>莉莉丝+<第四技能>】的形式
@@ -392,17 +418,36 @@
                         remainingHp: 5000,                  // 尾刀模式下指定莉莉丝剩余体力
                         eventCardNames: "凤凰,金属巨龙",      // 以半角逗号分隔的活动卡牌名称列表
                         gameCount: 100);
-                    Console.WriteLine(lilithGameResult.ValidationResult);
-                    Console.WriteLine(lilithGameResult.AvgBattleCount);
-                    Console.WriteLine(lilithGameResult.AvgDamageToLilith);
+                    Console.WriteLine("ValidationResult: {0}", lilithGameResult.ValidationResult);
+                    Console.WriteLine("AvgBattleCount: {0}", lilithGameResult.AvgBattleCount);
+                    Console.WriteLine("AvgDamageToLilith: {0}", lilithGameResult.AvgDamageToLilith);
                     Console.WriteLine("================");
+
+                    Console.WriteLine("Testing custom Lilith game...");
+                    var customLilithGameResult = facade.playCustomLilithGame(
+                        playerDeck: "凤凰*10",
+                        lilithDeck: "困难莉莉丝+法力反射10,金属巨龙+弱点攻击9",
+                        heroLv: 50,
+                        lilithCardAtBuff: 150,
+                        lilithCardHpBuff: 150,
+                        gameType: LilithGameType.ClearGuards,
+                        remainingGuard: 1,
+                        remainingHp: 0,
+                        eventCardNames: "凤凰",
+                        gameCount: 50
+                    );
+                    Console.WriteLine("ValidationResult: {0}", customLilithGameResult.ValidationResult);
+                    Console.WriteLine("AvgBattleCount: {0}", customLilithGameResult.AvgBattleCount);
+                    Console.WriteLine("AvgDamageToLilith: {0}", customLilithGameResult.AvgDamageToLilith);
+                    Console.WriteLine("================");
+
                     return 0;
                 }
-            }
-            catch (System.Exception e)
-            {
-                Console.WriteLine(e.ToString() + e.StackTrace);
-                return 1;
+                catch (System.Exception e)
+                {
+                    Console.WriteLine(e.ToString() + e.StackTrace);
+                    return 1;
+                }
             }
         }


Update version to v0.1.1

Update version to v0.1.1

--- src/GlobalAssemblyInfo.cs
+++ src/GlobalAssemblyInfo.cs
@@ -4,5 +4,5 @@
 [assembly: AssemblyProduct("Orleans.Activities - https://github.com/OrleansContrib/Orleans.Activities")]
 [assembly: AssemblyCopyright("Copyright  https://github.com/OrleansContrib 2016")]

-[assembly: AssemblyVersion("0.2.0.0")]
-[assembly: AssemblyInformationalVersion("0.2.0-alpha")]
+[assembly: AssemblyVersion("0.1.1.0")]
+[assembly: AssemblyInformationalVersion("0.1.1")]


ConvertIdToString

ConvertIdToString

--- src/PhantomNet.Entities/_EntityTypes/_Entity/EntityAccessorExtensions.cs
+++ src/PhantomNet.Entities/_EntityTypes/_Entity/EntityAccessorExtensions.cs
@@ -92,7 +92,7 @@
         private static string ConvertIdToString<TKey>(TKey id)
             where TKey : IEquatable<TKey>
         {
-            if (id.Equals(default(TKey)))
+            if (object.Equals(id, default(TKey)))
             {
                 return null;
             }


* #2 X-Forwarded-For may be a comma separated list

--- src/Premotion.AspNet.AppHarbor.Integration/AppHarborIntegrationModule.cs
+++ src/Premotion.AspNet.AppHarbor.Integration/AppHarborIntegrationModule.cs
@@ -26,11 +26,17 @@
 		/// <summary>
 		/// AppHarbor uses an loadbalancer which rewrites the REMOTE_ADDR header. The original user's IP addres is stored in a separate header with this name.
 		/// </summary>
-		private const string ForwardedUserHostAddressHeaderName = "HTTP_X_FORWARDED_FOR";
+		private const string ForwardedForHeaderName = "HTTP_X_FORWARDED_FOR";
 		/// <summary>
 		/// AppHarbor uses an loadbalancer which rewrites the SERVER_PROTOCOL header. The original protocol is stored in a separate header with this name.
 		/// </summary>
+		/// <remarks>http://en.wikipedia.org/wiki/X-Forwarded-For</remarks>
 		private const string ForwardedProtocolHeaderName = "HTTP_X_FORWARDED_PROTO";
+		/// <summary>
+		/// Defines the separator which to use to split the Forwarded for header.
+		/// </summary>
+		/// <remarks>http://en.wikipedia.org/wiki/X-Forwarded-For</remarks>
+		private static readonly string[] ForwardedForAddressesSeparator = new[] {", "};
 		#endregion
 		#region Implementation of IHttpModule
 		/// <summary>
@@ -77,12 +83,17 @@
 			                        	var serverVariables = HttpContext.Current.Request.ServerVariables;

 			                        	// get the forwarder headers
-			                        	var userHostAddress = serverVariables[ForwardedUserHostAddressHeaderName];
-			                        	var protocol = serverVariables[ForwardedProtocolHeaderName];
+			                        	var forwardedFor = serverVariables[ForwardedForHeaderName] ?? string.Empty;
+			                        	var protocol = serverVariables[ForwardedProtocolHeaderName] ?? string.Empty;
 			                        	var isHttps = "HTTPS".Equals(protocol, StringComparison.OrdinalIgnoreCase);

+			                        	// split the forwarded for header by comma+space separated list of IP addresses, the left-most being the farthest downstream client
+			                        	// see http://en.wikipedia.org/wiki/X-Forwarded-For
+			                        	var forwardedForAdresses = forwardedFor.Split(ForwardedForAddressesSeparator, StringSplitOptions.RemoveEmptyEntries);
+			                        	if (forwardedForAdresses.Length > 0)
+			                        		setServerVariable(serverVariables, "REMOTE_ADDR", forwardedForAdresses[0]);
+
 			                        	// set correct headers
-			                        	setServerVariable(serverVariables, "REMOTE_ADDR", userHostAddress);
 			                        	setServerVariable(serverVariables, "HTTPS", isHttps ? "on" : "off");
 			                        	setServerVariable(serverVariables, "SERVER_PORT", isHttps ? "443" : "80");
 			                        	setServerVariable(serverVariables, "SERVER_PORT_SECURE", isHttps ? "1" : "0");


(#313) Save 'AllResponses' as a static memeber

This prohibits multiple consumer event registrations when performing
multiple RPC calls for same message type

--- src/RawRabbit.Operations.Request/Middleware/ResponseConsumeMiddleware.cs
+++ src/RawRabbit.Operations.Request/Middleware/ResponseConsumeMiddleware.cs
@@ -23,10 +23,12 @@

 	public class ResponseConsumeMiddleware : Pipe.Middleware.Middleware
 	{
+		protected static readonly ConcurrentDictionary<IBasicConsumer, ConcurrentDictionary<string, TaskCompletionSource<BasicDeliverEventArgs>>> AllResponses =
+			new ConcurrentDictionary<IBasicConsumer, ConcurrentDictionary<string, TaskCompletionSource<BasicDeliverEventArgs>>>();
+
 		protected readonly IConsumerFactory ConsumerFactory;
 		protected readonly Pipe.Middleware.Middleware ResponsePipe;
 		private readonly ILog _logger = LogProvider.For<ResponseConsumeMiddleware>();
-		protected readonly ConcurrentDictionary<IBasicConsumer, ConcurrentDictionary<string, TaskCompletionSource<BasicDeliverEventArgs>>> AllResponses;
 		protected Func<IPipeContext, ConsumerConfiguration> ResponseConfigFunc;
 		protected Func<IPipeContext, string> CorrelationidFunc;
 		protected Func<IPipeContext, bool> DedicatedConsumerFunc;
@@ -38,7 +40,6 @@
 			DedicatedConsumerFunc = options?.UseDedicatedConsumer ?? (context => context.GetDedicatedResponseConsumer());
 			ConsumerFactory = consumerFactory;
 			ResponsePipe = factory.Create(options.ResponseRecieved);
-			AllResponses = new ConcurrentDictionary<IBasicConsumer, ConcurrentDictionary<string, TaskCompletionSource<BasicDeliverEventArgs>>>();
 		}

 		public override async Task InvokeAsync(IPipeContext context, CancellationToken token)


Increased code coverage for XmlDecryptionTransform from 52% to 93%

Added tests for System.Security.Cryptography.Xml.XmlDecryptionTransform.
Overall code coverage for System.Security.Cryptography.Xml increased from 61.9% to 63%.

Part of #16829

--- src/System.Security.Cryptography.Xml/tests/XmlDecryptionTransformTest.cs
+++ src/System.Security.Cryptography.Xml/tests/XmlDecryptionTransformTest.cs
@@ -9,6 +9,7 @@
 // Licensed to the .NET Foundation under one or more agreements.
 // See the LICENSE file in the project root for more information.

+using System.IO;
 using System.Xml;
 using Xunit;

@@ -21,11 +22,15 @@
         {
             return base.IsTargetElement(inputElement, idValue);
         }
+
+        public XmlNodeList UnprotectedGetInnerXml()
+        {
+            return base.GetInnerXml();
+        }
     }

     public class XmlDecryptionTransformTest
     {
-
         private UnprotectedXmlDecryptionTransform transform;

         public XmlDecryptionTransformTest()
@@ -44,6 +49,201 @@
         {
             XmlDocument doc = new XmlDocument();
             Assert.False(transform.UnprotectedIsTargetElement(doc.DocumentElement, null));
+        }
+
+        [Theory]
+        [InlineData("", "1", true)]
+        [InlineData("", "1", true)]
+        [InlineData("", "1", true)]
+        [InlineData("", "1", false)]
+        [InlineData("", "2", false)]
+        public void IsTargetElement_ValidXml(string xml, string id, bool expectedResult)
+        {
+            XmlDocument doc = new XmlDocument();
+            doc.LoadXml(xml);
+
+            Assert.Equal(expectedResult, transform.UnprotectedIsTargetElement(doc.DocumentElement, id));
+        }
+
+        [Fact]
+        public void AddExceptUri_Null()
+        {
+            Assert.Throws<ArgumentNullException>(() => transform.AddExceptUri(null));
+        }
+
+        [Fact]
+        public void EncryptedXml_NotNull()
+        {
+            Assert.NotNull(transform.EncryptedXml);
+        }
+
+        [Fact]
+        public void InputTypes()
+        {
+            Type[] inputTypes = transform.InputTypes;
+
+            Assert.Equal(2, inputTypes.Length);
+            Assert.Contains(typeof(Stream), inputTypes);
+            Assert.Contains(typeof(XmlDocument), inputTypes);
+        }
+
+        [Fact]
+        public void OutputTypes()
+        {
+            Type[] outputTypes = transform.OutputTypes;
+
+            Assert.Equal(1, outputTypes.Length);
+            Assert.Contains(typeof(XmlDocument), outputTypes);
+        }
+
+        [Fact]
+        public void LoadInnerXml_XmlNull()
+        {
+            Assert.Throws<CryptographicException>(() => transform.LoadInnerXml(null));
+        }
+
+        [Fact]
+        public void LoadInnerXml_XmlNoExcept()
+        {
+            XmlDocument doc = new XmlDocument();
+            doc.LoadXml("");
+
+            transform.LoadInnerXml(doc.ChildNodes);
+
+            Assert.Null(transform.UnprotectedGetInnerXml());
+        }
+
+        [Fact]
+        public void LoadInnerXml_XmlNoUriForExcept()
+        {
+            XmlDocument doc = new XmlDocument();
+            doc.LoadXml(@"<dcrpt:Except xmlns:dcrpt=""http://www.w3.org/2002/07/decrypt#""/>");
+
+            Assert.Throws<CryptographicException>(() => transform.LoadInnerXml(doc.ChildNodes));
+        }
+
+        [Fact]
+        public void LoadInnerXml_XmlValidUriForExcept()
+        {
+            XmlDocument doc = new XmlDocument();
+            doc.LoadXml(@"<dcrpt:Except URI=""#item1"" xmlns:dcrpt=""http://www.w3.org/2002/07/decrypt#""/>");
+
+            transform.LoadInnerXml(doc.ChildNodes);
+
+            Assert.NotNull(transform.UnprotectedGetInnerXml());
+        }
+
+        [Fact]
+        public void LoadStreamInput_CorrectXml()
+        {
+            XmlDocument doc = new XmlDocument();
+            string xml = "<root></root>";
+            doc.LoadXml(xml);
+
+            using (MemoryStream memoryStream = new MemoryStream())
+            using (StreamWriter streamWriter = new StreamWriter(memoryStream, Text.Encoding.Unicode))
+            {
+                streamWriter.Write(xml);
+                streamWriter.Flush();
+                memoryStream.Position = 0;
+
+                transform.LoadInput(memoryStream);
+                XmlDocument output = (XmlDocument)transform.GetOutput();
+
+                Assert.Equal(xml, output.OuterXml);
+            }
+        }
+
+        [Fact]
+        public void GetOutput_WrongType()
+        {
+            XmlDocument doc = new XmlDocument();
+            string xml = "<test />";
+            doc.LoadXml(xml);
+
+            transform.LoadInput(doc);
+            Assert.Throws<ArgumentException>(() => transform.GetOutput(typeof(string)));
+        }
+
+        [Fact]
+        public void GetOutput_XmlNoEncryptedData()
+        {
+            XmlDocument doc = new XmlDocument();
+            string xml = "<test />";
+            doc.LoadXml(xml);
+
+            transform.LoadInput(doc);
+            XmlDocument transformedDocument = (XmlDocument)transform.GetOutput(typeof(XmlDocument));
+
+            Assert.Equal(xml, transformedDocument.OuterXml);
+        }
+
+        [Fact]
+        public void GetOutput_XmlWithEncryptedData()
+        {
+            XmlDocument doc = new XmlDocument();
+            string xml = "<root><c>To Be Encrypted</c><d /></root>";
+            doc.LoadXml(xml);
+
+            XmlDocument transformedDocument = GetTransformedOutput(doc, "c");
+
+            Assert.NotNull(transformedDocument);
+            Assert.Equal(xml, transformedDocument.OuterXml);
+        }
+
+        [Fact]
+        public void GetOutput_XmlWithEncryptedDataInRoot()
+        {
+            XmlDocument doc = new XmlDocument();
+            string xml = "<root>To Be Encrypted</root>";
+            doc.LoadXml(xml);
+
+            XmlDocument transformedDocument = GetTransformedOutput(doc, "//root");
+
+            Assert.NotNull(transformedDocument);
+            Assert.Equal(xml, transformedDocument.OuterXml);
+        }
+
+        [Fact]
+        public void GetOutput_XmlWithEncryptedDataAndExcept()
+        {
+            XmlDocument doc = new XmlDocument();
+            string xml = "<root><c>To Be Encrypted</c><d /></root>";
+            doc.LoadXml(xml);
+
+            transform.AddExceptUri("#_notfound");
+            transform.AddExceptUri("#_0");
+            XmlDocument transformedDocument = GetTransformedOutput(doc, "c");
+
+            XmlNamespaceManager xmlNamespaceManager = new XmlNamespaceManager(doc.NameTable);
+            xmlNamespaceManager.AddNamespace("enc", EncryptedXml.XmlEncNamespaceUrl);
+            Assert.NotNull(transformedDocument.DocumentElement.SelectSingleNode("//enc:EncryptedData", xmlNamespaceManager));
+            Assert.NotEqual(xml, transformedDocument.OuterXml);
+        }
+
+        private XmlDocument GetTransformedOutput(XmlDocument doc, string nodeToEncrypt)
+        {
+            using (var aesAlgo = Aes.Create())
+            {
+                var encryptedXml = new EncryptedXml();
+                encryptedXml.AddKeyNameMapping("aes", aesAlgo);
+                XmlElement elementToEncrypt = (XmlElement)doc.DocumentElement.SelectSingleNode(nodeToEncrypt);
+                EncryptedData encryptedData = encryptedXml.Encrypt(elementToEncrypt, "aes");
+                EncryptedXml.ReplaceElement(elementToEncrypt, encryptedData, false);
+
+                XmlNamespaceManager xmlNamespaceManager = new XmlNamespaceManager(doc.NameTable);
+                xmlNamespaceManager.AddNamespace("enc", EncryptedXml.XmlEncNamespaceUrl);
+                XmlElement encryptedNode = (XmlElement)doc.DocumentElement.SelectSingleNode("//enc:EncryptedData", xmlNamespaceManager);
+                encryptedNode.SetAttribute("ID", "#_0");
+
+                transform.LoadInput(doc);
+                transform.EncryptedXml = encryptedXml;
+                XmlDocument transformedDocument = (XmlDocument)transform.GetOutput();
+
+                transform.EncryptedXml = null;
+
+                return transformedDocument;
+            }
         }
     }
 }


moved Soap11WSAddressingAugust2004 next to Soap11

--- src/System.ServiceModel.Primitives/ref/System.ServiceModel.Primitives.cs
+++ src/System.ServiceModel.Primitives/ref/System.ServiceModel.Primitives.cs
@@ -1224,8 +1224,8 @@
         public System.ServiceModel.EnvelopeVersion Envelope { get { return default(System.ServiceModel.EnvelopeVersion); } }
         public static System.ServiceModel.Channels.MessageVersion None { get { return default(System.ServiceModel.Channels.MessageVersion); } }
         public static System.ServiceModel.Channels.MessageVersion Soap11 { get { return default(System.ServiceModel.Channels.MessageVersion); } }
+        public static System.ServiceModel.Channels.MessageVersion Soap11WSAddressingAugust2004 { get { return default(System.ServiceModel.Channels.MessageVersion); } }
         public static System.ServiceModel.Channels.MessageVersion Soap12WSAddressing10 { get { return default(System.ServiceModel.Channels.MessageVersion); } }
-        public static System.ServiceModel.Channels.MessageVersion Soap11WSAddressingAugust2004 { get { return default(System.ServiceModel.Channels.MessageVersion); } }
         public static System.ServiceModel.Channels.MessageVersion Soap12WSAddressingAugust2004 { get { return default(System.ServiceModel.Channels.MessageVersion); } }
         public static System.ServiceModel.Channels.MessageVersion CreateVersion(System.ServiceModel.EnvelopeVersion envelopeVersion) { return default(System.ServiceModel.Channels.MessageVersion); }
         public static System.ServiceModel.Channels.MessageVersion CreateVersion(System.ServiceModel.EnvelopeVersion envelopeVersion, System.ServiceModel.Channels.AddressingVersion addressingVersion) { return default(System.ServiceModel.Channels.MessageVersion); }


Minor clarification of empty array parsing unit test

--- src/VelocyPack/VelocyPack.Tests/SegmentParsing/Arrays/EmptyArrayTests.cs
+++ src/VelocyPack/VelocyPack.Tests/SegmentParsing/Arrays/EmptyArrayTests.cs
@@ -9,14 +9,13 @@
         public void ParseEmptyArray()
         {
             // given
-            // hex dump of [1, 2, 3]
+            // hex dump of []
             var data = new byte[] { 0x01 };

             // when
             var segment = VelocyPack.ToSegment(data);

             // then
-            // array
             Assert.AreEqual(0, segment.StartIndex);
             Assert.AreEqual(1, segment.CursorIndex);
             Assert.AreEqual(SegmentType.Array, segment.Type);


Refactor code to make call stack clearer

--- src/SIM.Client/Program.cs
+++ src/SIM.Client/Program.cs
@@ -103,9 +103,14 @@
             continue;
           }

-          File.Create(command).Close();
-        }
-      }
+          CreateEmptyFileInCurrentDirectory(command);
+        }
+      }
+    }
+
+    private static void CreateEmptyFileInCurrentDirectory(string command)
+    {
+      File.Create(command).Close();
     }

     [CanBeNull]


2.1.0 Release

2.1.0 Release

--- src/SharedAssemblyInfo.cs
+++ src/SharedAssemblyInfo.cs
@@ -6,5 +6,5 @@
 [assembly: ComVisible(false)]
 [assembly: AssemblyVersion("2.1.0.0")]
 [assembly: AssemblyFileVersion("2.1.0.0")]
-[assembly: AssemblyInformationalVersion("2.1.0-pre2")]
+[assembly: AssemblyInformationalVersion("2.1.0")]
 [assembly: CLSCompliant(false)]


Added Post/Put from attributes

Added Post/Put from attributes

--- src/SimpleAuth/Api/Api.cs
+++ src/SimpleAuth/Api/Api.cs
@@ -4,6 +4,7 @@
 using System.IO;
 using System.Linq;
 using System.Net.Http;
+using System.Net.Http.Headers;
 using System.Reflection;
 using System.Text;
 using System.Threading;
@@ -216,16 +217,60 @@

 		public async virtual Task<string> GetString(string path, bool authenticated = true)
 		{
-			var resp = await GetMessage(path,authenticated: authenticated);
+			var resp = await SendMessage(path,null,HttpMethod.Get,authenticated: authenticated);
 			return await resp.Content.ReadAsStringAsync();
 		}

 		public async virtual Task<string> GetString(string path, Dictionary<string, string> queryParameters,
 			Dictionary<string, string> headers, bool authenticated = true)
 		{
-			var resp = await GetMessage(path,headers, authenticated: authenticated);
+			var resp = await SendMessage(path,null, HttpMethod.Get,headers, authenticated: authenticated);
 			return await resp.Content.ReadAsStringAsync();
 		}
+
+		public virtual Task<T> Post<T>(object body, bool authenticated = true, [System.Runtime.CompilerServices.CallerMemberName] string methodName = "")
+		{
+			return Post<T>(body,null, authenticated, methodName);
+		}
+
+		public virtual Task<T> Post<T>(object body, Dictionary<string, string> queryParameters, bool authenticated = true, [System.Runtime.CompilerServices.CallerMemberName] string methodName = "")
+		{
+			var headers = GetHeadersFromMethod(GetType().GetMethod(methodName));
+			return Post<T>(body,queryParameters, headers, authenticated, methodName);
+		}
+		public virtual async Task<T> Post<T>(object body, Dictionary<string, string> queryParameters, Dictionary<string, string> headers, bool authenticated = true, [System.Runtime.CompilerServices.CallerMemberName] string methodName = "")
+		{
+			var data = await Post(body, queryParameters, headers, authenticated, methodName);
+			return await Task.Run(() => Deserialize<T>(data,body));
+		}
+		public virtual Task<string> Post(object body, Dictionary<string, string> queryParameters, Dictionary<string, string> headers, bool authenticated = true, [System.Runtime.CompilerServices.CallerMemberName] string methodName = "")
+		{
+			return SendObjectMessage(body, HttpMethod.Post, queryParameters, headers, authenticated, methodName);
+		}
+
+
+		public virtual Task<T> Put<T>(object body, bool authenticated = true, [System.Runtime.CompilerServices.CallerMemberName] string methodName = "")
+		{
+			return Put<T>(body, null, authenticated, methodName);
+		}
+
+		public virtual Task<T> Put<T>(object body, Dictionary<string, string> queryParameters, bool authenticated = true, [System.Runtime.CompilerServices.CallerMemberName] string methodName = "")
+		{
+			var headers = GetHeadersFromMethod(GetType().GetMethod(methodName));
+			return Put<T>(body, queryParameters, headers, authenticated, methodName);
+		}
+		public virtual async Task<T> Put<T>(object body, Dictionary<string, string> queryParameters, Dictionary<string, string> headers, bool authenticated = true, [System.Runtime.CompilerServices.CallerMemberName] string methodName = "")
+		{
+			var data = await Put(body, queryParameters, headers, authenticated, methodName);
+			return await Task.Run(() => Deserialize<T>(data, body));
+		}
+		public virtual Task<string> Put(object body, Dictionary<string, string> queryParameters, Dictionary<string, string> headers, bool authenticated = true, [System.Runtime.CompilerServices.CallerMemberName] string methodName = "")
+		{
+			return SendObjectMessage(body, HttpMethod.Put, queryParameters, headers, authenticated, methodName);
+		}
+
+
+
 		public virtual async Task<string> PostUrl(string path, string content, string mediaType = "text/json", bool authenticated = true)
 		{
 			var message = await PostMessage(path,new StringContent(content, System.Text.Encoding.UTF8, mediaType),authenticated);
@@ -266,25 +311,43 @@
 			return await Client.PutAsync(path, content);
 		}

-		public async Task<HttpResponseMessage> GetMessage(string path, Dictionary<string,string> headers = null,  bool authenticated = true)
-		{
+
+		public virtual async Task<string> SendObjectMessage(object body, HttpMethod method, Dictionary<string, string> queryParameters, Dictionary<string, string> headers, bool authenticated = true, [System.Runtime.CompilerServices.CallerMemberName] string methodName = "")
+		{
+			var path = GetValueFromAttribute<PathAttribute>(GetType().GetMethod(methodName));
+			if (string.IsNullOrWhiteSpace(path))
+				throw new Exception("Missing Path Attribute");
+
+			path = CombineUrl(path, queryParameters);
+
+			var mediaType = "text/json";
+			headers?.TryGetValue("Content-Type", out mediaType);
+
+			var bodyJson = body.ToJson();
+			var content = new StringContent(bodyJson, System.Text.Encoding.UTF8, mediaType);
+
+			var message = await SendMessage(path, content, method, headers, authenticated);
+			var data = await message.Content.ReadAsStringAsync();
+			return data;
+		}
+
+
+		public async Task<HttpResponseMessage> SendMessage(string path, HttpContent content, HttpMethod method , Dictionary<string, string> headers = null, bool authenticated = true)
+		{
+			if (authenticated)
+				await VerifyCredentials();
 			path = await PrepareUrl(path);
 			var uri = BaseAddress != null ? new Uri(BaseAddress, path.TrimStart('/')) : new Uri(path);
 			var request = new HttpRequestMessage
 			{
-				Method = HttpMethod.Get,
+				Method = method,
 				RequestUri = uri,
+				Content =  content,
 			};

-			if (headers?.Any() == true)
-			{
-				foreach (var header in headers)
-				{
-					request.Headers.Add(header.Key, header.Value);
-				}
-			}
-
-            return await SendMessage(request,authenticated);
+			MergeHeaders(request.Headers, headers);
+
+			return await SendMessage(request, authenticated);
 		}

 		public async Task<HttpResponseMessage> SendMessage(HttpRequestMessage message, bool authenticated = true)
@@ -313,6 +376,28 @@
 		{
 			try
 			{
+				return Newtonsoft.Json.JsonConvert.DeserializeObject<T>(data);
+			}
+			catch (Exception ex)
+			{
+				Debug.WriteLine(ex);
+			}
+			return default(T);
+		}
+		protected virtual T Deserialize<T>(string data, object inObject)
+		{
+			try
+			{
+				if (inObject is T)
+				{
+					var serializer = new Newtonsoft.Json.JsonSerializer();
+					using (var reader = new StringReader(data))
+					{
+						var outObj = (T)inObject;
+						serializer.Populate(reader,outObj);
+						return outObj;
+					}
+				}
 				return Newtonsoft.Json.JsonConvert.DeserializeObject<T>(data);
 			}
 			catch (Exception ex)
@@ -368,6 +453,18 @@
 		{
 			return method.GetCustomAttributes(true).OfType<T>().FirstOrDefault()?.Value;
 		}
+
+		public static void MergeHeaders(HttpRequestHeaders inHeaders, Dictionary<string, string> newHeaders)
+		{
+			if (newHeaders == null)
+				return;
+			foreach (var header in newHeaders)
+			{
+				if (header.Key == "Content-Type")
+					continue;
+				inHeaders.Add(header.Key,header.Value);
+			}
+		}
 	}
 }


regenerate invalid thumbnails

regenerate invalid thumbnails

--- src/ThumbnailGenerator.cs
+++ src/ThumbnailGenerator.cs
@@ -72,14 +72,6 @@

 		}

-		public override void Request (Uri uri, int order, int width, int height)
-		{
-			if (ThumbnailFactory.ThumbnailExists (uri) && ThumbnailFactory.ThumbnailIsRecent (uri))
-				return;
-
-			base.Request (uri, order, width, height);
-		}
-
 		protected override void ProcessRequest (RequestItem request)
 		{
 			try {


Small filtering fix

Small filtering fix


Making sure we don't try to use a dictionary from another thread as it is being modified.

--- agg/Font/StyledTypeFace.cs
+++ agg/Font/StyledTypeFace.cs
@@ -100,36 +100,36 @@

         public static Dictionary<char, ImageBuffer> GetCorrectCache(TypeFace typeFace, double emSizeInPoints, RGBA_Bytes color)
         {
-            // check if the cache is getting too big and if so prune it (or just delete it and start over).
-
-            Dictionary<TypeFace, Dictionary<double, Dictionary<char, ImageBuffer>>> foundTypeFaceColor;
-            Instance.typeFaceImageCache.TryGetValue(color, out foundTypeFaceColor);
-            if (foundTypeFaceColor == null)
-            {
-                // add in the type face
-                foundTypeFaceColor = new Dictionary<TypeFace, Dictionary<double, Dictionary<char, ImageBuffer>>>();
-                Instance.typeFaceImageCache.Add(color, foundTypeFaceColor);
-            }
-
-            Dictionary<double, Dictionary<char, ImageBuffer>> foundTypeFaceSizes;
-            foundTypeFaceColor.TryGetValue(typeFace, out foundTypeFaceSizes);
-            if (foundTypeFaceSizes == null)
-            {
-                // add in the type face
-                foundTypeFaceSizes = new Dictionary<double, Dictionary<char, ImageBuffer>>();
-                foundTypeFaceColor.Add(typeFace, foundTypeFaceSizes);
-            }
-
-            Dictionary<char, ImageBuffer> foundTypeFaceSize;
-            foundTypeFaceSizes.TryGetValue(emSizeInPoints, out foundTypeFaceSize);
-            if (foundTypeFaceSize == null)
-            {
-                // add in the point size
-                foundTypeFaceSize = new Dictionary<char, ImageBuffer>();
-                foundTypeFaceSizes.Add(emSizeInPoints, foundTypeFaceSize);
-            }
-
-            return foundTypeFaceSize;
+			using (TimedLock.Lock(typeFace, "GetCorrectCache"))
+			{
+				// check if the cache is getting too big and if so prune it (or just delete it and start over).
+
+				Dictionary<TypeFace, Dictionary<double, Dictionary<char, ImageBuffer>>> foundTypeFaceColor;
+				if (!Instance.typeFaceImageCache.TryGetValue(color, out foundTypeFaceColor))
+				{
+					// add in the type face
+					foundTypeFaceColor = new Dictionary<TypeFace, Dictionary<double, Dictionary<char, ImageBuffer>>>();
+					Instance.typeFaceImageCache.Add(color, foundTypeFaceColor);
+				}
+
+				Dictionary<double, Dictionary<char, ImageBuffer>> foundTypeFaceSizes;
+				if (!foundTypeFaceColor.TryGetValue(typeFace, out foundTypeFaceSizes))
+				{
+					// add in the type face
+					foundTypeFaceSizes = new Dictionary<double, Dictionary<char, ImageBuffer>>();
+					foundTypeFaceColor.Add(typeFace, foundTypeFaceSizes);
+				}
+
+				Dictionary<char, ImageBuffer> foundTypeFaceSize;
+				if (!foundTypeFaceSizes.TryGetValue(emSizeInPoints, out foundTypeFaceSize))
+				{
+					// add in the point size
+					foundTypeFaceSize = new Dictionary<char, ImageBuffer>();
+					foundTypeFaceSizes.Add(emSizeInPoints, foundTypeFaceSize);
+				}
+
+				return foundTypeFaceSize;
+			}
         }

         static StyledTypeFaceImageCache Instance


Whitespace fix.

Whitespace fix.

--- algorithm/binary_search.cs
+++ algorithm/binary_search.cs
@@ -37,7 +37,7 @@
             return min + (max - min) / 2;
         }

-        private static  int _count = 1;
+        private static int _count = 1;
         static void runCase(int[] list, int val, int expected)
         {
             int actual = search(list, val);


[mscorlib] Mono friendly versioning

[mscorlib] Mono friendly versioning

--- mscorlib/system/runtime/versioning/resourceattributes.cs
+++ mscorlib/system/runtime/versioning/resourceattributes.cs
@@ -108,6 +108,11 @@
             return MakeVersionSafeName(name, from, to, null);
         }

+#if MONO
+        [MethodImplAttribute(MethodImplOptions.InternalCall)]
+        extern static uint GetCurrentProcessId ();
+#endif
+
         [System.Security.SecuritySafeCritical]  // auto-generated
         [ResourceExposure(ResourceScope.None)]
         [ResourceConsumption(ResourceScope.Process, ResourceScope.Process)]
@@ -131,7 +136,11 @@
             if ((requires & SxSRequirements.ProcessID) != 0) {
                 safeName.Append(separator);
                 safeName.Append('p');
+#if MONO
+                safeName.Append (GetCurrentProcessId ());
+#else
                 safeName.Append(Win32Native.GetCurrentProcessId());
+#endif
             }
             if ((requires & SxSRequirements.CLRInstanceID) != 0) {
                 String clrID = GetCLRInstanceString();


fix pinned drawable comment test

fix pinned drawable comment test

--- osu.Game.Tests/Visual/Online/TestSceneDrawableComment.cs
+++ osu.Game.Tests/Visual/Online/TestSceneDrawableComment.cs
@@ -43,9 +43,7 @@
         {
             AddStep(description, () =>
             {
-                if (description == "Pinned")
-                    comment.Pinned = true;
-
+                comment.Pinned = description == "Pinned";
                 comment.Message = text;
                 container.Add(new DrawableComment(comment));
             });


Adjusted score rank size

Adjusted score rank size

--- osu.Game/Screens/Select/Leaderboards/LeaderboardScore.cs
+++ osu.Game/Screens/Select/Leaderboards/LeaderboardScore.cs
@@ -25,7 +25,7 @@
         private const float corner_radius = 5;
         private const float edge_margin = 10;
         private const float background_alpha = 0.25f;
-        private const float score_rank_size = 30f;
+        private const float score_rank_size = 40f;

         private readonly EdgeEffect imageShadow = new EdgeEffect
         {
@@ -241,7 +241,7 @@
                                     Anchor = Anchor.TopRight,
                                     Origin = Anchor.TopRight,
                                     Size = new Vector2(score_rank_size),
-                                    Position = new Vector2(0f, -5f),
+                                    Position = new Vector2(0f, -10f),
                                 },
                                 scoreLabel = new GlowingSpriteText(string.Format("{0:n0}", Score.TotalScore), @"Venera", 23, Color4.White, OsuColour.FromHex(@"83ccfa"))
                                 {


Conditional branch can use weave

Conditional branch can use weave

--- inklecate2Sharp/Parser/ParsedObjects/ConditionalSingleBranch.cs
+++ inklecate2Sharp/Parser/ParsedObjects/ConditionalSingleBranch.cs
@@ -7,14 +7,23 @@
     {
         public bool isBoolCondition { get; set; }
         public bool boolRequired { get; set; }
-        public Expression ownExpression { get; set; }
+        public Expression ownExpression {
+            get {
+                return _ownExpression;
+            }
+            set {
+                _ownExpression = value;
+                AddContent (_ownExpression);
+            }
+        }
         public bool shouldMatchEquality { get; set; }
         public bool alwaysMatch { get; set; } // used for else clause
         public Runtime.Divert returnDivert { get; protected set; }

         public ConditionalSingleBranch (List<Parsed.Object> content)
         {
-            AddContent (content);
+            _innerContent = content;
+            AddContent (_innerContent);
         }

         // Runtime content can be summarised as follows:
@@ -80,11 +89,11 @@

         Runtime.Container GenerateRuntimeForContent()
         {
-            var container = new Runtime.Container ();
+            //var container = new Runtime.Container ();

-            foreach (var parsedObj in content) {
-                container.AddContent (parsedObj.runtimeObject);
-            }
+            int contentIdx = 0;
+            _innerWeave = new Weave (_innerContent, ref contentIdx);
+            var container = _innerWeave.rootContainer;

             // Small optimisation: If it's just one piece of content that has
             // its own container already (without an explicit name), then just
@@ -104,11 +113,17 @@
         {
             _divertOnBranch.targetPath = _contentContainer.path;

+            _innerWeave.ResolveReferences (context);
+
             base.ResolveReferences (context);
         }

         Runtime.Container _contentContainer;
         Runtime.Divert _divertOnBranch;
+        Expression _ownExpression;
+        List<Parsed.Object> _innerContent;
+
+        Weave _innerWeave;
     }
 }


Realign white line on argon hold note ends to match hit target

--- osu.Game.Rulesets.Mania/Skinning/Argon/ArgonHoldNoteTailPiece.cs
+++ osu.Game.Rulesets.Mania/Skinning/Argon/ArgonHoldNoteTailPiece.cs
@@ -38,6 +38,8 @@
                 },
                 new Container
                 {
+                    Anchor = Anchor.BottomLeft,
+                    Origin = Anchor.BottomLeft,
                     RelativeSizeAxes = Axes.Both,
                     Height = 0.82f,
                     Masking = true,
@@ -54,6 +56,8 @@
                 {
                     RelativeSizeAxes = Axes.X,
                     Height = ArgonNotePiece.CORNER_RADIUS * 2,
+                    Anchor = Anchor.BottomLeft,
+                    Origin = Anchor.BottomLeft,
                 },
             };
         }


apply suggestions

apply suggestions

- Replace the sprite with a solid black box when a storyboard requests it.
- Create a new storyboard instance and exclude the fail layer as well as strip all samples from it
- Do not attempt in creating the storyboard when it isn't needed

--- osu.Game/Graphics/Backgrounds/BeatmapBackgroundWithStoryboard.cs
+++ osu.Game/Graphics/Backgrounds/BeatmapBackgroundWithStoryboard.cs
@@ -1,10 +1,13 @@
 // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
 // See the LICENCE file in the repository root for full licence text.

+using System.Linq;
 using osu.Framework.Allocation;
 using osu.Framework.Graphics;
+using osu.Framework.Graphics.Textures;
 using osu.Framework.Timing;
 using osu.Game.Beatmaps;
+using osu.Game.Storyboards;
 using osu.Game.Storyboards.Drawables;

 namespace osu.Game.Graphics.Backgrounds
@@ -19,16 +22,23 @@
         [BackgroundDependencyLoader]
         private void load()
         {
-            LoadComponentAsync(new DrawableStoryboard(Beatmap.Storyboard)
-                {
-                    Clock = new InterpolatingFramedClock(Beatmap.Track),
-                },
-                loaded =>
-                {
-                    AddInternal(loaded);
-                    if (Beatmap.Storyboard.ReplacesBackground)
-                        Sprite.FadeOut(300, Easing.OutQuint);
-                });
+            if (!Beatmap.Storyboard.HasDrawable)
+                return;
+
+            var storyboard = new Storyboard { BeatmapInfo = Beatmap.BeatmapInfo };
+            foreach (var layer in storyboard.Layers)
+            {
+                if (layer.Name != "Fail")
+                    layer.Elements = Beatmap.Storyboard.GetLayer(layer.Name).Elements.Where(e => !(e is StoryboardSampleInfo)).ToList();
+            }
+
+            if (storyboard.ReplacesBackground)
+            {
+                Sprite.Texture = Texture.WhitePixel;
+                Sprite.Colour = Colour4.Black;
+            }
+
+            LoadComponentAsync(new DrawableStoryboard(storyboard) { Clock = new InterpolatingFramedClock(Beatmap.Track) }, AddInternal);
         }
     }
 }


Fix initial tablet size not being initialised

--- osu.Game/Overlays/Settings/Sections/Input/TabletAreaSelection.cs
+++ osu.Game/Overlays/Settings/Sections/Input/TabletAreaSelection.cs
@@ -80,6 +80,11 @@
                     },
                 }
             };
+        }
+
+        protected override void LoadComplete()
+        {
+            base.LoadComplete();

             areaOffset.BindTo(handler.AreaOffset);
             areaOffset.BindValueChanged(val =>
@@ -101,7 +106,7 @@
                 tabletContainer.Size = new Vector2(val.NewValue.Width, val.NewValue.Height);
                 tabletName.Text = handler.DeviceName;
                 checkBounds();
-            });
+            }, true);
         }

         [Resolved]


Ensure deletions are correct without relying on FK cascade rule

--- osu.Game/Database/MutableDatabaseBackedStoreWithFileIncludes.cs
+++ osu.Game/Database/MutableDatabaseBackedStoreWithFileIncludes.cs
@@ -19,5 +19,9 @@
         protected override IQueryable<T> AddIncludesForConsumption(IQueryable<T> query) =>
             base.AddIncludesForConsumption(query)
                 .Include(s => s.Files).ThenInclude(f => f.FileInfo);
+
+        protected override IQueryable<T> AddIncludesForDeletion(IQueryable<T> query) =>
+            base.AddIncludesForDeletion(query)
+                .Include(s => s.Files); // don't include FileInfo. these are handled by the FileStore itself.
     }
 }


Add null check to supress quality errors

--- osu.Game/Graphics/Containers/SelectionCycleFillFlowContainer.cs
+++ osu.Game/Graphics/Containers/SelectionCycleFillFlowContainer.cs
@@ -17,6 +17,8 @@
     public class SelectionCycleFillFlowContainer<T> : FillFlowContainer<T> where T : Drawable, IStateful<SelectionState>
     {
         private int? selectedIndex;
+
+        public T Selected => (selectedIndex >= 0 && selectedIndex < Count) ? this[selectedIndex.Value] : null;

         private void setSelected(int? value)
         {
@@ -51,6 +53,7 @@
         }

         public void Deselect() => setSelected(null);
+
         public void Select(T item)
         {
             var newIndex = IndexOf(item);
@@ -61,19 +64,20 @@
                 setSelected(IndexOf(item));
         }

-        public T Selected => (selectedIndex >= 0 && selectedIndex < Count) ? this[selectedIndex.Value] : null;
-
         private readonly Dictionary<T, Action<SelectionState>> handlerMap = new Dictionary<T, Action<SelectionState>>();

         public override void Add(T drawable)
         {
-            // This event is used to update selection state when modified within the drawable itself.
-            // It is added to a dictionary so that we can unsubscribe if the drawable is removed from this container
-            handlerMap[drawable] = state => selectionChanged(drawable, state);
+            base.Add(drawable);

-            drawable.StateChanged += handlerMap[drawable];
+            if (drawable != null)
+            {
+                // This event is used to update selection state when modified within the drawable itself.
+                // It is added to a dictionary so that we can unsubscribe if the drawable is removed from this container
+                handlerMap[drawable] = state => selectionChanged(drawable, state);

-            base.Add(drawable);
+                drawable.StateChanged += handlerMap[drawable];
+            }
         }

         public override bool Remove(T drawable)
@@ -81,7 +85,7 @@
             if (!base.Remove(drawable))
                 return false;

-            if (handlerMap.TryGetValue(drawable, out var action))
+            if (drawable != null && handlerMap.TryGetValue(drawable, out var action))
             {
                 drawable.StateChanged -= action;
                 handlerMap.Remove(drawable);


Handle bindable changes to fix new playlist creation not showing correct details

--- osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomSubScreen.cs
+++ osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomSubScreen.cs
@@ -37,6 +37,8 @@
         private MatchLeaderboard leaderboard;
         private SelectionPollingComponent selectionPollingComponent;

+        private FillFlowContainer progressSection;
+
         public PlaylistsRoomSubScreen(Room room)
             : base(room, false) // Editing is temporarily not allowed.
         {
@@ -67,6 +69,8 @@
                     Schedule(() => SelectedItem.Value = Room.Playlist.FirstOrDefault());
                 }
             }, true);
+
+            Room.MaxAttempts.BindValueChanged(attempts => progressSection.Alpha = Room.MaxAttempts.Value != null ? 1 : 0, true);
         }

         protected override Drawable CreateMainContent() => new GridContainer
@@ -154,11 +158,11 @@
                             },
                             new Drawable[]
                             {
-                                new FillFlowContainer
+                                progressSection = new FillFlowContainer
                                 {
                                     RelativeSizeAxes = Axes.X,
                                     AutoSizeAxes = Axes.Y,
-                                    Alpha = Room.MaxAttempts.Value != null ? 1 : 0,
+                                    Alpha = 0,
                                     Margin = new MarginPadding { Bottom = 10 },
                                     Direction = FillDirection.Vertical,
                                     Children = new Drawable[]


Enable OAEP padding

Enable OAEP padding

--- src/15below.Deployment.Update/NDjangoExpansions/DecryptFilter.cs
+++ src/15below.Deployment.Update/NDjangoExpansions/DecryptFilter.cs
@@ -20,7 +20,7 @@

             if (value is NDjangoWrapper.ErrorTemplate)
             {
-                throw new Exception($"Value does not exist when calling decrypt");
+                throw new Exception("Value does not exist when calling decrypt");
             }
             else if (cert == null)
             {
@@ -66,7 +66,7 @@
         private byte[] DecryptData(X509Certificate2 cert, byte[] data)
         {
             var rsa = (RSACryptoServiceProvider)cert.PrivateKey;
-            return rsa.Decrypt(data, false);
+            return rsa.Decrypt(data, true);
         }
     }
 }


Split RabbitMQ channel create and consumer create.

Because when channel create the Subscribe is not register, so the previously stored message may lose. This fix split the channel create and consumer create, when Subscribe registered then call the consumer create function.

--- src/BuildingBlocks/EventBus/EventBusRabbitMQ/EventBusRabbitMQ.cs
+++ src/BuildingBlocks/EventBus/EventBusRabbitMQ/EventBusRabbitMQ.cs
@@ -98,7 +98,7 @@

                     channel.BasicPublish(exchange: BROKER_NAME,
                                      routingKey: eventName,
-                                     mandatory:true,
+                                     mandatory: true,
                                      basicProperties: properties,
                                      body: body);
                 });
@@ -112,6 +112,7 @@

             DoInternalSubscription(eventName);
             _subsManager.AddDynamicSubscription<TH>(eventName);
+            StartBasicConsume();
         }

         public void Subscribe<T, TH>()
@@ -124,6 +125,7 @@
             _logger.LogInformation("Subscribing to event {EventName} with {EventHandler}", eventName, typeof(TH).GetGenericTypeName());

             _subsManager.AddSubscription<T, TH>();
+            StartBasicConsume();
         }

         private void DoInternalSubscription(string eventName)
@@ -170,6 +172,31 @@
             }

             _subsManager.Clear();
+        }
+
+        private void StartBasicConsume()
+        {
+            if (_consumerChannel != null)
+            {
+                var consumer = new EventingBasicConsumer(_consumerChannel);
+                consumer.Received += async (model, ea) =>
+                {
+                    var eventName = ea.RoutingKey;
+                    var message = Encoding.UTF8.GetString(ea.Body);
+
+                    await ProcessEvent(eventName, message);
+
+                    _consumerChannel.BasicAck(ea.DeliveryTag, multiple: false);
+                };
+
+                _consumerChannel.BasicConsume(queue: _queueName,
+                                     autoAck: false,
+                                     consumer: consumer);
+            }
+            else
+            {
+                _logger.LogError("StartBasicConsume can not call on _consumerChannelCreated == false");
+            }
         }

         private IModel CreateConsumerChannel()
@@ -190,26 +217,11 @@
                                  autoDelete: false,
                                  arguments: null);

-
-            var consumer = new EventingBasicConsumer(channel);
-            consumer.Received += async (model, ea) =>
-            {
-                var eventName = ea.RoutingKey;
-                var message = Encoding.UTF8.GetString(ea.Body);
-
-                await ProcessEvent(eventName, message);
-
-                channel.BasicAck(ea.DeliveryTag,multiple:false);
-            };
-
-            channel.BasicConsume(queue: _queueName,
-                                 autoAck: false,
-                                 consumer: consumer);
-
             channel.CallbackException += (sender, ea) =>
             {
                 _consumerChannel.Dispose();
                 _consumerChannel = CreateConsumerChannel();
+                StartBasicConsume();
             };

             return channel;


Uploading original images for now

Uploading original images for now

--- src/Collectively.Services.Remarks/Services/RemarkPhotoService.cs
+++ src/Collectively.Services.Remarks/Services/RemarkPhotoService.cs
@@ -19,20 +19,18 @@
         private readonly IRemarkRepository _remarkRepository;
         private readonly IUserRepository _userRepository;
         private readonly IFileHandler _fileHandler;
-        private readonly IImageService _imageService;
         private readonly IUniqueNumberGenerator _uniqueNumberGenerator;
         private readonly GeneralSettings _settings;

         public RemarkPhotoService(IRemarkRepository remarkRepository,
             IUserRepository userRepository,
-            IFileHandler fileHandler, IImageService imageService,
+            IFileHandler fileHandler,
             IUniqueNumberGenerator uniqueNumberGenerator,
             GeneralSettings settings)
         {
             _remarkRepository = remarkRepository;
             _userRepository = userRepository;
             _fileHandler = fileHandler;
-            _imageService = imageService;
             _uniqueNumberGenerator = uniqueNumberGenerator;
             _settings = settings;
         }
@@ -73,34 +71,16 @@
         private async Task UploadImagesWithDifferentSizesAsync(Remark remark, RemarkUser user, File originalPhoto, string metadata = null)
         {
             var extension = originalPhoto.Name.Split('.').Last();
-            var photos = _imageService.ProcessImage(originalPhoto);
             var uniqueNumber = _uniqueNumberGenerator.Generate();
             var groupId = Guid.NewGuid();
-            var tasks = new List<Task>();
-            //Rethink if it's a good solution...
-            // var processingPhotos = photos.Select(x => RemarkPhoto.AsProcessing(groupId, user));
-            // foreach (var photo in processingPhotos)
-            // {
-            //     remark.AddPhoto(photo);
-            // }
-            // await _remarkRepository.UpdateAsync(remark);
-            // foreach (var photo in processingPhotos)
-            // {
-            //     remark.RemovePhoto(photo.Name);
-            // }
-            foreach (var photo in photos)
+            var size = "big";
+            var fileName = metadata == null
+                ? $"{remark.Id:N}_{size}_{uniqueNumber}.{extension}"
+                : $"{remark.Id:N}_{size}_{metadata}_{uniqueNumber}.{extension}";
+            await _fileHandler.UploadAsync(originalPhoto, fileName, url =>
             {
-                var size = photo.Key;
-                var fileName = metadata == null
-                    ? $"{remark.Id:N}_{size}_{uniqueNumber}.{extension}"
-                    : $"{remark.Id:N}_{size}_{metadata}_{uniqueNumber}.{extension}";
-                var task = _fileHandler.UploadAsync(photo.Value, fileName, url =>
-                {
-                    remark.AddPhoto(RemarkPhoto.Create(groupId, fileName, size, url, user, metadata));
-                });
-                tasks.Add(task);
-            }
-            await Task.WhenAll(tasks);
+                remark.AddPhoto(RemarkPhoto.Create(groupId, fileName, size, url, user, metadata));
+            });
         }

         public async Task<Maybe<IEnumerable<string>>> GetPhotosForGroupsAsync(Guid remarkId, params Guid[] groupIds)


1098521-Add tests for string,Format overload in string interp (changeset 1411149)

--- src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenExprLambdaTests.cs
+++ src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenExprLambdaTests.cs
@@ -4867,6 +4867,48 @@
                 expectedOutput: expectedOutput);
         }

+        [WorkItem(1098521, "DevDiv")]
+        [Fact]
+        public void InterpolationUsesOverloadResolution()
+        {
+            const string source = @"
+using System;
+using System.Linq.Expressions;
+
+struct S { }
+
+class C : TestBase
+{
+    static void M<T>()
+        where T : struct
+    {
+            Expression<Func<string>> f;
+            f = () => $"""";
+            Check<string>(f, ""Constant( Type:System.String)"");
+            f = () => $""{1}"";
+            Check<string>(f, ""Call(null.[System.String Format(System.String, System.Object)](Constant({0} Type:System.String), Convert(Constant(1 Type:System.Int32) Type:System.Object)) Type:System.String)"");
+            f = () => $""{1}{2}"";
+            Check<string>(f, ""Call(null.[System.String Format(System.String, System.Object, System.Object)](Constant({0}{1} Type:System.String), Convert(Constant(1 Type:System.Int32) Type:System.Object), Convert(Constant(2 Type:System.Int32) Type:System.Object)) Type:System.String)"");
+            f = () => $""{1}{2}{3}"";
+            Check<string>(f, ""Call(null.[System.String Format(System.String, System.Object, System.Object, System.Object)](Constant({0}{1}{2} Type:System.String), Convert(Constant(1 Type:System.Int32) Type:System.Object), Convert(Constant(2 Type:System.Int32) Type:System.Object), Convert(Constant(3 Type:System.Int32) Type:System.Object)) Type:System.String)"");
+            f = () => $""{1}{2}{3}{4}"";
+            Check<string>(f, ""Call(null.[System.String Format(System.String, System.Object[])](Constant({0}{1}{2}{3} Type:System.String), NewArrayInit([Convert(Constant(1 Type:System.Int32) Type:System.Object) Convert(Constant(2 Type:System.Int32) Type:System.Object) Convert(Constant(3 Type:System.Int32) Type:System.Object) Convert(Constant(4 Type:System.Int32) Type:System.Object)] Type:System.Object[])) Type:System.String)"");
+            Console.WriteLine(""DONE"");
+    }
+
+    static void Main()
+    {
+        M<S>();
+    }
+}";
+
+            const string expectedOutput = @"DONE";
+            CompileAndVerify(
+                new[] { source, ExpressionTestLibrary },
+                new[] { ExpressionAssemblyRef },
+                expectedOutput: expectedOutput);
+        }
+
         #endregion Regression Tests

         #region helpers