[System.Web] ASP.Net MVC5 missing methods fixed
authorMatthias Bogad <delirium@hacked.xyz>
Sun, 17 May 2015 17:54:05 +0000 (19:54 +0200)
committerMatthias Bogad <delirium@hacked.xyz>
Tue, 9 Jun 2015 12:06:52 +0000 (14:06 +0200)
I have added System.HttpApplication.RegisterModule(), the missing two properties of the System.Web.Routing.RouteCollection as well as the corresponding property in the HttpRuntimeSection to completely turn this off. Microsofts MIT-Licensed counterparts of the official System.Web assembly from github [0] were used as a reference. It is kind-of bolted on, but should be good enough until the whole open-sourced System.Web is incorporated. It should at least get the default MVC5 Template from Visual Studio 2013 up and running, once the async pipeline for the owin stuff is fixed.

[0]: http://github.com/Microsoft/referencesource/

Additionally, the MissingMethodException "get_InClientBuildManager" in System.Web.Hosting.HostingEnvironment was fixed.
In this commit, the following bugs were fixed:
https://bugzilla.xamarin.com/show_bug.cgi?id=21810
https://bugzilla.xamarin.com/show_bug.cgi?id=16475

mcs/class/System.Web.Routing/System.Web.Routing/RouteCollection.cs
mcs/class/System.Web/System.Web.Configuration_2.0/HttpRuntimeSection.cs
mcs/class/System.Web/System.Web.Hosting/HostingEnvironment.cs
mcs/class/System.Web/System.Web/DynamicModuleManager.cs [new file with mode: 0644]
mcs/class/System.Web/System.Web/HttpApplication.cs
mcs/class/System.Web/net_4_5_System.Web.dll.sources

index b3e4a1c16dcf32f25e1e66d93c70ecb37699e7d9..d53c063441e031e840b38712192ef849e2c4bbae 100644 (file)
@@ -92,6 +92,8 @@ namespace System.Web.Routing
                        }
                }
 
+               public bool LowercaseUrls { get; set; }
+               public bool AppendTrailingSlash { get; set; }
                public bool RouteExistingFiles { get; set; }
 
                public void Add (string name, RouteBase item)
index 62eb0716440d75bdb62c0933c298994a2c61068f..a328b5e18fcbb139a2a26bbaaa0726f0bef4c426 100644 (file)
@@ -63,6 +63,7 @@ namespace System.Web.Configuration
                static ConfigurationProperty encoderTypeProp;
                static ConfigurationProperty relaxedUrlToFileSystemMappingProp;
                static ConfigurationProperty targetFrameworkProp;
+               static ConfigurationProperty allowDynamicModuleRegistrationProp;
                static ConfigurationPropertyCollection properties;
 
                static HttpRuntimeSection ()
@@ -141,6 +142,8 @@ namespace System.Web.Configuration
                                                                                PropertyHelper.VersionConverter,
                                                                                PropertyHelper.DefaultValidator,
                                                                                ConfigurationPropertyOptions.None);
+                       allowDynamicModuleRegistrationProp = new ConfigurationProperty ("allowDynamicModuleRegistration", typeof(bool), true,
+                                                                               ConfigurationPropertyOptions.None);
                        
                        properties = new ConfigurationPropertyCollection();
                        properties.Add (apartmentThreadingProp);
@@ -169,6 +172,7 @@ namespace System.Web.Configuration
                        properties.Add (encoderTypeProp);
                        properties.Add (relaxedUrlToFileSystemMappingProp);
                        properties.Add (targetFrameworkProp);
+                       properties.Add (allowDynamicModuleRegistrationProp);
                }
 
                public HttpRuntimeSection()
@@ -349,6 +353,11 @@ namespace System.Web.Configuration
                protected internal override ConfigurationPropertyCollection Properties {
                        get { return properties; }
                }
+               [ConfigurationProperty ("allowDynamicModuleRegistration", DefaultValue = "True")]
+               public bool AllowDynamicModuleRegistration {
+                       get { return (bool) base [allowDynamicModuleRegistrationProp]; }
+                       set { base [allowDynamicModuleRegistrationProp] = value; }
+               }
        }
 }
 
index ebf540bfb924df4dc2192c8277913ed9698f8fe0..4b8a52f036de2deb44f292da94fd47541e04a425 100644 (file)
@@ -104,6 +104,13 @@ namespace System.Web.Hosting {
                        get { return vpath_provider; }
                }
 
+               public static bool InClientBuildManager {
+                       get {
+                               // Mono doesn't have a ClientBuildManager, so we can't be in it. Simple as that.
+                               return false;
+                       }
+               }
+
                public static void DecrementBusyCount ()
                {
                        Interlocked.Decrement (ref busy_count);
diff --git a/mcs/class/System.Web/System.Web/DynamicModuleManager.cs b/mcs/class/System.Web/System.Web/DynamicModuleManager.cs
new file mode 100644 (file)
index 0000000..99e0a36
--- /dev/null
@@ -0,0 +1,57 @@
+//
+// DynamicModuleManager.cs: Manager for dynamic Http Modules.
+//
+// Author:
+//   Matthias Bogad (bogad@cs.tum.edu)
+//
+// (C) 2015
+//
+
+using System;
+using System.Collections.Generic;
+
+namespace System.Web {
+       sealed class DynamicModuleManager {
+               const string moduleNameFormat = "__Module__{0}_{1}";
+       
+               readonly List<DynamicModuleInfo> entries = new List<DynamicModuleInfo> ();
+               bool entriesAreReadOnly = false;
+               readonly object mutex = new object ();
+               
+               public void Add (Type moduleType) 
+               {
+                       if (moduleType == null)
+                               throw new ArgumentException ("moduleType");
+                       
+                       if (!typeof (IHttpModule).IsAssignableFrom (moduleType))
+                               throw new ArgumentException ("Given object does not implement IHttpModule.", "moduleType");
+                       
+                       lock (mutex) {
+                               if (entriesAreReadOnly)
+                                       throw new InvalidOperationException ("A module was to be added to the dynamic module list, but the list was already initialized. The dynamic module list can only be initialized once.");
+
+                               entries.Add (new DynamicModuleInfo (moduleType,
+                                                       string.Format (moduleNameFormat, moduleType.AssemblyQualifiedName, Guid.NewGuid ())));
+                       }
+               }
+               
+               public ICollection<DynamicModuleInfo> LockAndGetModules ()
+               {
+                       lock (mutex) {
+                               entriesAreReadOnly = true;
+                               return entries;
+                       }
+               }
+       }
+
+       struct DynamicModuleInfo {
+               public readonly string Name;
+               public readonly Type Type;
+
+               public DynamicModuleInfo (Type type, string name)
+               {
+                       Name = name;
+                       Type = type;
+               }
+       }
+}
index 68c098dcc261c264a2237318072781429e24192b..34c2d105769aa4f5623694fd0d1d903d48c81039 100644 (file)
@@ -4,7 +4,8 @@
 // Author:
 //     Miguel de Icaza (miguel@novell.com)
 //     Gonzalo Paniagua (gonzalo@ximian.com)
-//    
+//     Matthias Bogad (bogad@cs.tum.edu)
+//
 //
 // Copyright (C) 2005-2009 Novell, Inc (http://www.novell.com)
 //
 //    Events Disposed
 //
 
+using System;
 using System.IO;
 using System.Collections;
+using System.Collections.Generic;
 using System.ComponentModel;
 using System.Configuration;
 using System.Diagnostics;
@@ -162,6 +165,8 @@ namespace System.Web
                bool removeConfigurationFromCache;
                bool fullInitComplete = false;
                
+               static DynamicModuleManager dynamicModuleManeger = new DynamicModuleManager ();
+
                //
                // These are used to detect the case where the EndXXX method is invoked
                // from within the BeginXXXX delegate, so we detect whether we kick the
@@ -209,6 +214,13 @@ namespace System.Web
                                        if (context == null)
                                                context = HttpContext.Current;
                                        HttpModuleCollection coll = modules.LoadModules (this);
+
+                                       HttpModuleCollection dynMods = CreateDynamicModules ();
+
+                                       for (int i = 0; i < dynMods.Count; i++) {
+                                               coll.AddModule (dynMods.GetKey (i), dynMods.Get (i));
+                                       }
+
                                        Interlocked.CompareExchange (ref modcoll, coll, null);
                                        HttpContext.Current = saved;
 
@@ -404,7 +416,7 @@ namespace System.Web
                
                public void AddOnAcquireRequestStateAsync (BeginEventHandler bh, EndEventHandler eh)
                {
-                       AsyncInvoker invoker = new AsyncInvoker (bh, eh);
+                       AsyncInvoker invoker = new AsyncInvoker (bh, eh, this);
                        AcquireRequestState += new EventHandler (invoker.Invoke);
                }
 
@@ -417,7 +429,7 @@ namespace System.Web
                
                public void AddOnAuthenticateRequestAsync (BeginEventHandler bh, EndEventHandler eh)
                {
-                       AsyncInvoker invoker = new AsyncInvoker (bh, eh);
+                       AsyncInvoker invoker = new AsyncInvoker (bh, eh, this);
                        AuthenticateRequest += new EventHandler (invoker.Invoke);
                }
 
@@ -430,7 +442,7 @@ namespace System.Web
                
                public void AddOnAuthorizeRequestAsync (BeginEventHandler bh, EndEventHandler eh)
                {
-                       AsyncInvoker invoker = new AsyncInvoker (bh, eh);
+                       AsyncInvoker invoker = new AsyncInvoker (bh, eh, this);
                        AuthorizeRequest += new EventHandler (invoker.Invoke);
                }
 
@@ -452,7 +464,7 @@ namespace System.Web
                
                public void AddOnBeginRequestAsync (BeginEventHandler bh, EndEventHandler eh)
                {
-                       AsyncInvoker invoker = new AsyncInvoker (bh, eh);
+                       AsyncInvoker invoker = new AsyncInvoker (bh, eh, this);
                        BeginRequest += new EventHandler (invoker.Invoke);
                }
 
@@ -474,7 +486,7 @@ namespace System.Web
                
                public void AddOnEndRequestAsync (BeginEventHandler bh, EndEventHandler eh)
                {
-                       AsyncInvoker invoker = new AsyncInvoker (bh, eh);
+                       AsyncInvoker invoker = new AsyncInvoker (bh, eh, this);
                        EndRequest += new EventHandler (invoker.Invoke);
                }
 
@@ -487,7 +499,7 @@ namespace System.Web
                
                public void AddOnPostRequestHandlerExecuteAsync (BeginEventHandler bh, EndEventHandler eh)
                {
-                       AsyncInvoker invoker = new AsyncInvoker (bh, eh);
+                       AsyncInvoker invoker = new AsyncInvoker (bh, eh, this);
                        PostRequestHandlerExecute += new EventHandler (invoker.Invoke);
                }
 
@@ -500,7 +512,7 @@ namespace System.Web
                
                public void AddOnPreRequestHandlerExecuteAsync (BeginEventHandler bh, EndEventHandler eh)
                {
-                       AsyncInvoker invoker = new AsyncInvoker (bh, eh);
+                       AsyncInvoker invoker = new AsyncInvoker (bh, eh, this);
                        PreRequestHandlerExecute += new EventHandler (invoker.Invoke);
                }
 
@@ -513,7 +525,7 @@ namespace System.Web
                
                public void AddOnReleaseRequestStateAsync (BeginEventHandler bh, EndEventHandler eh)
                {
-                       AsyncInvoker invoker = new AsyncInvoker (bh, eh);
+                       AsyncInvoker invoker = new AsyncInvoker (bh, eh, this);
                        ReleaseRequestState += new EventHandler (invoker.Invoke);
                }
 
@@ -526,7 +538,7 @@ namespace System.Web
                
                public void AddOnResolveRequestCacheAsync (BeginEventHandler bh, EndEventHandler eh)
                {
-                       AsyncInvoker invoker = new AsyncInvoker (bh, eh);
+                       AsyncInvoker invoker = new AsyncInvoker (bh, eh, this);
                        ResolveRequestCache += new EventHandler (invoker.Invoke);
                }
 
@@ -539,7 +551,7 @@ namespace System.Web
                
                public void AddOnUpdateRequestCacheAsync (BeginEventHandler bh, EndEventHandler eh)
                {
-                       AsyncInvoker invoker = new AsyncInvoker (bh, eh);
+                       AsyncInvoker invoker = new AsyncInvoker (bh, eh, this);
                        UpdateRequestCache += new EventHandler (invoker.Invoke);
                }
 
@@ -557,7 +569,7 @@ namespace System.Web
                        
                public void AddOnPostAuthenticateRequestAsync (BeginEventHandler bh, EndEventHandler eh, object data)
                {
-                       AsyncInvoker invoker = new AsyncInvoker (bh, eh, data);
+                       AsyncInvoker invoker = new AsyncInvoker (bh, eh, this, data);
                        PostAuthenticateRequest += new EventHandler (invoker.Invoke);
                }
 
@@ -575,7 +587,7 @@ namespace System.Web
                
                public void AddOnPostAuthorizeRequestAsync (BeginEventHandler bh, EndEventHandler eh, object data)
                {
-                       AsyncInvoker invoker = new AsyncInvoker (bh, eh, data);
+                       AsyncInvoker invoker = new AsyncInvoker (bh, eh, this, data);
                        PostAuthorizeRequest += new EventHandler (invoker.Invoke);
                }
                
@@ -593,7 +605,7 @@ namespace System.Web
                
                public void AddOnPostResolveRequestCacheAsync (BeginEventHandler bh, EndEventHandler eh, object data)
                {
-                       AsyncInvoker invoker = new AsyncInvoker (bh, eh, data);
+                       AsyncInvoker invoker = new AsyncInvoker (bh, eh, this, data);
                        PostResolveRequestCache += new EventHandler (invoker.Invoke);
                }
 
@@ -611,7 +623,7 @@ namespace System.Web
                
                public void AddOnPostMapRequestHandlerAsync (BeginEventHandler bh, EndEventHandler eh, object data)
                {
-                       AsyncInvoker invoker = new AsyncInvoker (bh, eh, data);
+                       AsyncInvoker invoker = new AsyncInvoker (bh, eh, this, data);
                        PostMapRequestHandler += new EventHandler (invoker.Invoke);
                }
 
@@ -629,7 +641,7 @@ namespace System.Web
                
                public void AddOnPostAcquireRequestStateAsync (BeginEventHandler bh, EndEventHandler eh, object data)
                {
-                       AsyncInvoker invoker = new AsyncInvoker (bh, eh, data);
+                       AsyncInvoker invoker = new AsyncInvoker (bh, eh, this, data);
                        PostAcquireRequestState += new EventHandler (invoker.Invoke);
                }
 
@@ -647,7 +659,7 @@ namespace System.Web
                
                public void AddOnPostReleaseRequestStateAsync (BeginEventHandler bh, EndEventHandler eh, object data)
                {
-                       AsyncInvoker invoker = new AsyncInvoker (bh, eh, data);
+                       AsyncInvoker invoker = new AsyncInvoker (bh, eh, this, data);
                        PostReleaseRequestState += new EventHandler (invoker.Invoke);
                }
 
@@ -665,7 +677,7 @@ namespace System.Web
                
                public void AddOnPostUpdateRequestCacheAsync (BeginEventHandler bh, EndEventHandler eh, object data)
                {
-                       AsyncInvoker invoker = new AsyncInvoker (bh, eh, data);
+                       AsyncInvoker invoker = new AsyncInvoker (bh, eh, this, data);
                        PostUpdateRequestCache += new EventHandler (invoker.Invoke);
                }
 
@@ -674,61 +686,61 @@ namespace System.Web
                //
                public void AddOnAcquireRequestStateAsync (BeginEventHandler bh, EndEventHandler eh, object data)
                {
-                       AsyncInvoker invoker = new AsyncInvoker (bh, eh, data);
+                       AsyncInvoker invoker = new AsyncInvoker (bh, eh, this, data);
                        AcquireRequestState += new EventHandler (invoker.Invoke);
                }
 
                public void AddOnAuthenticateRequestAsync (BeginEventHandler bh, EndEventHandler eh, object data)
                {
-                       AsyncInvoker invoker = new AsyncInvoker (bh, eh, data);
+                       AsyncInvoker invoker = new AsyncInvoker (bh, eh, this, data);
                        AuthenticateRequest += new EventHandler (invoker.Invoke);
                }
 
                public void AddOnAuthorizeRequestAsync (BeginEventHandler bh, EndEventHandler eh, object data)
                {
-                       AsyncInvoker invoker = new AsyncInvoker (bh, eh, data);
+                       AsyncInvoker invoker = new AsyncInvoker (bh, eh, this, data);
                        AuthorizeRequest += new EventHandler (invoker.Invoke);
                }
 
                public void AddOnBeginRequestAsync (BeginEventHandler bh, EndEventHandler eh, object data)
                {
-                       AsyncInvoker invoker = new AsyncInvoker (bh, eh, data);
+                       AsyncInvoker invoker = new AsyncInvoker (bh, eh, this, data);
                        BeginRequest += new EventHandler (invoker.Invoke);
                }
 
                public void AddOnEndRequestAsync (BeginEventHandler bh, EndEventHandler eh, object data)
                {
-                       AsyncInvoker invoker = new AsyncInvoker (bh, eh, data);
+                       AsyncInvoker invoker = new AsyncInvoker (bh, eh, this, data);
                        EndRequest += new EventHandler (invoker.Invoke);
                }
                
                public void AddOnPostRequestHandlerExecuteAsync (BeginEventHandler bh, EndEventHandler eh, object data)
                {
-                       AsyncInvoker invoker = new AsyncInvoker (bh, eh, data);
+                       AsyncInvoker invoker = new AsyncInvoker (bh, eh, this, data);
                        PostRequestHandlerExecute += new EventHandler (invoker.Invoke);
                }
 
                public void AddOnPreRequestHandlerExecuteAsync (BeginEventHandler bh, EndEventHandler eh, object data)
                {
-                       AsyncInvoker invoker = new AsyncInvoker (bh, eh, data);
+                       AsyncInvoker invoker = new AsyncInvoker (bh, eh, this, data);
                        PreRequestHandlerExecute += new EventHandler (invoker.Invoke);
                }
 
                public void AddOnReleaseRequestStateAsync (BeginEventHandler bh, EndEventHandler eh, object data)
                {
-                       AsyncInvoker invoker = new AsyncInvoker (bh, eh, data);
+                       AsyncInvoker invoker = new AsyncInvoker (bh, eh, this, data);
                        ReleaseRequestState += new EventHandler (invoker.Invoke);
                }
 
                public void AddOnResolveRequestCacheAsync (BeginEventHandler bh, EndEventHandler eh, object data)
                {
-                       AsyncInvoker invoker = new AsyncInvoker (bh, eh, data);
+                       AsyncInvoker invoker = new AsyncInvoker (bh, eh, this, data);
                        ResolveRequestCache += new EventHandler (invoker.Invoke);
                }
 
                public void AddOnUpdateRequestCacheAsync (BeginEventHandler bh, EndEventHandler eh, object data)
                {
-                       AsyncInvoker invoker = new AsyncInvoker (bh, eh, data);
+                       AsyncInvoker invoker = new AsyncInvoker (bh, eh, this, data);
                        UpdateRequestCache += new EventHandler (invoker.Invoke);
                }
 
@@ -749,7 +761,7 @@ namespace System.Web
                
                public void AddOnLogRequestAsync (BeginEventHandler beginHandler, EndEventHandler endHandler, object state)
                {
-                       AsyncInvoker invoker = new AsyncInvoker (beginHandler, endHandler, state);
+                       AsyncInvoker invoker = new AsyncInvoker (beginHandler, endHandler, this, state);
                        LogRequest += new EventHandler (invoker.Invoke);
                }
 
@@ -767,7 +779,7 @@ namespace System.Web
 
                public void AddOnMapRequestHandlerAsync (BeginEventHandler beginHandler, EndEventHandler endHandler, object state)
                {
-                       AsyncInvoker invoker = new AsyncInvoker (beginHandler, endHandler, state);
+                       AsyncInvoker invoker = new AsyncInvoker (beginHandler, endHandler, this, state);
                        MapRequestHandler += new EventHandler (invoker.Invoke);
                }
 
@@ -785,7 +797,7 @@ namespace System.Web
 
                public void AddOnPostLogRequestAsync (BeginEventHandler beginHandler, EndEventHandler endHandler, object state)
                {
-                       AsyncInvoker invoker = new AsyncInvoker (beginHandler, endHandler, state);
+                       AsyncInvoker invoker = new AsyncInvoker (beginHandler, endHandler, this, state);
                        PostLogRequest += new EventHandler (invoker.Invoke);
                }
                
@@ -871,7 +883,7 @@ namespace System.Web
                //
                // If we catch an error, queue this error
                //
-               void ProcessError (Exception e)
+               internal void ProcessError (Exception e)
                {
                        bool first = context.Error == null;
                        context.AddError (e);
@@ -1643,7 +1655,39 @@ namespace System.Web
                                return true;
                        }
                }
-               
+
+               public static void RegisterModule (Type moduleType) 
+               {
+                       HttpRuntimeSection config = (HttpRuntimeSection)WebConfigurationManager.GetSection ("system.web/httpRuntime");
+
+                       if (!config.AllowDynamicModuleRegistration)
+                               throw new InvalidOperationException ("The Application has requested to register a dynamic Module, but dynamic module registration is disabled in web.config.");
+
+                       dynamicModuleManeger.Add (moduleType);
+               }
+
+
+               HttpModuleCollection CreateDynamicModules () 
+               {
+                       HttpModuleCollection modules = new HttpModuleCollection ();
+
+                       foreach (var module in dynamicModuleManeger.LockAndGetModules ()) {
+                               IHttpModule httpModule = CreateModuleInstance (module.Type);
+                               httpModule.Init (this);
+                               modules.AddModule (module.Name, httpModule);
+                       }
+                       return modules;
+               }
+
+               IHttpModule CreateModuleInstance (Type type)
+               {
+                       return (IHttpModule) Activator.CreateInstance (type,
+                                       BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.CreateInstance,
+                                       null,
+                                       null,
+                                       null);
+               }
+
 #region internals
                internal void ClearError ()
                {
@@ -1891,24 +1935,40 @@ namespace System.Web
                public BeginEventHandler begin;
                public EndEventHandler end;
                public object data;
+               HttpApplication app;
+               AsyncCallback callback;
                
-               public AsyncInvoker (BeginEventHandler bh, EndEventHandler eh, object d)
+               public AsyncInvoker (BeginEventHandler bh, EndEventHandler eh, HttpApplication a, object d)
                {
                        begin = bh;
                        end = eh;
                        data = d;
+                       app = a;
+                       callback = new AsyncCallback (doAsyncCallback);
                }
 
-               public AsyncInvoker (BeginEventHandler bh, EndEventHandler eh)
-               {
-                       begin = bh;
-                       end = eh;
-               }
+               public AsyncInvoker (BeginEventHandler bh, EndEventHandler eh, HttpApplication app) : this(bh, eh, app, null) { }
                
                public void Invoke (object sender, EventArgs e)
                {
-                       throw new Exception ("This is just a dummy");
+                       IAsyncResult res;
+                       res = begin (app, e, callback, data);
+               }
+
+               void doAsyncCallback (IAsyncResult res)
+               {
+                       ThreadPool.QueueUserWorkItem ((object ores) => {
+                               IAsyncResult tres = (IAsyncResult) ores;
+                               try {
+                                       end (tres);
+                               } catch (Exception ee) {
+                                       // I tried using ProcessError(), but we only come here frome an Invokation in PipelineDone().
+                                       // Using ProcessError, I still get a blank screen, this way, we at least log the error to console...
+                                       Console.Error.WriteLine (ee.ToString ());
+                               }
+                       }, res);
                }
        }
 #endregion
 }
+
index 8703eb00471f39775bcb5413a53b6d75c187bdd1..b074ec8f0a8cb9c7b928f59b9cddbeeb7c8a5044 100644 (file)
@@ -10,3 +10,4 @@ System.Web/UnvalidatedRequestValuesWrapper.cs
 System.Web/TaskAsyncResult.cs
 System.Web/TaskEventHandler.cs
 System.Web.Security/MembershipPasswordAttribute.cs
+System.Web/DynamicModuleManager.cs