├── .gitignore ├── .nuget ├── NuGet.exe ├── NuGet.settings.targets └── NuGet.targets ├── BuildNugetPackages.cmd ├── LICENSE.txt ├── Local.testsettings ├── README.markdown ├── TestLibrary ├── MyStartupCode.cs ├── Properties │ └── AssemblyInfo.cs └── TestLibrary.csproj ├── TestLibrary2 ├── MyOtherStartupCode.cs ├── Properties │ └── AssemblyInfo.cs └── TestLibrary2.csproj ├── TestWebApp ├── App_Code │ └── AppCodeStartupCode.cs ├── Content │ └── Site.css ├── Controllers │ ├── AccountController.cs │ └── HomeController.cs ├── Global.asax ├── Global.asax.cs ├── Models │ └── AccountModels.cs ├── Properties │ └── AssemblyInfo.cs ├── Scripts │ ├── MicrosoftAjax.debug.js │ ├── MicrosoftAjax.js │ ├── MicrosoftMvcAjax.debug.js │ ├── MicrosoftMvcAjax.js │ ├── MicrosoftMvcValidation.debug.js │ ├── MicrosoftMvcValidation.js │ ├── jquery-1.4.1-vsdoc.js │ ├── jquery-1.4.1.js │ ├── jquery-1.4.1.min.js │ ├── jquery.validate-vsdoc.js │ ├── jquery.validate.js │ └── jquery.validate.min.js ├── TestStartupCode │ ├── MyStartupCode.cs │ └── MyStartupCode2.cs ├── TestWebApp.csproj ├── Views │ ├── Account │ │ ├── ChangePassword.aspx │ │ ├── ChangePasswordSuccess.aspx │ │ ├── LogOn.aspx │ │ └── Register.aspx │ ├── Home │ │ ├── About.aspx │ │ └── Index.aspx │ ├── Shared │ │ ├── Error.aspx │ │ ├── LogOnUserControl.ascx │ │ └── Site.Master │ └── Web.config ├── Web.Debug.config ├── Web.Release.config ├── Web.config └── packages.config ├── TraceAndTestImpact.testsettings ├── WebActivator.sln ├── WebActivator.vsmdi ├── WebActivator ├── ActivationManager.cs ├── ApplicationShutdownMethodAttribute.cs ├── AssemblyExtensions.cs ├── BaseActivationMethodAttribute.cs ├── PostApplicationStartMethodAttribute.cs ├── PreApplicationStartMethodAttribute.cs ├── Properties │ ├── AssemblyInfo.cs │ └── WebActivator.nuspec ├── WebActivator.csproj └── packages.config └── WebActivatorTest ├── App.config ├── Properties └── AssemblyInfo.cs ├── WebActivatorTest.csproj └── WebActivatorUnitTest.cs /.gitignore: -------------------------------------------------------------------------------- 1 | bin 2 | obj 3 | Packages 4 | TestResults 5 | *.csproj.user 6 | *.vsp 7 | *.psess 8 | *.suo 9 | *.nupkg 10 | .vs -------------------------------------------------------------------------------- /.nuget/NuGet.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davidebbo/WebActivator/8a21247a5bdc61af3077bafceac602a9cb236875/.nuget/NuGet.exe -------------------------------------------------------------------------------- /.nuget/NuGet.settings.targets: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | $(MSBuildProjectDirectory)\..\ 5 | $(SolutionDir).nuget 6 | $(NuGetToolsPath)\nuget.exe 7 | $(ProjectDir)packages.config 8 | $(SolutionDir)packages 9 | $(TargetDir.Trim('\\')) 10 | 11 | 12 | "" 13 | 14 | 15 | false 16 | 17 | 18 | false 19 | 20 | 21 | "$(NuGetExePath)" install "$(PackagesConfig)" -source $(PackageSources) -o "$(PackagesDir)" 22 | "$(NuGetExePath)" pack "$(ProjectPath)" -p Configuration=$(Configuration) -o "$(PackageOutputDir)" -symbols 23 | 24 | 25 | 26 | RestorePackages; 27 | $(BuildDependsOn); 28 | 29 | 30 | 31 | 32 | $(BuildDependsOn); 33 | BuildPackage; 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /.nuget/NuGet.targets: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 9 | 10 | 11 | 12 | 14 | 15 | -------------------------------------------------------------------------------- /BuildNugetPackages.cmd: -------------------------------------------------------------------------------- 1 | pushd WebActivator 2 | msbuild /p:Configuration=Release 3 | nuget pack -symbols -Prop Configuration=Release 4 | move *.nupkg .. 5 | popd 6 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | -------------------------------------------------------------------------------- /Local.testsettings: -------------------------------------------------------------------------------- 1 |  2 | 3 | These are default test settings for a local test run. 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /README.markdown: -------------------------------------------------------------------------------- 1 | WebActivator 2 | ============ 3 | 4 | WebActivator is a [NuGet](http://nuget.org/) package that allows other packages to easily bring in Startup and Shutdown code into a web application. This gives a much cleaner solution than having to modify global.asax with the startup logic from many packages. 5 | 6 | ## Integrating WebActivator into your package 7 | 8 | ### Step 1: Add a dependency on it in your package's nuspec file 9 | 10 | 11 | 12 | 13 | MySuperPackage 14 | etc... 15 | 16 | 17 | 18 | 19 | 20 | 21 | The only thing that needs to be added for WebActivator is the `` line. 22 | 23 | ### Step 2: Add a preprocessed source file in Content\App_Start 24 | 25 | Under the folder where your nuspec file is, create a Content\App_Start folder. In there, create a file named MySuperPackage.cs.pp: 26 | 27 | using System; 28 | 29 | [assembly: WebActivatorEx.PreApplicationStartMethod( 30 | typeof($rootnamespace$.App_Start.MySuperPackage), "PreStart")] 31 | 32 | namespace $rootnamespace$.App_Start { 33 | public static class MySuperPackage { 34 | public static void PreStart() { 35 | // Add your start logic here 36 | } 37 | } 38 | } 39 | 40 | And that's it! Now your code will be called early on when the app starts. 41 | 42 | ## Choosing when your code executes 43 | 44 | The example above uses the PreApplicationStartMethod attribute, which makes the code run very early on, before global.asax's Application_Start gets to run. 45 | 46 | If that's too early for you, you can instead use the PostApplicationStartMethod attribute, which gets your code called //after// global.asax's Application_Start. 47 | 48 | And if you have some logic you'd like to execute when the app shuts down, you can use the ApplicationShutdownMethod attribute. 49 | 50 | Other than their name changing, all three attributes are used the same way. 51 | 52 | ## Please follow the folder convention 53 | 54 | As you saw in the example above, I placed the .cs.pp file under the App_Start folder, such that when someone installs your package, the .cs file ends up in the App_Start folder under the app root. Technically, WebActivator does not require this, but it's a good convention to follow so that the startup code from all the packages all ends up in one folder rather than being at the root of the app (which we don't want to pollute). 55 | 56 | The picky ones will bring up that App_Start is not a great name when you use WebActivator for shut down logic. Maybe so, but since shut down logic is somewhat rare, and often goes along with startup logic, it's best to keep everything under App_Start and live with this small naming anomaly :) 57 | 58 | ## Support for Web Sites 59 | 60 | In a Web Site (as opposed to a Web Application), you typically put your shared code in the App_Code folder. If you have code in there that uses the PostApplicationStartMethod attribute, it will get called when the app starts, giving Web Sites some WebActivator love. 61 | 62 | Please note that you can only use PostApplicationStartMethod in App_Code, and not PreApplicationStartMethod. The reason is that when PreApplicationStartMethod fires, the App_Code folder has not even been compiled! 63 | 64 | ## Support for invoking the start methods outside of ASP.NET 65 | 66 | This change came courtesy of [Jakub Konecki](http://stackoverflow.com/users/449906/jakub-konecki), who needed it for unit testing purpose. This comes as a set of static methods that you can use to invoke the startup methods: 67 | 68 | // Run all the WebActivator PreStart methods 69 | WebActivator.ActivationManager.RunPreStartMethods(); 70 | 71 | // Run all the WebActivator PostStart methods 72 | WebActivator.ActivationManager.RunPostStartMethods(); 73 | 74 | // Run all the WebActivator start methods 75 | WebActivator.ActivationManager.Run(); 76 | 77 | // Run all the WebActivator shutdown methods 78 | WebActivator.ActivationManager.RunShutdownMethods(); 79 | 80 | Note that normally you would not call these methods explicitly from a web application. But if you are using some 'WebActivated' NuGet packages from a different type of apps (say a Console app), it could make sense to have add calls to Run() and RunShutdownMethods() at the beginning and end of your app. 81 | 82 | ## Change history 83 | 84 | ### 2.2.0 (10/5/2016) 85 | 86 | * Add support for `webactivator:assembliesToScan` App Setting to only scan a fixed list. 87 | 88 | e.g. 89 | 90 | 91 | 92 | This overrides the excludedFilesExpression flag 93 | 94 | ### 2.1.0 (12/14/2015) 95 | 96 | * Add support for `webactivator:excludedFilesExpression` App Setting. https://github.com/davidebbo/WebActivator/issues/28 97 | 98 | ### 2.0.6 (11/24/2014) 99 | 100 | * Re-release under Apache 2 license 101 | 102 | ### 2.0.5 (3/10/2014) 103 | 104 | * Use Retail instead of Debug assembly in NuGet package 105 | 106 | ### 2.0.4 (11/18/2013) 107 | 108 | * Fixed to work on Mono https://github.com/davidebbo/WebActivator/pull/15 109 | 110 | ### 2.0.3 (8/6/2013) 111 | 112 | * Make the Order parameter work across multiple assemblies https://github.com/davidebbo/WebActivator/pull/13 113 | 114 | ### 2.0.2 (6/19/2013) 115 | 116 | * Ignore GetCustomAttributes exceptions to work around https://github.com/davidebbo/WebActivator/issues/12 117 | 118 | ### 2.0.1 (2/9/2013) 119 | 120 | * The WebActivator assembly is now signed (and is now named WebActivatorEx.dll) 121 | 122 | ### 1.5.3 (12/20/2012) 123 | 124 | Change contributed by @gdoten 125 | 126 | * Look in CodeBase rather than Location directory for assemblies to scan for attirbutes. 127 | * Make Assembly.LoadFrom exception handling a little more specific. 128 | * Fix to unit testing ExecuteOrder when all test are run at the same time. 129 | 130 | ### 1.5.2 (11/2/2012) 131 | 132 | * Only difference with 1.5.1 is the corrected project site link so it points to github instead of the old bitbuck 133 | 134 | ### 1.5.1 (5/31/2012) 135 | 136 | * Rerelease after moving from bitbucket to github 137 | 138 | ### 1.5 (10/26/2011) 139 | 140 | * Added ability to order method invocations within one assembly 141 | 142 | ### 1.4.3 (9/14/2011) 143 | 144 | * Take dependency on Microsoft.Web.Infrastructure 145 | 146 | ### 1.4 (2/28/2011) 147 | 148 | * Added ability to run code when the app shuts down 149 | 150 | ### 1.3 (2/24/2011) 151 | 152 | * Added support for Web Sites 153 | 154 | ### 1.2 (2/21/2011) 155 | 156 | * Added support for executing WebActivator outside ASP.NET runtime 157 | 158 | ### 1.1 (2/15/2011) 159 | 160 | * Added support for methods called after global.asax App_Start 161 | 162 | ### 1.0 (10/8/2010) 163 | 164 | * Initial release 165 | 166 | 167 | ## Related blog posts 168 | 169 | [Light up your NuGets with startup code and WebActivator](http://blogs.msdn.com/b/davidebb/archive/2010/10/11/light-up-your-nupacks-with-startup-code-and-webactivator.aspx) 170 | 171 | [New features in WebActivator 1.4](http://blog.davidebbo.com/2011/02/new-features-in-webactivator-13.html) 172 | 173 | [App_Start folder convention for NuGet and WebActivator](http://blog.davidebbo.com/2011/02/appstart-folder-convention-for-nuget.html) 174 | 175 | -------------------------------------------------------------------------------- /TestLibrary/MyStartupCode.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using WebActivatorEx; 3 | 4 | [assembly: PreApplicationStartMethod(typeof(TestLibrary.MyStartupCode), "Start", RunInDesigner = true)] 5 | [assembly: PreApplicationStartMethod(typeof(TestLibrary.MyStartupCode), "Start2", Order = 3)] 6 | [assembly: PreApplicationStartMethod(typeof(TestLibrary.MyStartupCode), "Start3", Order = 1)] 7 | [assembly: PostApplicationStartMethod(typeof(TestLibrary.MyStartupCode), "CallMeAfterAppStart")] 8 | [assembly: ApplicationShutdownMethod(typeof(TestLibrary.MyStartupCode), "CallMeWhenAppEnds")] 9 | 10 | namespace TestLibrary 11 | { 12 | public static class ExecutionLogger 13 | { 14 | public static string ExecutedOrder = ""; 15 | } 16 | 17 | public static class MyStartupCode 18 | { 19 | public static bool StartCalled { get; set; } 20 | public static bool Start2Called { get; set; } 21 | public static bool CallMeAfterAppStartCalled { get; set; } 22 | public static bool CallMeWhenAppEndsCalled { get; set; } 23 | 24 | internal static void Start() 25 | { 26 | if (StartCalled) 27 | { 28 | throw new Exception("Unexpected second call to Start"); 29 | } 30 | 31 | StartCalled = true; 32 | ExecutionLogger.ExecutedOrder += "Start"; 33 | } 34 | 35 | public static void Start2() 36 | { 37 | if (Start2Called) 38 | { 39 | throw new Exception("Unexpected second call to Start2"); 40 | } 41 | 42 | Start2Called = true; 43 | ExecutionLogger.ExecutedOrder += "Start2"; 44 | } 45 | 46 | public static void Start3() 47 | { 48 | ExecutionLogger.ExecutedOrder += "Start3"; 49 | } 50 | 51 | public static void CallMeAfterAppStart() 52 | { 53 | // This gets called after global.asax's Application_Start 54 | 55 | if (CallMeAfterAppStartCalled) 56 | { 57 | throw new Exception("Unexpected second call to CallMeAfterAppStart"); 58 | } 59 | 60 | CallMeAfterAppStartCalled = true; 61 | ExecutionLogger.ExecutedOrder += "CallMeAfterAppStart"; 62 | } 63 | 64 | public static void CallMeWhenAppEnds() 65 | { 66 | // This gets called when the app shuts down 67 | 68 | if (CallMeWhenAppEndsCalled) 69 | { 70 | throw new Exception("Unexpected second call to CallMeWhenAppEnds"); 71 | } 72 | 73 | CallMeWhenAppEndsCalled = true; 74 | ExecutionLogger.ExecutedOrder += "CallMeWhenAppEnds"; 75 | } 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /TestLibrary/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("TestLibrary")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("Microsoft")] 12 | [assembly: AssemblyProduct("TestLibrary")] 13 | [assembly: AssemblyCopyright("Copyright © Microsoft 2010")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("a712d194-8916-465b-b50c-1b2f40644087")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /TestLibrary/TestLibrary.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Debug 5 | AnyCPU 6 | 8.0.30703 7 | 2.0 8 | {3D5B026A-2E5F-4C03-8F70-945517215017} 9 | Library 10 | Properties 11 | TestLibrary 12 | TestLibrary 13 | v4.0 14 | 512 15 | ..\ 16 | true 17 | 18 | 19 | true 20 | full 21 | false 22 | bin\Debug\ 23 | DEBUG;TRACE 24 | prompt 25 | 4 26 | 27 | 28 | pdbonly 29 | true 30 | bin\Release\ 31 | TRACE 32 | prompt 33 | 4 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | {339C42C9-C961-4E37-B64E-16F1EF03E4D9} 54 | WebActivator 55 | 56 | 57 | 58 | 59 | 66 | -------------------------------------------------------------------------------- /TestLibrary2/MyOtherStartupCode.cs: -------------------------------------------------------------------------------- 1 |  2 | using System; 3 | using TestLibrary; 4 | using WebActivatorEx; 5 | 6 | [assembly: PreApplicationStartMethod(typeof(TestLibrary2.MyOtherStartupCode), "Start", Order = 2)] 7 | [assembly: PreApplicationStartMethod(typeof(TestLibrary2.MyOtherStartupCode), "Start2", Order = 4)] 8 | 9 | 10 | namespace TestLibrary2 11 | { 12 | public static class MyOtherStartupCode 13 | { 14 | public static bool StartCalled { get; set; } 15 | public static bool Start2Called { get; set; } 16 | 17 | internal static void Start() 18 | { 19 | if (StartCalled) 20 | { 21 | throw new Exception("Unexpected second call to Start"); 22 | } 23 | 24 | StartCalled = true; 25 | ExecutionLogger.ExecutedOrder += "OtherStart"; 26 | } 27 | 28 | public static void Start2() 29 | { 30 | if (Start2Called) 31 | { 32 | throw new Exception("Unexpected second call to Start2"); 33 | } 34 | 35 | Start2Called = true; 36 | ExecutionLogger.ExecutedOrder += "OtherStart2"; 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /TestLibrary2/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("TestLibrary2")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("TestLibrary2")] 13 | [assembly: AssemblyCopyright("Copyright © 2013")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("bfe276da-e81c-4dab-8c27-276d085e0a52")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /TestLibrary2/TestLibrary2.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Debug 5 | AnyCPU 6 | 8.0.30703 7 | 2.0 8 | {638765A7-E010-495F-B325-821D735B2121} 9 | Library 10 | Properties 11 | TestLibrary2 12 | TestLibrary2 13 | v4.0 14 | 512 15 | 16 | 17 | true 18 | full 19 | false 20 | bin\Debug\ 21 | DEBUG;TRACE 22 | prompt 23 | 4 24 | 25 | 26 | pdbonly 27 | true 28 | bin\Release\ 29 | TRACE 30 | prompt 31 | 4 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | {3D5B026A-2E5F-4C03-8F70-945517215017} 49 | TestLibrary 50 | 51 | 52 | {339C42C9-C961-4E37-B64E-16F1EF03E4D9} 53 | WebActivator 54 | 55 | 56 | 57 | 64 | -------------------------------------------------------------------------------- /TestWebApp/App_Code/AppCodeStartupCode.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Web; 5 | 6 | [assembly: WebActivatorEx.PostApplicationStartMethod(typeof(AppCodeStartupCode), "Start")] 7 | [assembly: WebActivatorEx.ApplicationShutdownMethodAttribute(typeof(AppCodeStartupCode), "Shutdown")] 8 | 9 | public class AppCodeStartupCode 10 | { 11 | public static bool StartCalled { get; set; } 12 | public static void Start() 13 | { 14 | if (StartCalled) 15 | { 16 | throw new Exception("Unexpected second call to Start"); 17 | } 18 | 19 | StartCalled = true; 20 | } 21 | 22 | public static bool ShutdownCalled { get; set; } 23 | public static void Shutdown() 24 | { 25 | if (ShutdownCalled) 26 | { 27 | throw new Exception("Unexpected second call to Shutdown"); 28 | } 29 | 30 | ShutdownCalled = true; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /TestWebApp/Content/Site.css: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------- 2 | The base color for this template is #5c87b2. If you'd like 3 | to use a different color start by replacing all instances of 4 | #5c87b2 with your new color. 5 | ----------------------------------------------------------*/ 6 | body 7 | { 8 | background-color: #5c87b2; 9 | font-size: .75em; 10 | font-family: Verdana, Helvetica, Sans-Serif; 11 | margin: 0; 12 | padding: 0; 13 | color: #696969; 14 | } 15 | 16 | a:link 17 | { 18 | color: #034af3; 19 | text-decoration: underline; 20 | } 21 | a:visited 22 | { 23 | color: #505abc; 24 | } 25 | a:hover 26 | { 27 | color: #1d60ff; 28 | text-decoration: none; 29 | } 30 | a:active 31 | { 32 | color: #12eb87; 33 | } 34 | 35 | p, ul 36 | { 37 | margin-bottom: 20px; 38 | line-height: 1.6em; 39 | } 40 | 41 | /* HEADINGS 42 | ----------------------------------------------------------*/ 43 | h1, h2, h3, h4, h5, h6 44 | { 45 | font-size: 1.5em; 46 | color: #000; 47 | font-family: Arial, Helvetica, sans-serif; 48 | } 49 | 50 | h1 51 | { 52 | font-size: 2em; 53 | padding-bottom: 0; 54 | margin-bottom: 0; 55 | } 56 | h2 57 | { 58 | padding: 0 0 10px 0; 59 | } 60 | h3 61 | { 62 | font-size: 1.2em; 63 | } 64 | h4 65 | { 66 | font-size: 1.1em; 67 | } 68 | h5, h6 69 | { 70 | font-size: 1em; 71 | } 72 | 73 | /* this rule styles

tags that are the 74 | first child of the left and right table columns */ 75 | .rightColumn > h1, .rightColumn > h2, .leftColumn > h1, .leftColumn > h2 76 | { 77 | margin-top: 0; 78 | } 79 | 80 | /* PRIMARY LAYOUT ELEMENTS 81 | ----------------------------------------------------------*/ 82 | 83 | /* you can specify a greater or lesser percentage for the 84 | page width. Or, you can specify an exact pixel width. */ 85 | .page 86 | { 87 | width: 90%; 88 | margin-left: auto; 89 | margin-right: auto; 90 | } 91 | 92 | #header 93 | { 94 | position: relative; 95 | margin-bottom: 0px; 96 | color: #000; 97 | padding: 0; 98 | } 99 | 100 | #header h1 101 | { 102 | font-weight: bold; 103 | padding: 5px 0; 104 | margin: 0; 105 | color: #fff; 106 | border: none; 107 | line-height: 2em; 108 | font-family: Arial, Helvetica, sans-serif; 109 | font-size: 32px !important; 110 | } 111 | 112 | #main 113 | { 114 | padding: 30px 30px 15px 30px; 115 | background-color: #fff; 116 | margin-bottom: 30px; 117 | _height: 1px; /* only IE6 applies CSS properties starting with an underscore */ 118 | } 119 | 120 | #footer 121 | { 122 | color: #999; 123 | padding: 10px 0; 124 | text-align: center; 125 | line-height: normal; 126 | margin: 0; 127 | font-size: .9em; 128 | } 129 | 130 | /* TAB MENU 131 | ----------------------------------------------------------*/ 132 | ul#menu 133 | { 134 | border-bottom: 1px #5C87B2 solid; 135 | padding: 0 0 2px; 136 | position: relative; 137 | margin: 0; 138 | text-align: right; 139 | } 140 | 141 | ul#menu li 142 | { 143 | display: inline; 144 | list-style: none; 145 | } 146 | 147 | ul#menu li#greeting 148 | { 149 | padding: 10px 20px; 150 | font-weight: bold; 151 | text-decoration: none; 152 | line-height: 2.8em; 153 | color: #fff; 154 | } 155 | 156 | ul#menu li a 157 | { 158 | padding: 10px 20px; 159 | font-weight: bold; 160 | text-decoration: none; 161 | line-height: 2.8em; 162 | background-color: #e8eef4; 163 | color: #034af3; 164 | } 165 | 166 | ul#menu li a:hover 167 | { 168 | background-color: #fff; 169 | text-decoration: none; 170 | } 171 | 172 | ul#menu li a:active 173 | { 174 | background-color: #a6e2a6; 175 | text-decoration: none; 176 | } 177 | 178 | ul#menu li.selected a 179 | { 180 | background-color: #fff; 181 | color: #000; 182 | } 183 | 184 | /* FORM LAYOUT ELEMENTS 185 | ----------------------------------------------------------*/ 186 | 187 | fieldset 188 | { 189 | margin: 1em 0; 190 | padding: 1em; 191 | border: 1px solid #CCC; 192 | } 193 | 194 | fieldset p 195 | { 196 | margin: 2px 12px 10px 10px; 197 | } 198 | 199 | legend 200 | { 201 | font-size: 1.1em; 202 | font-weight: 600; 203 | padding: 2px 4px 8px 4px; 204 | } 205 | 206 | input[type="text"] 207 | { 208 | width: 200px; 209 | border: 1px solid #CCC; 210 | } 211 | 212 | input[type="password"] 213 | { 214 | width: 200px; 215 | border: 1px solid #CCC; 216 | } 217 | 218 | /* TABLE 219 | ----------------------------------------------------------*/ 220 | 221 | table 222 | { 223 | border: solid 1px #e8eef4; 224 | border-collapse: collapse; 225 | } 226 | 227 | table td 228 | { 229 | padding: 5px; 230 | border: solid 1px #e8eef4; 231 | } 232 | 233 | table th 234 | { 235 | padding: 6px 5px; 236 | text-align: left; 237 | background-color: #e8eef4; 238 | border: solid 1px #e8eef4; 239 | } 240 | 241 | /* MISC 242 | ----------------------------------------------------------*/ 243 | .clear 244 | { 245 | clear: both; 246 | } 247 | 248 | .error 249 | { 250 | color:Red; 251 | } 252 | 253 | #menucontainer 254 | { 255 | margin-top:40px; 256 | } 257 | 258 | div#title 259 | { 260 | display:block; 261 | float:left; 262 | text-align:left; 263 | } 264 | 265 | #logindisplay 266 | { 267 | font-size:1.1em; 268 | display:block; 269 | text-align:right; 270 | margin:10px; 271 | color:White; 272 | } 273 | 274 | #logindisplay a:link 275 | { 276 | color: white; 277 | text-decoration: underline; 278 | } 279 | 280 | #logindisplay a:visited 281 | { 282 | color: white; 283 | text-decoration: underline; 284 | } 285 | 286 | #logindisplay a:hover 287 | { 288 | color: white; 289 | text-decoration: none; 290 | } 291 | 292 | /* Styles for validation helpers 293 | -----------------------------------------------------------*/ 294 | .field-validation-error 295 | { 296 | color: #ff0000; 297 | } 298 | 299 | .field-validation-valid 300 | { 301 | display: none; 302 | } 303 | 304 | .input-validation-error 305 | { 306 | border: 1px solid #ff0000; 307 | background-color: #ffeeee; 308 | } 309 | 310 | .validation-summary-errors 311 | { 312 | font-weight: bold; 313 | color: #ff0000; 314 | } 315 | 316 | .validation-summary-valid 317 | { 318 | display: none; 319 | } 320 | 321 | /* Styles for editor and display helpers 322 | ----------------------------------------------------------*/ 323 | .display-label, 324 | .editor-label, 325 | .display-field, 326 | .editor-field 327 | { 328 | margin: 0.5em 0; 329 | } 330 | 331 | .text-box 332 | { 333 | width: 30em; 334 | } 335 | 336 | .text-box.multi-line 337 | { 338 | height: 6.5em; 339 | } 340 | 341 | .tri-state 342 | { 343 | width: 6em; 344 | } 345 | -------------------------------------------------------------------------------- /TestWebApp/Controllers/AccountController.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics.CodeAnalysis; 4 | using System.Linq; 5 | using System.Security.Principal; 6 | using System.Web; 7 | using System.Web.Mvc; 8 | using System.Web.Routing; 9 | using System.Web.Security; 10 | using TestWebApp.Models; 11 | 12 | namespace TestWebApp.Controllers 13 | { 14 | public class AccountController : Controller 15 | { 16 | 17 | public IFormsAuthenticationService FormsService { get; set; } 18 | public IMembershipService MembershipService { get; set; } 19 | 20 | protected override void Initialize(RequestContext requestContext) 21 | { 22 | if (FormsService == null) { FormsService = new FormsAuthenticationService(); } 23 | if (MembershipService == null) { MembershipService = new AccountMembershipService(); } 24 | 25 | base.Initialize(requestContext); 26 | } 27 | 28 | // ************************************** 29 | // URL: /Account/LogOn 30 | // ************************************** 31 | 32 | public ActionResult LogOn() 33 | { 34 | return View(); 35 | } 36 | 37 | [HttpPost] 38 | public ActionResult LogOn(LogOnModel model, string returnUrl) 39 | { 40 | if (ModelState.IsValid) 41 | { 42 | if (MembershipService.ValidateUser(model.UserName, model.Password)) 43 | { 44 | FormsService.SignIn(model.UserName, model.RememberMe); 45 | if (!String.IsNullOrEmpty(returnUrl) && Url.IsLocalUrl(returnUrl)) 46 | { 47 | return Redirect(returnUrl); 48 | } 49 | else 50 | { 51 | return RedirectToAction("Index", "Home"); 52 | } 53 | } 54 | else 55 | { 56 | ModelState.AddModelError("", "The user name or password provided is incorrect."); 57 | } 58 | } 59 | 60 | // If we got this far, something failed, redisplay form 61 | return View(model); 62 | } 63 | 64 | // ************************************** 65 | // URL: /Account/LogOff 66 | // ************************************** 67 | 68 | public ActionResult LogOff() 69 | { 70 | FormsService.SignOut(); 71 | 72 | return RedirectToAction("Index", "Home"); 73 | } 74 | 75 | // ************************************** 76 | // URL: /Account/Register 77 | // ************************************** 78 | 79 | public ActionResult Register() 80 | { 81 | ViewBag.PasswordLength = MembershipService.MinPasswordLength; 82 | return View(); 83 | } 84 | 85 | [HttpPost] 86 | public ActionResult Register(RegisterModel model) 87 | { 88 | if (ModelState.IsValid) 89 | { 90 | // Attempt to register the user 91 | MembershipCreateStatus createStatus = MembershipService.CreateUser(model.UserName, model.Password, model.Email); 92 | 93 | if (createStatus == MembershipCreateStatus.Success) 94 | { 95 | FormsService.SignIn(model.UserName, false /* createPersistentCookie */); 96 | return RedirectToAction("Index", "Home"); 97 | } 98 | else 99 | { 100 | ModelState.AddModelError("", AccountValidation.ErrorCodeToString(createStatus)); 101 | } 102 | } 103 | 104 | // If we got this far, something failed, redisplay form 105 | ViewBag.PasswordLength = MembershipService.MinPasswordLength; 106 | return View(model); 107 | } 108 | 109 | // ************************************** 110 | // URL: /Account/ChangePassword 111 | // ************************************** 112 | 113 | [Authorize] 114 | public ActionResult ChangePassword() 115 | { 116 | ViewBag.PasswordLength = MembershipService.MinPasswordLength; 117 | return View(); 118 | } 119 | 120 | [Authorize] 121 | [HttpPost] 122 | public ActionResult ChangePassword(ChangePasswordModel model) 123 | { 124 | if (ModelState.IsValid) 125 | { 126 | if (MembershipService.ChangePassword(User.Identity.Name, model.OldPassword, model.NewPassword)) 127 | { 128 | return RedirectToAction("ChangePasswordSuccess"); 129 | } 130 | else 131 | { 132 | ModelState.AddModelError("", "The current password is incorrect or the new password is invalid."); 133 | } 134 | } 135 | 136 | // If we got this far, something failed, redisplay form 137 | ViewBag.PasswordLength = MembershipService.MinPasswordLength; 138 | return View(model); 139 | } 140 | 141 | // ************************************** 142 | // URL: /Account/ChangePasswordSuccess 143 | // ************************************** 144 | 145 | public ActionResult ChangePasswordSuccess() 146 | { 147 | return View(); 148 | } 149 | 150 | } 151 | } 152 | -------------------------------------------------------------------------------- /TestWebApp/Controllers/HomeController.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Web; 5 | using System.Web.Mvc; 6 | 7 | namespace TestWebApp.Controllers 8 | { 9 | public class HomeController : Controller 10 | { 11 | public ActionResult Index() 12 | { 13 | ViewBag.Message = "Welcome to ASP.NET MVC!"; 14 | 15 | return View(); 16 | } 17 | 18 | public ActionResult About() 19 | { 20 | return View(); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /TestWebApp/Global.asax: -------------------------------------------------------------------------------- 1 | <%@ Application Codebehind="Global.asax.cs" Inherits="TestWebApp.MvcApplication" Language="C#" %> 2 | -------------------------------------------------------------------------------- /TestWebApp/Global.asax.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Web; 5 | using System.Web.Mvc; 6 | using System.Web.Routing; 7 | 8 | namespace TestWebApp 9 | { 10 | // Note: For instructions on enabling IIS6 or IIS7 classic mode, 11 | // visit http://go.microsoft.com/?LinkId=9394801 12 | 13 | public class MvcApplication : System.Web.HttpApplication 14 | { 15 | public static void RegisterGlobalFilters(GlobalFilterCollection filters) 16 | { 17 | filters.Add(new HandleErrorAttribute()); 18 | } 19 | 20 | public static void RegisterRoutes(RouteCollection routes) 21 | { 22 | routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); 23 | 24 | routes.MapRoute( 25 | "Default", // Route name 26 | "{controller}/{action}/{id}", // URL with parameters 27 | new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults 28 | ); 29 | 30 | } 31 | 32 | protected void Application_Start() 33 | { 34 | AreaRegistration.RegisterAllAreas(); 35 | 36 | RegisterGlobalFilters(GlobalFilters.Filters); 37 | RegisterRoutes(RouteTable.Routes); 38 | } 39 | } 40 | } -------------------------------------------------------------------------------- /TestWebApp/Models/AccountModels.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.ComponentModel.DataAnnotations; 5 | using System.Globalization; 6 | using System.Linq; 7 | using System.Web; 8 | using System.Web.Mvc; 9 | using System.Web.Security; 10 | 11 | namespace TestWebApp.Models 12 | { 13 | 14 | #region Models 15 | [PropertiesMustMatch("NewPassword", "ConfirmPassword", ErrorMessage = "The new password and confirmation password do not match.")] 16 | public class ChangePasswordModel 17 | { 18 | [Required] 19 | [DataType(DataType.Password)] 20 | [Display(Name = "Current password")] 21 | public string OldPassword { get; set; } 22 | 23 | [Required] 24 | [ValidatePasswordLength] 25 | [DataType(DataType.Password)] 26 | [Display(Name = "New password")] 27 | public string NewPassword { get; set; } 28 | 29 | [Required] 30 | [DataType(DataType.Password)] 31 | [Display(Name = "Confirm new password")] 32 | public string ConfirmPassword { get; set; } 33 | } 34 | 35 | public class LogOnModel 36 | { 37 | [Required] 38 | [Display(Name = "User name")] 39 | public string UserName { get; set; } 40 | 41 | [Required] 42 | [DataType(DataType.Password)] 43 | [Display(Name = "Password")] 44 | public string Password { get; set; } 45 | 46 | [Display(Name = "Remember me?")] 47 | public bool RememberMe { get; set; } 48 | } 49 | 50 | [PropertiesMustMatch("Password", "ConfirmPassword", ErrorMessage = "The password and confirmation password do not match.")] 51 | public class RegisterModel 52 | { 53 | [Required] 54 | [Display(Name = "User name")] 55 | public string UserName { get; set; } 56 | 57 | [Required] 58 | [DataType(DataType.EmailAddress)] 59 | [Display(Name = "Email address")] 60 | public string Email { get; set; } 61 | 62 | [Required] 63 | [ValidatePasswordLength] 64 | [DataType(DataType.Password)] 65 | [Display(Name = "Password")] 66 | public string Password { get; set; } 67 | 68 | [Required] 69 | [DataType(DataType.Password)] 70 | [Display(Name = "Confirm password")] 71 | public string ConfirmPassword { get; set; } 72 | } 73 | #endregion 74 | 75 | #region Services 76 | // The FormsAuthentication type is sealed and contains static members, so it is difficult to 77 | // unit test code that calls its members. The interface and helper class below demonstrate 78 | // how to create an abstract wrapper around such a type in order to make the AccountController 79 | // code unit testable. 80 | 81 | public interface IMembershipService 82 | { 83 | int MinPasswordLength { get; } 84 | 85 | bool ValidateUser(string userName, string password); 86 | MembershipCreateStatus CreateUser(string userName, string password, string email); 87 | bool ChangePassword(string userName, string oldPassword, string newPassword); 88 | } 89 | 90 | public class AccountMembershipService : IMembershipService 91 | { 92 | private readonly MembershipProvider _provider; 93 | 94 | public AccountMembershipService() 95 | : this(null) 96 | { 97 | } 98 | 99 | public AccountMembershipService(MembershipProvider provider) 100 | { 101 | _provider = provider ?? Membership.Provider; 102 | } 103 | 104 | public int MinPasswordLength 105 | { 106 | get 107 | { 108 | return _provider.MinRequiredPasswordLength; 109 | } 110 | } 111 | 112 | public bool ValidateUser(string userName, string password) 113 | { 114 | if (String.IsNullOrEmpty(userName)) throw new ArgumentException("Value cannot be null or empty.", "userName"); 115 | if (String.IsNullOrEmpty(password)) throw new ArgumentException("Value cannot be null or empty.", "password"); 116 | 117 | return _provider.ValidateUser(userName, password); 118 | } 119 | 120 | public MembershipCreateStatus CreateUser(string userName, string password, string email) 121 | { 122 | if (String.IsNullOrEmpty(userName)) throw new ArgumentException("Value cannot be null or empty.", "userName"); 123 | if (String.IsNullOrEmpty(password)) throw new ArgumentException("Value cannot be null or empty.", "password"); 124 | if (String.IsNullOrEmpty(email)) throw new ArgumentException("Value cannot be null or empty.", "email"); 125 | 126 | MembershipCreateStatus status; 127 | _provider.CreateUser(userName, password, email, null, null, true, null, out status); 128 | return status; 129 | } 130 | 131 | public bool ChangePassword(string userName, string oldPassword, string newPassword) 132 | { 133 | if (String.IsNullOrEmpty(userName)) throw new ArgumentException("Value cannot be null or empty.", "userName"); 134 | if (String.IsNullOrEmpty(oldPassword)) throw new ArgumentException("Value cannot be null or empty.", "oldPassword"); 135 | if (String.IsNullOrEmpty(newPassword)) throw new ArgumentException("Value cannot be null or empty.", "newPassword"); 136 | 137 | // The underlying ChangePassword() will throw an exception rather 138 | // than return false in certain failure scenarios. 139 | try 140 | { 141 | MembershipUser currentUser = _provider.GetUser(userName, true /* userIsOnline */); 142 | return currentUser.ChangePassword(oldPassword, newPassword); 143 | } 144 | catch (ArgumentException) 145 | { 146 | return false; 147 | } 148 | catch (MembershipPasswordException) 149 | { 150 | return false; 151 | } 152 | } 153 | } 154 | 155 | public interface IFormsAuthenticationService 156 | { 157 | void SignIn(string userName, bool createPersistentCookie); 158 | void SignOut(); 159 | } 160 | 161 | public class FormsAuthenticationService : IFormsAuthenticationService 162 | { 163 | public void SignIn(string userName, bool createPersistentCookie) 164 | { 165 | if (String.IsNullOrEmpty(userName)) throw new ArgumentException("Value cannot be null or empty.", "userName"); 166 | 167 | FormsAuthentication.SetAuthCookie(userName, createPersistentCookie); 168 | } 169 | 170 | public void SignOut() 171 | { 172 | FormsAuthentication.SignOut(); 173 | } 174 | } 175 | #endregion 176 | 177 | #region Validation 178 | public static class AccountValidation 179 | { 180 | public static string ErrorCodeToString(MembershipCreateStatus createStatus) 181 | { 182 | // See http://go.microsoft.com/fwlink/?LinkID=177550 for 183 | // a full list of status codes. 184 | switch (createStatus) 185 | { 186 | case MembershipCreateStatus.DuplicateUserName: 187 | return "Username already exists. Please enter a different user name."; 188 | 189 | case MembershipCreateStatus.DuplicateEmail: 190 | return "A username for that e-mail address already exists. Please enter a different e-mail address."; 191 | 192 | case MembershipCreateStatus.InvalidPassword: 193 | return "The password provided is invalid. Please enter a valid password value."; 194 | 195 | case MembershipCreateStatus.InvalidEmail: 196 | return "The e-mail address provided is invalid. Please check the value and try again."; 197 | 198 | case MembershipCreateStatus.InvalidAnswer: 199 | return "The password retrieval answer provided is invalid. Please check the value and try again."; 200 | 201 | case MembershipCreateStatus.InvalidQuestion: 202 | return "The password retrieval question provided is invalid. Please check the value and try again."; 203 | 204 | case MembershipCreateStatus.InvalidUserName: 205 | return "The user name provided is invalid. Please check the value and try again."; 206 | 207 | case MembershipCreateStatus.ProviderError: 208 | return "The authentication provider returned an error. Please verify your entry and try again. If the problem persists, please contact your system administrator."; 209 | 210 | case MembershipCreateStatus.UserRejected: 211 | return "The user creation request has been canceled. Please verify your entry and try again. If the problem persists, please contact your system administrator."; 212 | 213 | default: 214 | return "An unknown error occurred. Please verify your entry and try again. If the problem persists, please contact your system administrator."; 215 | } 216 | } 217 | } 218 | 219 | [AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = true)] 220 | public sealed class PropertiesMustMatchAttribute : ValidationAttribute 221 | { 222 | private const string _defaultErrorMessage = "'{0}' and '{1}' do not match."; 223 | private readonly object _typeId = new object(); 224 | 225 | public PropertiesMustMatchAttribute(string originalProperty, string confirmProperty) 226 | : base(_defaultErrorMessage) 227 | { 228 | OriginalProperty = originalProperty; 229 | ConfirmProperty = confirmProperty; 230 | } 231 | 232 | public string ConfirmProperty { get; private set; } 233 | public string OriginalProperty { get; private set; } 234 | 235 | public override object TypeId 236 | { 237 | get 238 | { 239 | return _typeId; 240 | } 241 | } 242 | 243 | public override string FormatErrorMessage(string name) 244 | { 245 | return String.Format(CultureInfo.CurrentCulture, ErrorMessageString, 246 | OriginalProperty, ConfirmProperty); 247 | } 248 | 249 | public override bool IsValid(object value) 250 | { 251 | PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(value); 252 | object originalValue = properties.Find(OriginalProperty, true /* ignoreCase */).GetValue(value); 253 | object confirmValue = properties.Find(ConfirmProperty, true /* ignoreCase */).GetValue(value); 254 | return Object.Equals(originalValue, confirmValue); 255 | } 256 | } 257 | 258 | [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = false, Inherited = true)] 259 | public sealed class ValidatePasswordLengthAttribute : ValidationAttribute 260 | { 261 | private const string _defaultErrorMessage = "'{0}' must be at least {1} characters long."; 262 | private readonly int _minCharacters = Membership.Provider.MinRequiredPasswordLength; 263 | 264 | public ValidatePasswordLengthAttribute() 265 | : base(_defaultErrorMessage) 266 | { 267 | } 268 | 269 | public override string FormatErrorMessage(string name) 270 | { 271 | return String.Format(CultureInfo.CurrentCulture, ErrorMessageString, 272 | name, _minCharacters); 273 | } 274 | 275 | public override bool IsValid(object value) 276 | { 277 | string valueAsString = value as string; 278 | return (valueAsString != null && valueAsString.Length >= _minCharacters); 279 | } 280 | } 281 | #endregion 282 | 283 | } 284 | -------------------------------------------------------------------------------- /TestWebApp/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("TestWebApp")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("Microsoft")] 12 | [assembly: AssemblyProduct("TestWebApp")] 13 | [assembly: AssemblyCopyright("Copyright © Microsoft 2010")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("a5307a5e-ed85-4797-a5fb-20eaf6e31456")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Revision and Build Numbers 33 | // by using the '*' as shown below: 34 | [assembly: AssemblyVersion("1.0.0.0")] 35 | [assembly: AssemblyFileVersion("1.0.0.0")] 36 | -------------------------------------------------------------------------------- /TestWebApp/Scripts/MicrosoftMvcAjax.debug.js: -------------------------------------------------------------------------------- 1 | //!---------------------------------------------------------- 2 | //! Copyright (C) Microsoft Corporation. All rights reserved. 3 | //!---------------------------------------------------------- 4 | //! MicrosoftMvcAjax.js 5 | 6 | Type.registerNamespace('Sys.Mvc'); 7 | 8 | //////////////////////////////////////////////////////////////////////////////// 9 | // Sys.Mvc.AjaxOptions 10 | 11 | Sys.Mvc.$create_AjaxOptions = function Sys_Mvc_AjaxOptions() { return {}; } 12 | 13 | 14 | //////////////////////////////////////////////////////////////////////////////// 15 | // Sys.Mvc.InsertionMode 16 | 17 | Sys.Mvc.InsertionMode = function() { 18 | /// 19 | /// 20 | /// 21 | /// 22 | /// 23 | /// 24 | }; 25 | Sys.Mvc.InsertionMode.prototype = { 26 | replace: 0, 27 | insertBefore: 1, 28 | insertAfter: 2 29 | } 30 | Sys.Mvc.InsertionMode.registerEnum('Sys.Mvc.InsertionMode', false); 31 | 32 | 33 | //////////////////////////////////////////////////////////////////////////////// 34 | // Sys.Mvc.AjaxContext 35 | 36 | Sys.Mvc.AjaxContext = function Sys_Mvc_AjaxContext(request, updateTarget, loadingElement, insertionMode) { 37 | /// 38 | /// 39 | /// 40 | /// 41 | /// 42 | /// 43 | /// 44 | /// 45 | /// 46 | /// 47 | /// 48 | /// 49 | /// 50 | /// 51 | /// 52 | /// 53 | /// 54 | /// 55 | this._request = request; 56 | this._updateTarget = updateTarget; 57 | this._loadingElement = loadingElement; 58 | this._insertionMode = insertionMode; 59 | } 60 | Sys.Mvc.AjaxContext.prototype = { 61 | _insertionMode: 0, 62 | _loadingElement: null, 63 | _response: null, 64 | _request: null, 65 | _updateTarget: null, 66 | 67 | get_data: function Sys_Mvc_AjaxContext$get_data() { 68 | /// 69 | if (this._response) { 70 | return this._response.get_responseData(); 71 | } 72 | else { 73 | return null; 74 | } 75 | }, 76 | 77 | get_insertionMode: function Sys_Mvc_AjaxContext$get_insertionMode() { 78 | /// 79 | return this._insertionMode; 80 | }, 81 | 82 | get_loadingElement: function Sys_Mvc_AjaxContext$get_loadingElement() { 83 | /// 84 | return this._loadingElement; 85 | }, 86 | 87 | get_object: function Sys_Mvc_AjaxContext$get_object() { 88 | /// 89 | var executor = this.get_response(); 90 | return (executor) ? executor.get_object() : null; 91 | }, 92 | 93 | get_response: function Sys_Mvc_AjaxContext$get_response() { 94 | /// 95 | return this._response; 96 | }, 97 | set_response: function Sys_Mvc_AjaxContext$set_response(value) { 98 | /// 99 | this._response = value; 100 | return value; 101 | }, 102 | 103 | get_request: function Sys_Mvc_AjaxContext$get_request() { 104 | /// 105 | return this._request; 106 | }, 107 | 108 | get_updateTarget: function Sys_Mvc_AjaxContext$get_updateTarget() { 109 | /// 110 | return this._updateTarget; 111 | } 112 | } 113 | 114 | 115 | //////////////////////////////////////////////////////////////////////////////// 116 | // Sys.Mvc.AsyncHyperlink 117 | 118 | Sys.Mvc.AsyncHyperlink = function Sys_Mvc_AsyncHyperlink() { 119 | } 120 | Sys.Mvc.AsyncHyperlink.handleClick = function Sys_Mvc_AsyncHyperlink$handleClick(anchor, evt, ajaxOptions) { 121 | /// 122 | /// 123 | /// 124 | /// 125 | /// 126 | /// 127 | evt.preventDefault(); 128 | Sys.Mvc.MvcHelpers._asyncRequest(anchor.href, 'post', '', anchor, ajaxOptions); 129 | } 130 | 131 | 132 | //////////////////////////////////////////////////////////////////////////////// 133 | // Sys.Mvc.MvcHelpers 134 | 135 | Sys.Mvc.MvcHelpers = function Sys_Mvc_MvcHelpers() { 136 | } 137 | Sys.Mvc.MvcHelpers._serializeSubmitButton = function Sys_Mvc_MvcHelpers$_serializeSubmitButton(element, offsetX, offsetY) { 138 | /// 139 | /// 140 | /// 141 | /// 142 | /// 143 | /// 144 | /// 145 | if (element.disabled) { 146 | return null; 147 | } 148 | var name = element.name; 149 | if (name) { 150 | var tagName = element.tagName.toUpperCase(); 151 | var encodedName = encodeURIComponent(name); 152 | var inputElement = element; 153 | if (tagName === 'INPUT') { 154 | var type = inputElement.type; 155 | if (type === 'submit') { 156 | return encodedName + '=' + encodeURIComponent(inputElement.value); 157 | } 158 | else if (type === 'image') { 159 | return encodedName + '.x=' + offsetX + '&' + encodedName + '.y=' + offsetY; 160 | } 161 | } 162 | else if ((tagName === 'BUTTON') && (name.length) && (inputElement.type === 'submit')) { 163 | return encodedName + '=' + encodeURIComponent(inputElement.value); 164 | } 165 | } 166 | return null; 167 | } 168 | Sys.Mvc.MvcHelpers._serializeForm = function Sys_Mvc_MvcHelpers$_serializeForm(form) { 169 | /// 170 | /// 171 | /// 172 | var formElements = form.elements; 173 | var formBody = new Sys.StringBuilder(); 174 | var count = formElements.length; 175 | for (var i = 0; i < count; i++) { 176 | var element = formElements[i]; 177 | var name = element.name; 178 | if (!name || !name.length) { 179 | continue; 180 | } 181 | var tagName = element.tagName.toUpperCase(); 182 | if (tagName === 'INPUT') { 183 | var inputElement = element; 184 | var type = inputElement.type; 185 | if ((type === 'text') || (type === 'password') || (type === 'hidden') || (((type === 'checkbox') || (type === 'radio')) && element.checked)) { 186 | formBody.append(encodeURIComponent(name)); 187 | formBody.append('='); 188 | formBody.append(encodeURIComponent(inputElement.value)); 189 | formBody.append('&'); 190 | } 191 | } 192 | else if (tagName === 'SELECT') { 193 | var selectElement = element; 194 | var optionCount = selectElement.options.length; 195 | for (var j = 0; j < optionCount; j++) { 196 | var optionElement = selectElement.options[j]; 197 | if (optionElement.selected) { 198 | formBody.append(encodeURIComponent(name)); 199 | formBody.append('='); 200 | formBody.append(encodeURIComponent(optionElement.value)); 201 | formBody.append('&'); 202 | } 203 | } 204 | } 205 | else if (tagName === 'TEXTAREA') { 206 | formBody.append(encodeURIComponent(name)); 207 | formBody.append('='); 208 | formBody.append(encodeURIComponent((element.value))); 209 | formBody.append('&'); 210 | } 211 | } 212 | var additionalInput = form._additionalInput; 213 | if (additionalInput) { 214 | formBody.append(additionalInput); 215 | formBody.append('&'); 216 | } 217 | return formBody.toString(); 218 | } 219 | Sys.Mvc.MvcHelpers._asyncRequest = function Sys_Mvc_MvcHelpers$_asyncRequest(url, verb, body, triggerElement, ajaxOptions) { 220 | /// 221 | /// 222 | /// 223 | /// 224 | /// 225 | /// 226 | /// 227 | /// 228 | /// 229 | /// 230 | if (ajaxOptions.confirm) { 231 | if (!confirm(ajaxOptions.confirm)) { 232 | return; 233 | } 234 | } 235 | if (ajaxOptions.url) { 236 | url = ajaxOptions.url; 237 | } 238 | if (ajaxOptions.httpMethod) { 239 | verb = ajaxOptions.httpMethod; 240 | } 241 | if (body.length > 0 && !body.endsWith('&')) { 242 | body += '&'; 243 | } 244 | body += 'X-Requested-With=XMLHttpRequest'; 245 | var upperCaseVerb = verb.toUpperCase(); 246 | var isGetOrPost = (upperCaseVerb === 'GET' || upperCaseVerb === 'POST'); 247 | if (!isGetOrPost) { 248 | body += '&'; 249 | body += 'X-HTTP-Method-Override=' + upperCaseVerb; 250 | } 251 | var requestBody = ''; 252 | if (upperCaseVerb === 'GET' || upperCaseVerb === 'DELETE') { 253 | if (url.indexOf('?') > -1) { 254 | if (!url.endsWith('&')) { 255 | url += '&'; 256 | } 257 | url += body; 258 | } 259 | else { 260 | url += '?'; 261 | url += body; 262 | } 263 | } 264 | else { 265 | requestBody = body; 266 | } 267 | var request = new Sys.Net.WebRequest(); 268 | request.set_url(url); 269 | if (isGetOrPost) { 270 | request.set_httpVerb(verb); 271 | } 272 | else { 273 | request.set_httpVerb('POST'); 274 | request.get_headers()['X-HTTP-Method-Override'] = upperCaseVerb; 275 | } 276 | request.set_body(requestBody); 277 | if (verb.toUpperCase() === 'PUT') { 278 | request.get_headers()['Content-Type'] = 'application/x-www-form-urlencoded;'; 279 | } 280 | request.get_headers()['X-Requested-With'] = 'XMLHttpRequest'; 281 | var updateElement = null; 282 | if (ajaxOptions.updateTargetId) { 283 | updateElement = $get(ajaxOptions.updateTargetId); 284 | } 285 | var loadingElement = null; 286 | if (ajaxOptions.loadingElementId) { 287 | loadingElement = $get(ajaxOptions.loadingElementId); 288 | } 289 | var ajaxContext = new Sys.Mvc.AjaxContext(request, updateElement, loadingElement, ajaxOptions.insertionMode); 290 | var continueRequest = true; 291 | if (ajaxOptions.onBegin) { 292 | continueRequest = ajaxOptions.onBegin(ajaxContext) !== false; 293 | } 294 | if (loadingElement) { 295 | Sys.UI.DomElement.setVisible(ajaxContext.get_loadingElement(), true); 296 | } 297 | if (continueRequest) { 298 | request.add_completed(Function.createDelegate(null, function(executor) { 299 | Sys.Mvc.MvcHelpers._onComplete(request, ajaxOptions, ajaxContext); 300 | })); 301 | request.invoke(); 302 | } 303 | } 304 | Sys.Mvc.MvcHelpers._onComplete = function Sys_Mvc_MvcHelpers$_onComplete(request, ajaxOptions, ajaxContext) { 305 | /// 306 | /// 307 | /// 308 | /// 309 | /// 310 | /// 311 | ajaxContext.set_response(request.get_executor()); 312 | if (ajaxOptions.onComplete && ajaxOptions.onComplete(ajaxContext) === false) { 313 | return; 314 | } 315 | var statusCode = ajaxContext.get_response().get_statusCode(); 316 | if ((statusCode >= 200 && statusCode < 300) || statusCode === 304 || statusCode === 1223) { 317 | if (statusCode !== 204 && statusCode !== 304 && statusCode !== 1223) { 318 | var contentType = ajaxContext.get_response().getResponseHeader('Content-Type'); 319 | if ((contentType) && (contentType.indexOf('application/x-javascript') !== -1)) { 320 | eval(ajaxContext.get_data()); 321 | } 322 | else { 323 | Sys.Mvc.MvcHelpers.updateDomElement(ajaxContext.get_updateTarget(), ajaxContext.get_insertionMode(), ajaxContext.get_data()); 324 | } 325 | } 326 | if (ajaxOptions.onSuccess) { 327 | ajaxOptions.onSuccess(ajaxContext); 328 | } 329 | } 330 | else { 331 | if (ajaxOptions.onFailure) { 332 | ajaxOptions.onFailure(ajaxContext); 333 | } 334 | } 335 | if (ajaxContext.get_loadingElement()) { 336 | Sys.UI.DomElement.setVisible(ajaxContext.get_loadingElement(), false); 337 | } 338 | } 339 | Sys.Mvc.MvcHelpers.updateDomElement = function Sys_Mvc_MvcHelpers$updateDomElement(target, insertionMode, content) { 340 | /// 341 | /// 342 | /// 343 | /// 344 | /// 345 | /// 346 | if (target) { 347 | switch (insertionMode) { 348 | case Sys.Mvc.InsertionMode.replace: 349 | target.innerHTML = content; 350 | break; 351 | case Sys.Mvc.InsertionMode.insertBefore: 352 | if (content && content.length > 0) { 353 | target.innerHTML = content + target.innerHTML.trimStart(); 354 | } 355 | break; 356 | case Sys.Mvc.InsertionMode.insertAfter: 357 | if (content && content.length > 0) { 358 | target.innerHTML = target.innerHTML.trimEnd() + content; 359 | } 360 | break; 361 | } 362 | } 363 | } 364 | 365 | 366 | //////////////////////////////////////////////////////////////////////////////// 367 | // Sys.Mvc.AsyncForm 368 | 369 | Sys.Mvc.AsyncForm = function Sys_Mvc_AsyncForm() { 370 | } 371 | Sys.Mvc.AsyncForm.handleClick = function Sys_Mvc_AsyncForm$handleClick(form, evt) { 372 | /// 373 | /// 374 | /// 375 | /// 376 | var additionalInput = Sys.Mvc.MvcHelpers._serializeSubmitButton(evt.target, evt.offsetX, evt.offsetY); 377 | form._additionalInput = additionalInput; 378 | } 379 | Sys.Mvc.AsyncForm.handleSubmit = function Sys_Mvc_AsyncForm$handleSubmit(form, evt, ajaxOptions) { 380 | /// 381 | /// 382 | /// 383 | /// 384 | /// 385 | /// 386 | evt.preventDefault(); 387 | var validationCallbacks = form.validationCallbacks; 388 | if (validationCallbacks) { 389 | for (var i = 0; i < validationCallbacks.length; i++) { 390 | var callback = validationCallbacks[i]; 391 | if (!callback()) { 392 | return; 393 | } 394 | } 395 | } 396 | var body = Sys.Mvc.MvcHelpers._serializeForm(form); 397 | Sys.Mvc.MvcHelpers._asyncRequest(form.action, form.method || 'post', body, form, ajaxOptions); 398 | } 399 | 400 | 401 | Sys.Mvc.AjaxContext.registerClass('Sys.Mvc.AjaxContext'); 402 | Sys.Mvc.AsyncHyperlink.registerClass('Sys.Mvc.AsyncHyperlink'); 403 | Sys.Mvc.MvcHelpers.registerClass('Sys.Mvc.MvcHelpers'); 404 | Sys.Mvc.AsyncForm.registerClass('Sys.Mvc.AsyncForm'); 405 | 406 | // ---- Do not remove this footer ---- 407 | // Generated using Script# v0.5.0.0 (http://projects.nikhilk.net) 408 | // ----------------------------------- 409 | -------------------------------------------------------------------------------- /TestWebApp/Scripts/MicrosoftMvcAjax.js: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------- 2 | // Copyright (C) Microsoft Corporation. All rights reserved. 3 | //---------------------------------------------------------- 4 | // MicrosoftMvcAjax.js 5 | 6 | Type.registerNamespace('Sys.Mvc');Sys.Mvc.$create_AjaxOptions=function(){return {};} 7 | Sys.Mvc.InsertionMode=function(){};Sys.Mvc.InsertionMode.prototype = {replace:0,insertBefore:1,insertAfter:2} 8 | Sys.Mvc.InsertionMode.registerEnum('Sys.Mvc.InsertionMode',false);Sys.Mvc.AjaxContext=function(request,updateTarget,loadingElement,insertionMode){this.$3=request;this.$4=updateTarget;this.$1=loadingElement;this.$0=insertionMode;} 9 | Sys.Mvc.AjaxContext.prototype={$0:0,$1:null,$2:null,$3:null,$4:null,get_data:function(){if(this.$2){return this.$2.get_responseData();}else{return null;}},get_insertionMode:function(){return this.$0;},get_loadingElement:function(){return this.$1;},get_object:function(){var $0=this.get_response();return ($0)?$0.get_object():null;},get_response:function(){return this.$2;},set_response:function(value){this.$2=value;return value;},get_request:function(){return this.$3;},get_updateTarget:function(){return this.$4;}} 10 | Sys.Mvc.AsyncHyperlink=function(){} 11 | Sys.Mvc.AsyncHyperlink.handleClick=function(anchor,evt,ajaxOptions){evt.preventDefault();Sys.Mvc.MvcHelpers.$2(anchor.href,'post','',anchor,ajaxOptions);} 12 | Sys.Mvc.MvcHelpers=function(){} 13 | Sys.Mvc.MvcHelpers.$0=function($p0,$p1,$p2){if($p0.disabled){return null;}var $0=$p0.name;if($0){var $1=$p0.tagName.toUpperCase();var $2=encodeURIComponent($0);var $3=$p0;if($1==='INPUT'){var $4=$3.type;if($4==='submit'){return $2+'='+encodeURIComponent($3.value);}else if($4==='image'){return $2+'.x='+$p1+'&'+$2+'.y='+$p2;}}else if(($1==='BUTTON')&&($0.length)&&($3.type==='submit')){return $2+'='+encodeURIComponent($3.value);}}return null;} 14 | Sys.Mvc.MvcHelpers.$1=function($p0){var $0=$p0.elements;var $1=new Sys.StringBuilder();var $2=$0.length;for(var $4=0;$4<$2;$4++){var $5=$0[$4];var $6=$5.name;if(!$6||!$6.length){continue;}var $7=$5.tagName.toUpperCase();if($7==='INPUT'){var $8=$5;var $9=$8.type;if(($9==='text')||($9==='password')||($9==='hidden')||((($9==='checkbox')||($9==='radio'))&&$5.checked)){$1.append(encodeURIComponent($6));$1.append('=');$1.append(encodeURIComponent($8.value));$1.append('&');}}else if($7==='SELECT'){var $A=$5;var $B=$A.options.length;for(var $C=0;$C<$B;$C++){var $D=$A.options[$C];if($D.selected){$1.append(encodeURIComponent($6));$1.append('=');$1.append(encodeURIComponent($D.value));$1.append('&');}}}else if($7==='TEXTAREA'){$1.append(encodeURIComponent($6));$1.append('=');$1.append(encodeURIComponent(($5.value)));$1.append('&');}}var $3=$p0._additionalInput;if($3){$1.append($3);$1.append('&');}return $1.toString();} 15 | Sys.Mvc.MvcHelpers.$2=function($p0,$p1,$p2,$p3,$p4){if($p4.confirm){if(!confirm($p4.confirm)){return;}}if($p4.url){$p0=$p4.url;}if($p4.httpMethod){$p1=$p4.httpMethod;}if($p2.length>0&&!$p2.endsWith('&')){$p2+='&';}$p2+='X-Requested-With=XMLHttpRequest';var $0=$p1.toUpperCase();var $1=($0==='GET'||$0==='POST');if(!$1){$p2+='&';$p2+='X-HTTP-Method-Override='+$0;}var $2='';if($0==='GET'||$0==='DELETE'){if($p0.indexOf('?')>-1){if(!$p0.endsWith('&')){$p0+='&';}$p0+=$p2;}else{$p0+='?';$p0+=$p2;}}else{$2=$p2;}var $3=new Sys.Net.WebRequest();$3.set_url($p0);if($1){$3.set_httpVerb($p1);}else{$3.set_httpVerb('POST');$3.get_headers()['X-HTTP-Method-Override']=$0;}$3.set_body($2);if($p1.toUpperCase()==='PUT'){$3.get_headers()['Content-Type']='application/x-www-form-urlencoded;';}$3.get_headers()['X-Requested-With']='XMLHttpRequest';var $4=null;if($p4.updateTargetId){$4=$get($p4.updateTargetId);}var $5=null;if($p4.loadingElementId){$5=$get($p4.loadingElementId);}var $6=new Sys.Mvc.AjaxContext($3,$4,$5,$p4.insertionMode);var $7=true;if($p4.onBegin){$7=$p4.onBegin($6)!==false;}if($5){Sys.UI.DomElement.setVisible($6.get_loadingElement(),true);}if($7){$3.add_completed(Function.createDelegate(null,function($p1_0){ 16 | Sys.Mvc.MvcHelpers.$3($3,$p4,$6);}));$3.invoke();}} 17 | Sys.Mvc.MvcHelpers.$3=function($p0,$p1,$p2){$p2.set_response($p0.get_executor());if($p1.onComplete&&$p1.onComplete($p2)===false){return;}var $0=$p2.get_response().get_statusCode();if(($0>=200&&$0<300)||$0===304||$0===1223){if($0!==204&&$0!==304&&$0!==1223){var $1=$p2.get_response().getResponseHeader('Content-Type');if(($1)&&($1.indexOf('application/x-javascript')!==-1)){eval($p2.get_data());}else{Sys.Mvc.MvcHelpers.updateDomElement($p2.get_updateTarget(),$p2.get_insertionMode(),$p2.get_data());}}if($p1.onSuccess){$p1.onSuccess($p2);}}else{if($p1.onFailure){$p1.onFailure($p2);}}if($p2.get_loadingElement()){Sys.UI.DomElement.setVisible($p2.get_loadingElement(),false);}} 18 | Sys.Mvc.MvcHelpers.updateDomElement=function(target,insertionMode,content){if(target){switch(insertionMode){case 0:target.innerHTML=content;break;case 1:if(content&&content.length>0){target.innerHTML=content+target.innerHTML.trimStart();}break;case 2:if(content&&content.length>0){target.innerHTML=target.innerHTML.trimEnd()+content;}break;}}} 19 | Sys.Mvc.AsyncForm=function(){} 20 | Sys.Mvc.AsyncForm.handleClick=function(form,evt){var $0=Sys.Mvc.MvcHelpers.$0(evt.target,evt.offsetX,evt.offsetY);form._additionalInput = $0;} 21 | Sys.Mvc.AsyncForm.handleSubmit=function(form,evt,ajaxOptions){evt.preventDefault();var $0=form.validationCallbacks;if($0){for(var $2=0;$2<$0.length;$2++){var $3=$0[$2];if(!$3()){return;}}}var $1=Sys.Mvc.MvcHelpers.$1(form);Sys.Mvc.MvcHelpers.$2(form.action,form.method||'post',$1,form,ajaxOptions);} 22 | Sys.Mvc.AjaxContext.registerClass('Sys.Mvc.AjaxContext');Sys.Mvc.AsyncHyperlink.registerClass('Sys.Mvc.AsyncHyperlink');Sys.Mvc.MvcHelpers.registerClass('Sys.Mvc.MvcHelpers');Sys.Mvc.AsyncForm.registerClass('Sys.Mvc.AsyncForm'); 23 | // ---- Do not remove this footer ---- 24 | // Generated using Script# v0.5.0.0 (http://projects.nikhilk.net) 25 | // ----------------------------------- 26 | -------------------------------------------------------------------------------- /TestWebApp/Scripts/MicrosoftMvcValidation.js: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------- 2 | // Copyright (C) Microsoft Corporation. All rights reserved. 3 | //---------------------------------------------------------- 4 | // MicrosoftMvcValidation.js 5 | 6 | Type.registerNamespace('Sys.Mvc');Sys.Mvc.$create_Validation=function(){return {};} 7 | Sys.Mvc.$create_JsonValidationField=function(){return {};} 8 | Sys.Mvc.$create_JsonValidationOptions=function(){return {};} 9 | Sys.Mvc.$create_JsonValidationRule=function(){return {};} 10 | Sys.Mvc.$create_ValidationContext=function(){return {};} 11 | Sys.Mvc.NumberValidator=function(){} 12 | Sys.Mvc.NumberValidator.create=function(rule){return Function.createDelegate(new Sys.Mvc.NumberValidator(),new Sys.Mvc.NumberValidator().validate);} 13 | Sys.Mvc.NumberValidator.prototype={validate:function(value,context){if(Sys.Mvc._ValidationUtil.$1(value)){return true;}var $0=Number.parseLocale(value);return (!isNaN($0));}} 14 | Sys.Mvc.FormContext=function(formElement,validationSummaryElement){this.$5=[];this.fields=new Array(0);this.$9=formElement;this.$7=validationSummaryElement;formElement['__MVC_FormValidation'] = this;if(validationSummaryElement){var $0=validationSummaryElement.getElementsByTagName('ul');if($0.length>0){this.$8=$0[0];}}this.$3=Function.createDelegate(this,this.$D);this.$4=Function.createDelegate(this,this.$E);} 15 | Sys.Mvc.FormContext._Application_Load=function(){var $0=window.mvcClientValidationMetadata;if($0){while($0.length>0){var $1=$0.pop();Sys.Mvc.FormContext.$12($1);}}} 16 | Sys.Mvc.FormContext.$F=function($p0,$p1){var $0=[];var $1=document.getElementsByName($p1);for(var $2=0;$2<$1.length;$2++){var $3=$1[$2];if(Sys.Mvc.FormContext.$10($p0,$3)){Array.add($0,$3);}}return $0;} 17 | Sys.Mvc.FormContext.getValidationForForm=function(formElement){return formElement['__MVC_FormValidation'];} 18 | Sys.Mvc.FormContext.$10=function($p0,$p1){while($p1){if($p0===$p1){return true;}$p1=$p1.parentNode;}return false;} 19 | Sys.Mvc.FormContext.$12=function($p0){var $0=$get($p0.FormId);var $1=(!Sys.Mvc._ValidationUtil.$1($p0.ValidationSummaryId))?$get($p0.ValidationSummaryId):null;var $2=new Sys.Mvc.FormContext($0,$1);$2.enableDynamicValidation();$2.replaceValidationSummary=$p0.ReplaceValidationSummary;for(var $4=0;$4<$p0.Fields.length;$4++){var $5=$p0.Fields[$4];var $6=Sys.Mvc.FormContext.$F($0,$5.FieldName);var $7=(!Sys.Mvc._ValidationUtil.$1($5.ValidationMessageId))?$get($5.ValidationMessageId):null;var $8=new Sys.Mvc.FieldContext($2);Array.addRange($8.elements,$6);$8.validationMessageElement=$7;$8.replaceValidationMessageContents=$5.ReplaceValidationMessageContents;for(var $9=0;$9<$5.ValidationRules.length;$9++){var $A=$5.ValidationRules[$9];var $B=Sys.Mvc.ValidatorRegistry.getValidator($A);if($B){var $C=Sys.Mvc.$create_Validation();$C.fieldErrorMessage=$A.ErrorMessage;$C.validator=$B;Array.add($8.validations,$C);}}$8.enableDynamicValidation();Array.add($2.fields,$8);}var $3=$0.validationCallbacks;if(!$3){$3=[];$0.validationCallbacks = $3;}$3.push(Function.createDelegate(null,function(){ 20 | return Sys.Mvc._ValidationUtil.$0($2.validate('submit'));}));return $2;} 21 | Sys.Mvc.FormContext.prototype={$3:null,$4:null,$6:null,$7:null,$8:null,$9:null,replaceValidationSummary:false,addError:function(message){this.addErrors([message]);},addErrors:function(messages){if(!Sys.Mvc._ValidationUtil.$0(messages)){Array.addRange(this.$5,messages);this.$11();}},clearErrors:function(){Array.clear(this.$5);this.$11();},$A:function(){if(this.$7){if(this.$8){Sys.Mvc._ValidationUtil.$3(this.$8);for(var $0=0;$0=8){Sys.UI.DomEvent.addHandler($2,'propertychange',this.$9);}}else{Sys.UI.DomEvent.addHandler($2,'input',this.$8);}Sys.UI.DomEvent.addHandler($2,'change',this.$7);Sys.UI.DomEvent.addHandler($2,'blur',this.$6);}},$11:function($p0,$p1){var $0=$p1||this.defaultErrorMessage;if(Boolean.isInstanceOfType($p0)){return ($p0)?null:$0;}if(String.isInstanceOfType($p0)){return (($p0).length)?$p0:$0;}return null;},$12:function(){var $0=this.elements;return ($0.length>0)?$0[0].value:null;},$13:function(){var $0=this.elements;for(var $1=0;$1<$0.length;$1++){var $2=$0[$1];$2['__MVC_HasValidationFired'] = true;}},$14:function(){if(!this.$A.length){this.$C();}else{this.$B();}},validate:function(eventName){var $0=this.validations;var $1=[];var $2=this.$12();for(var $3=0;$3<$0.length;$3++){var $4=$0[$3];var $5=Sys.Mvc.$create_ValidationContext();$5.eventName=eventName;$5.fieldContext=this;$5.validation=$4;var $6=$4.validator($2,$5);var $7=this.$11($6,$4.fieldErrorMessage);if(!Sys.Mvc._ValidationUtil.$1($7)){Array.add($1,$7);}}this.$13();this.clearErrors();this.addErrors($1);return $1;}} 24 | Sys.Mvc.RangeValidator=function(minimum,maximum){this.$0=minimum;this.$1=maximum;} 25 | Sys.Mvc.RangeValidator.create=function(rule){var $0=rule.ValidationParameters['minimum'];var $1=rule.ValidationParameters['maximum'];return Function.createDelegate(new Sys.Mvc.RangeValidator($0,$1),new Sys.Mvc.RangeValidator($0,$1).validate);} 26 | Sys.Mvc.RangeValidator.prototype={$0:null,$1:null,validate:function(value,context){if(Sys.Mvc._ValidationUtil.$1(value)){return true;}var $0=Number.parseLocale(value);return (!isNaN($0)&&this.$0<=$0&&$0<=this.$1);}} 27 | Sys.Mvc.RegularExpressionValidator=function(pattern){this.$0=pattern;} 28 | Sys.Mvc.RegularExpressionValidator.create=function(rule){var $0=rule.ValidationParameters['pattern'];return Function.createDelegate(new Sys.Mvc.RegularExpressionValidator($0),new Sys.Mvc.RegularExpressionValidator($0).validate);} 29 | Sys.Mvc.RegularExpressionValidator.prototype={$0:null,validate:function(value,context){if(Sys.Mvc._ValidationUtil.$1(value)){return true;}var $0=new RegExp(this.$0);var $1=$0.exec(value);return (!Sys.Mvc._ValidationUtil.$0($1)&&$1[0].length===value.length);}} 30 | Sys.Mvc.RequiredValidator=function(){} 31 | Sys.Mvc.RequiredValidator.create=function(rule){return Function.createDelegate(new Sys.Mvc.RequiredValidator(),new Sys.Mvc.RequiredValidator().validate);} 32 | Sys.Mvc.RequiredValidator.$0=function($p0){if($p0.tagName.toUpperCase()==='INPUT'){var $0=($p0.type).toUpperCase();if($0==='RADIO'){return true;}}return false;} 33 | Sys.Mvc.RequiredValidator.$1=function($p0){if($p0.tagName.toUpperCase()==='SELECT'){return true;}return false;} 34 | Sys.Mvc.RequiredValidator.$2=function($p0){if($p0.tagName.toUpperCase()==='INPUT'){var $0=($p0.type).toUpperCase();switch($0){case 'TEXT':case 'PASSWORD':case 'FILE':return true;}}if($p0.tagName.toUpperCase()==='TEXTAREA'){return true;}return false;} 35 | Sys.Mvc.RequiredValidator.$3=function($p0){for(var $0=0;$0<$p0.length;$0++){var $1=$p0[$0];if($1.checked){return true;}}return false;} 36 | Sys.Mvc.RequiredValidator.$4=function($p0){for(var $0=0;$0<$p0.length;$0++){var $1=$p0[$0];if($1.selected){if(!Sys.Mvc._ValidationUtil.$1($1.value)){return true;}}}return false;} 37 | Sys.Mvc.RequiredValidator.$5=function($p0){return (!Sys.Mvc._ValidationUtil.$1($p0.value));} 38 | Sys.Mvc.RequiredValidator.prototype={validate:function(value,context){var $0=context.fieldContext.elements;if(!$0.length){return true;}var $1=$0[0];if(Sys.Mvc.RequiredValidator.$2($1)){return Sys.Mvc.RequiredValidator.$5($1);}if(Sys.Mvc.RequiredValidator.$0($1)){return Sys.Mvc.RequiredValidator.$3($0);}if(Sys.Mvc.RequiredValidator.$1($1)){return Sys.Mvc.RequiredValidator.$4(($1).options);}return true;}} 39 | Sys.Mvc.StringLengthValidator=function(minLength,maxLength){this.$1=minLength;this.$0=maxLength;} 40 | Sys.Mvc.StringLengthValidator.create=function(rule){var $0=rule.ValidationParameters['minimumLength'];var $1=rule.ValidationParameters['maximumLength'];return Function.createDelegate(new Sys.Mvc.StringLengthValidator($0,$1),new Sys.Mvc.StringLengthValidator($0,$1).validate);} 41 | Sys.Mvc.StringLengthValidator.prototype={$0:0,$1:0,validate:function(value,context){if(Sys.Mvc._ValidationUtil.$1(value)){return true;}return (this.$1<=value.length&&value.length<=this.$0);}} 42 | Sys.Mvc._ValidationUtil=function(){} 43 | Sys.Mvc._ValidationUtil.$0=function($p0){return (!$p0||!$p0.length);} 44 | Sys.Mvc._ValidationUtil.$1=function($p0){return (!$p0||!$p0.length);} 45 | Sys.Mvc._ValidationUtil.$2=function($p0,$p1){return ($p1 in $p0);} 46 | Sys.Mvc._ValidationUtil.$3=function($p0){while($p0.firstChild){$p0.removeChild($p0.firstChild);}} 47 | Sys.Mvc._ValidationUtil.$4=function($p0,$p1){var $0=document.createTextNode($p1);Sys.Mvc._ValidationUtil.$3($p0);$p0.appendChild($0);} 48 | Sys.Mvc.ValidatorRegistry=function(){} 49 | Sys.Mvc.ValidatorRegistry.getValidator=function(rule){var $0=Sys.Mvc.ValidatorRegistry.validators[rule.ValidationType];return ($0)?$0(rule):null;} 50 | Sys.Mvc.ValidatorRegistry.$0=function(){return {required:Function.createDelegate(null,Sys.Mvc.RequiredValidator.create),stringLength:Function.createDelegate(null,Sys.Mvc.StringLengthValidator.create),regularExpression:Function.createDelegate(null,Sys.Mvc.RegularExpressionValidator.create),range:Function.createDelegate(null,Sys.Mvc.RangeValidator.create),number:Function.createDelegate(null,Sys.Mvc.NumberValidator.create)};} 51 | Sys.Mvc.NumberValidator.registerClass('Sys.Mvc.NumberValidator');Sys.Mvc.FormContext.registerClass('Sys.Mvc.FormContext');Sys.Mvc.FieldContext.registerClass('Sys.Mvc.FieldContext');Sys.Mvc.RangeValidator.registerClass('Sys.Mvc.RangeValidator');Sys.Mvc.RegularExpressionValidator.registerClass('Sys.Mvc.RegularExpressionValidator');Sys.Mvc.RequiredValidator.registerClass('Sys.Mvc.RequiredValidator');Sys.Mvc.StringLengthValidator.registerClass('Sys.Mvc.StringLengthValidator');Sys.Mvc._ValidationUtil.registerClass('Sys.Mvc._ValidationUtil');Sys.Mvc.ValidatorRegistry.registerClass('Sys.Mvc.ValidatorRegistry');Sys.Mvc.ValidatorRegistry.validators=Sys.Mvc.ValidatorRegistry.$0(); 52 | // ---- Do not remove this footer ---- 53 | // Generated using Script# v0.5.0.0 (http://projects.nikhilk.net) 54 | // ----------------------------------- 55 | Sys.Application.add_load(function(){Sys.Application.remove_load(arguments.callee);Sys.Mvc.FormContext._Application_Load();}); -------------------------------------------------------------------------------- /TestWebApp/Scripts/jquery.validate.min.js: -------------------------------------------------------------------------------- 1 | /* 2 | * jQuery validation plug-in 1.6 3 | * 4 | * http://bassistance.de/jquery-plugins/jquery-plugin-validation/ 5 | * http://docs.jquery.com/Plugins/Validation 6 | * 7 | * Copyright (c) 2006 - 2008 Jörn Zaefferer 8 | * 9 | * $Id: jquery.validate.js 6403 2009-06-17 14:27:16Z joern.zaefferer $ 10 | * 11 | * Permission is hereby granted, free of charge, to any person obtaining 12 | * a copy of this software and associated documentation files (the 13 | * "Software"), to deal in the Software without restriction, including 14 | * without limitation the rights to use, copy, modify, merge, publish, 15 | * distribute, sublicense, and/or sell copies of the Software, and to 16 | * permit persons to whom the Software is furnished to do so, subject to 17 | * the following conditions: 18 | * 19 | * The above copyright notice and this permission notice shall be 20 | * included in all copies or substantial portions of the Software. 21 | * 22 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 23 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 24 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 25 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 26 | * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 27 | * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 28 | * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 29 | */ 30 | (function($){$.extend($.fn,{validate:function(options){if(!this.length){options&&options.debug&&window.console&&console.warn("nothing selected, can't validate, returning nothing");return;}var validator=$.data(this[0],'validator');if(validator){return validator;}validator=new $.validator(options,this[0]);$.data(this[0],'validator',validator);if(validator.settings.onsubmit){this.find("input, button").filter(".cancel").click(function(){validator.cancelSubmit=true;});if(validator.settings.submitHandler){this.find("input, button").filter(":submit").click(function(){validator.submitButton=this;});}this.submit(function(event){if(validator.settings.debug)event.preventDefault();function handle(){if(validator.settings.submitHandler){if(validator.submitButton){var hidden=$("").attr("name",validator.submitButton.name).val(validator.submitButton.value).appendTo(validator.currentForm);}validator.settings.submitHandler.call(validator,validator.currentForm);if(validator.submitButton){hidden.remove();}return false;}return true;}if(validator.cancelSubmit){validator.cancelSubmit=false;return handle();}if(validator.form()){if(validator.pendingRequest){validator.formSubmitted=true;return false;}return handle();}else{validator.focusInvalid();return false;}});}return validator;},valid:function(){if($(this[0]).is('form')){return this.validate().form();}else{var valid=true;var validator=$(this[0].form).validate();this.each(function(){valid&=validator.element(this);});return valid;}},removeAttrs:function(attributes){var result={},$element=this;$.each(attributes.split(/\s/),function(index,value){result[value]=$element.attr(value);$element.removeAttr(value);});return result;},rules:function(command,argument){var element=this[0];if(command){var settings=$.data(element.form,'validator').settings;var staticRules=settings.rules;var existingRules=$.validator.staticRules(element);switch(command){case"add":$.extend(existingRules,$.validator.normalizeRule(argument));staticRules[element.name]=existingRules;if(argument.messages)settings.messages[element.name]=$.extend(settings.messages[element.name],argument.messages);break;case"remove":if(!argument){delete staticRules[element.name];return existingRules;}var filtered={};$.each(argument.split(/\s/),function(index,method){filtered[method]=existingRules[method];delete existingRules[method];});return filtered;}}var data=$.validator.normalizeRules($.extend({},$.validator.metadataRules(element),$.validator.classRules(element),$.validator.attributeRules(element),$.validator.staticRules(element)),element);if(data.required){var param=data.required;delete data.required;data=$.extend({required:param},data);}return data;}});$.extend($.expr[":"],{blank:function(a){return!$.trim(""+a.value);},filled:function(a){return!!$.trim(""+a.value);},unchecked:function(a){return!a.checked;}});$.validator=function(options,form){this.settings=$.extend({},$.validator.defaults,options);this.currentForm=form;this.init();};$.validator.format=function(source,params){if(arguments.length==1)return function(){var args=$.makeArray(arguments);args.unshift(source);return $.validator.format.apply(this,args);};if(arguments.length>2&¶ms.constructor!=Array){params=$.makeArray(arguments).slice(1);}if(params.constructor!=Array){params=[params];}$.each(params,function(i,n){source=source.replace(new RegExp("\\{"+i+"\\}","g"),n);});return source;};$.extend($.validator,{defaults:{messages:{},groups:{},rules:{},errorClass:"error",validClass:"valid",errorElement:"label",focusInvalid:true,errorContainer:$([]),errorLabelContainer:$([]),onsubmit:true,ignore:[],ignoreTitle:false,onfocusin:function(element){this.lastActive=element;if(this.settings.focusCleanup&&!this.blockFocusCleanup){this.settings.unhighlight&&this.settings.unhighlight.call(this,element,this.settings.errorClass,this.settings.validClass);this.errorsFor(element).hide();}},onfocusout:function(element){if(!this.checkable(element)&&(element.name in this.submitted||!this.optional(element))){this.element(element);}},onkeyup:function(element){if(element.name in this.submitted||element==this.lastElement){this.element(element);}},onclick:function(element){if(element.name in this.submitted)this.element(element);else if(element.parentNode.name in this.submitted)this.element(element.parentNode)},highlight:function(element,errorClass,validClass){$(element).addClass(errorClass).removeClass(validClass);},unhighlight:function(element,errorClass,validClass){$(element).removeClass(errorClass).addClass(validClass);}},setDefaults:function(settings){$.extend($.validator.defaults,settings);},messages:{required:"This field is required.",remote:"Please fix this field.",email:"Please enter a valid email address.",url:"Please enter a valid URL.",date:"Please enter a valid date.",dateISO:"Please enter a valid date (ISO).",number:"Please enter a valid number.",digits:"Please enter only digits.",creditcard:"Please enter a valid credit card number.",equalTo:"Please enter the same value again.",accept:"Please enter a value with a valid extension.",maxlength:$.validator.format("Please enter no more than {0} characters."),minlength:$.validator.format("Please enter at least {0} characters."),rangelength:$.validator.format("Please enter a value between {0} and {1} characters long."),range:$.validator.format("Please enter a value between {0} and {1}."),max:$.validator.format("Please enter a value less than or equal to {0}."),min:$.validator.format("Please enter a value greater than or equal to {0}.")},autoCreateRanges:false,prototype:{init:function(){this.labelContainer=$(this.settings.errorLabelContainer);this.errorContext=this.labelContainer.length&&this.labelContainer||$(this.currentForm);this.containers=$(this.settings.errorContainer).add(this.settings.errorLabelContainer);this.submitted={};this.valueCache={};this.pendingRequest=0;this.pending={};this.invalid={};this.reset();var groups=(this.groups={});$.each(this.settings.groups,function(key,value){$.each(value.split(/\s/),function(index,name){groups[name]=key;});});var rules=this.settings.rules;$.each(rules,function(key,value){rules[key]=$.validator.normalizeRule(value);});function delegate(event){var validator=$.data(this[0].form,"validator");validator.settings["on"+event.type]&&validator.settings["on"+event.type].call(validator,this[0]);}$(this.currentForm).delegate("focusin focusout keyup",":text, :password, :file, select, textarea",delegate).delegate("click",":radio, :checkbox, select, option",delegate);if(this.settings.invalidHandler)$(this.currentForm).bind("invalid-form.validate",this.settings.invalidHandler);},form:function(){this.checkForm();$.extend(this.submitted,this.errorMap);this.invalid=$.extend({},this.errorMap);if(!this.valid())$(this.currentForm).triggerHandler("invalid-form",[this]);this.showErrors();return this.valid();},checkForm:function(){this.prepareForm();for(var i=0,elements=(this.currentElements=this.elements());elements[i];i++){this.check(elements[i]);}return this.valid();},element:function(element){element=this.clean(element);this.lastElement=element;this.prepareElement(element);this.currentElements=$(element);var result=this.check(element);if(result){delete this.invalid[element.name];}else{this.invalid[element.name]=true;}if(!this.numberOfInvalids()){this.toHide=this.toHide.add(this.containers);}this.showErrors();return result;},showErrors:function(errors){if(errors){$.extend(this.errorMap,errors);this.errorList=[];for(var name in errors){this.errorList.push({message:errors[name],element:this.findByName(name)[0]});}this.successList=$.grep(this.successList,function(element){return!(element.name in errors);});}this.settings.showErrors?this.settings.showErrors.call(this,this.errorMap,this.errorList):this.defaultShowErrors();},resetForm:function(){if($.fn.resetForm)$(this.currentForm).resetForm();this.submitted={};this.prepareForm();this.hideErrors();this.elements().removeClass(this.settings.errorClass);},numberOfInvalids:function(){return this.objectLength(this.invalid);},objectLength:function(obj){var count=0;for(var i in obj)count++;return count;},hideErrors:function(){this.addWrapper(this.toHide).hide();},valid:function(){return this.size()==0;},size:function(){return this.errorList.length;},focusInvalid:function(){if(this.settings.focusInvalid){try{$(this.findLastActive()||this.errorList.length&&this.errorList[0].element||[]).filter(":visible").focus();}catch(e){}}},findLastActive:function(){var lastActive=this.lastActive;return lastActive&&$.grep(this.errorList,function(n){return n.element.name==lastActive.name;}).length==1&&lastActive;},elements:function(){var validator=this,rulesCache={};return $([]).add(this.currentForm.elements).filter(":input").not(":submit, :reset, :image, [disabled]").not(this.settings.ignore).filter(function(){!this.name&&validator.settings.debug&&window.console&&console.error("%o has no name assigned",this);if(this.name in rulesCache||!validator.objectLength($(this).rules()))return false;rulesCache[this.name]=true;return true;});},clean:function(selector){return $(selector)[0];},errors:function(){return $(this.settings.errorElement+"."+this.settings.errorClass,this.errorContext);},reset:function(){this.successList=[];this.errorList=[];this.errorMap={};this.toShow=$([]);this.toHide=$([]);this.currentElements=$([]);},prepareForm:function(){this.reset();this.toHide=this.errors().add(this.containers);},prepareElement:function(element){this.reset();this.toHide=this.errorsFor(element);},check:function(element){element=this.clean(element);if(this.checkable(element)){element=this.findByName(element.name)[0];}var rules=$(element).rules();var dependencyMismatch=false;for(method in rules){var rule={method:method,parameters:rules[method]};try{var result=$.validator.methods[method].call(this,element.value.replace(/\r/g,""),element,rule.parameters);if(result=="dependency-mismatch"){dependencyMismatch=true;continue;}dependencyMismatch=false;if(result=="pending"){this.toHide=this.toHide.not(this.errorsFor(element));return;}if(!result){this.formatAndAdd(element,rule);return false;}}catch(e){this.settings.debug&&window.console&&console.log("exception occured when checking element "+element.id 31 | +", check the '"+rule.method+"' method",e);throw e;}}if(dependencyMismatch)return;if(this.objectLength(rules))this.successList.push(element);return true;},customMetaMessage:function(element,method){if(!$.metadata)return;var meta=this.settings.meta?$(element).metadata()[this.settings.meta]:$(element).metadata();return meta&&meta.messages&&meta.messages[method];},customMessage:function(name,method){var m=this.settings.messages[name];return m&&(m.constructor==String?m:m[method]);},findDefined:function(){for(var i=0;iWarning: No message defined for "+element.name+"");},formatAndAdd:function(element,rule){var message=this.defaultMessage(element,rule.method),theregex=/\$?\{(\d+)\}/g;if(typeof message=="function"){message=message.call(this,rule.parameters,element);}else if(theregex.test(message)){message=jQuery.format(message.replace(theregex,'{$1}'),rule.parameters);}this.errorList.push({message:message,element:element});this.errorMap[element.name]=message;this.submitted[element.name]=message;},addWrapper:function(toToggle){if(this.settings.wrapper)toToggle=toToggle.add(toToggle.parent(this.settings.wrapper));return toToggle;},defaultShowErrors:function(){for(var i=0;this.errorList[i];i++){var error=this.errorList[i];this.settings.highlight&&this.settings.highlight.call(this,error.element,this.settings.errorClass,this.settings.validClass);this.showLabel(error.element,error.message);}if(this.errorList.length){this.toShow=this.toShow.add(this.containers);}if(this.settings.success){for(var i=0;this.successList[i];i++){this.showLabel(this.successList[i]);}}if(this.settings.unhighlight){for(var i=0,elements=this.validElements();elements[i];i++){this.settings.unhighlight.call(this,elements[i],this.settings.errorClass,this.settings.validClass);}}this.toHide=this.toHide.not(this.toShow);this.hideErrors();this.addWrapper(this.toShow).show();},validElements:function(){return this.currentElements.not(this.invalidElements());},invalidElements:function(){return $(this.errorList).map(function(){return this.element;});},showLabel:function(element,message){var label=this.errorsFor(element);if(label.length){label.removeClass().addClass(this.settings.errorClass);label.attr("generated")&&label.html(message);}else{label=$("<"+this.settings.errorElement+"/>").attr({"for":this.idOrName(element),generated:true}).addClass(this.settings.errorClass).html(message||"");if(this.settings.wrapper){label=label.hide().show().wrap("<"+this.settings.wrapper+"/>").parent();}if(!this.labelContainer.append(label).length)this.settings.errorPlacement?this.settings.errorPlacement(label,$(element)):label.insertAfter(element);}if(!message&&this.settings.success){label.text("");typeof this.settings.success=="string"?label.addClass(this.settings.success):this.settings.success(label);}this.toShow=this.toShow.add(label);},errorsFor:function(element){var name=this.idOrName(element);return this.errors().filter(function(){return $(this).attr('for')==name});},idOrName:function(element){return this.groups[element.name]||(this.checkable(element)?element.name:element.id||element.name);},checkable:function(element){return/radio|checkbox/i.test(element.type);},findByName:function(name){var form=this.currentForm;return $(document.getElementsByName(name)).map(function(index,element){return element.form==form&&element.name==name&&element||null;});},getLength:function(value,element){switch(element.nodeName.toLowerCase()){case'select':return $("option:selected",element).length;case'input':if(this.checkable(element))return this.findByName(element.name).filter(':checked').length;}return value.length;},depend:function(param,element){return this.dependTypes[typeof param]?this.dependTypes[typeof param](param,element):true;},dependTypes:{"boolean":function(param,element){return param;},"string":function(param,element){return!!$(param,element.form).length;},"function":function(param,element){return param(element);}},optional:function(element){return!$.validator.methods.required.call(this,$.trim(element.value),element)&&"dependency-mismatch";},startRequest:function(element){if(!this.pending[element.name]){this.pendingRequest++;this.pending[element.name]=true;}},stopRequest:function(element,valid){this.pendingRequest--;if(this.pendingRequest<0)this.pendingRequest=0;delete this.pending[element.name];if(valid&&this.pendingRequest==0&&this.formSubmitted&&this.form()){$(this.currentForm).submit();this.formSubmitted=false;}else if(!valid&&this.pendingRequest==0&&this.formSubmitted){$(this.currentForm).triggerHandler("invalid-form",[this]);this.formSubmitted=false;}},previousValue:function(element){return $.data(element,"previousValue")||$.data(element,"previousValue",{old:null,valid:true,message:this.defaultMessage(element,"remote")});}},classRuleSettings:{required:{required:true},email:{email:true},url:{url:true},date:{date:true},dateISO:{dateISO:true},dateDE:{dateDE:true},number:{number:true},numberDE:{numberDE:true},digits:{digits:true},creditcard:{creditcard:true}},addClassRules:function(className,rules){className.constructor==String?this.classRuleSettings[className]=rules:$.extend(this.classRuleSettings,className);},classRules:function(element){var rules={};var classes=$(element).attr('class');classes&&$.each(classes.split(' '),function(){if(this in $.validator.classRuleSettings){$.extend(rules,$.validator.classRuleSettings[this]);}});return rules;},attributeRules:function(element){var rules={};var $element=$(element);for(method in $.validator.methods){var value=$element.attr(method);if(value){rules[method]=value;}}if(rules.maxlength&&/-1|2147483647|524288/.test(rules.maxlength)){delete rules.maxlength;}return rules;},metadataRules:function(element){if(!$.metadata)return{};var meta=$.data(element.form,'validator').settings.meta;return meta?$(element).metadata()[meta]:$(element).metadata();},staticRules:function(element){var rules={};var validator=$.data(element.form,'validator');if(validator.settings.rules){rules=$.validator.normalizeRule(validator.settings.rules[element.name])||{};}return rules;},normalizeRules:function(rules,element){$.each(rules,function(prop,val){if(val===false){delete rules[prop];return;}if(val.param||val.depends){var keepRule=true;switch(typeof val.depends){case"string":keepRule=!!$(val.depends,element.form).length;break;case"function":keepRule=val.depends.call(element,element);break;}if(keepRule){rules[prop]=val.param!==undefined?val.param:true;}else{delete rules[prop];}}});$.each(rules,function(rule,parameter){rules[rule]=$.isFunction(parameter)?parameter(element):parameter;});$.each(['minlength','maxlength','min','max'],function(){if(rules[this]){rules[this]=Number(rules[this]);}});$.each(['rangelength','range'],function(){if(rules[this]){rules[this]=[Number(rules[this][0]),Number(rules[this][1])];}});if($.validator.autoCreateRanges){if(rules.min&&rules.max){rules.range=[rules.min,rules.max];delete rules.min;delete rules.max;}if(rules.minlength&&rules.maxlength){rules.rangelength=[rules.minlength,rules.maxlength];delete rules.minlength;delete rules.maxlength;}}if(rules.messages){delete rules.messages}return rules;},normalizeRule:function(data){if(typeof data=="string"){var transformed={};$.each(data.split(/\s/),function(){transformed[this]=true;});data=transformed;}return data;},addMethod:function(name,method,message){$.validator.methods[name]=method;$.validator.messages[name]=message!=undefined?message:$.validator.messages[name];if(method.length<3){$.validator.addClassRules(name,$.validator.normalizeRule(name));}},methods:{required:function(value,element,param){if(!this.depend(param,element))return"dependency-mismatch";switch(element.nodeName.toLowerCase()){case'select':var val=$(element).val();return val&&val.length>0;case'input':if(this.checkable(element))return this.getLength(value,element)>0;default:return $.trim(value).length>0;}},remote:function(value,element,param){if(this.optional(element))return"dependency-mismatch";var previous=this.previousValue(element);if(!this.settings.messages[element.name])this.settings.messages[element.name]={};previous.originalMessage=this.settings.messages[element.name].remote;this.settings.messages[element.name].remote=previous.message;param=typeof param=="string"&&{url:param}||param;if(previous.old!==value){previous.old=value;var validator=this;this.startRequest(element);var data={};data[element.name]=value;$.ajax($.extend(true,{url:param,mode:"abort",port:"validate"+element.name,dataType:"json",data:data,success:function(response){validator.settings.messages[element.name].remote=previous.originalMessage;var valid=response===true;if(valid){var submitted=validator.formSubmitted;validator.prepareElement(element);validator.formSubmitted=submitted;validator.successList.push(element);validator.showErrors();}else{var errors={};var message=(previous.message=response||validator.defaultMessage(element,"remote"));errors[element.name]=$.isFunction(message)?message(value):message;validator.showErrors(errors);}previous.valid=valid;validator.stopRequest(element,valid);}},param));return"pending";}else if(this.pending[element.name]){return"pending";}return previous.valid;},minlength:function(value,element,param){return this.optional(element)||this.getLength($.trim(value),element)>=param;},maxlength:function(value,element,param){return this.optional(element)||this.getLength($.trim(value),element)<=param;},rangelength:function(value,element,param){var length=this.getLength($.trim(value),element);return this.optional(element)||(length>=param[0]&&length<=param[1]);},min:function(value,element,param){return this.optional(element)||value>=param;},max:function(value,element,param){return this.optional(element)||value<=param;},range:function(value,element,param){return this.optional(element)||(value>=param[0]&&value<=param[1]);},email:function(value,element){return this.optional(element)||/^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?$/i.test(value);},url:function(value,element){return this.optional(element)||/^(https?|ftp):\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(\#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i.test(value);},date:function(value,element){return this.optional(element)||!/Invalid|NaN/.test(new Date(value));},dateISO:function(value,element){return this.optional(element)||/^\d{4}[\/-]\d{1,2}[\/-]\d{1,2}$/.test(value);},number:function(value,element){return this.optional(element)||/^-?(?:\d+|\d{1,3}(?:,\d{3})+)(?:\.\d+)?$/.test(value);},digits:function(value,element){return this.optional(element)||/^\d+$/.test(value);},creditcard:function(value,element){if(this.optional(element))return"dependency-mismatch";if(/[^0-9-]+/.test(value))return false;var nCheck=0,nDigit=0,bEven=false;value=value.replace(/\D/g,"");for(var n=value.length-1;n>=0;n--){var cDigit=value.charAt(n);var nDigit=parseInt(cDigit,10);if(bEven){if((nDigit*=2)>9)nDigit-=9;}nCheck+=nDigit;bEven=!bEven;}return(nCheck%10)==0;},accept:function(value,element,param){param=typeof param=="string"?param.replace(/,/g,'|'):"png|jpe?g|gif";return this.optional(element)||value.match(new RegExp(".("+param+")$","i"));},equalTo:function(value,element,param){var target=$(param).unbind(".validate-equalTo").bind("blur.validate-equalTo",function(){$(element).valid();});return value==target.val();}}});$.format=$.validator.format;})(jQuery);;(function($){var ajax=$.ajax;var pendingRequests={};$.ajax=function(settings){settings=$.extend(settings,$.extend({},$.ajaxSettings,settings));var port=settings.port;if(settings.mode=="abort"){if(pendingRequests[port]){pendingRequests[port].abort();}return(pendingRequests[port]=ajax.apply(this,arguments));}return ajax.apply(this,arguments);};})(jQuery);;(function($){$.each({focus:'focusin',blur:'focusout'},function(original,fix){$.event.special[fix]={setup:function(){if($.browser.msie)return false;this.addEventListener(original,$.event.special[fix].handler,true);},teardown:function(){if($.browser.msie)return false;this.removeEventListener(original,$.event.special[fix].handler,true);},handler:function(e){arguments[0]=$.event.fix(e);arguments[0].type=fix;return $.event.handle.apply(this,arguments);}};});$.extend($.fn,{delegate:function(type,delegate,handler){return this.bind(type,function(event){var target=$(event.target);if(target.is(delegate)){return handler.apply(target,arguments);}});},triggerEvent:function(type,target){return this.triggerHandler(type,[$.event.fix({type:type,target:target})]);}})})(jQuery); -------------------------------------------------------------------------------- /TestWebApp/TestStartupCode/MyStartupCode.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics; 2 | using System.Web.Mvc; 3 | using System.Web.Routing; 4 | 5 | [assembly: WebActivatorEx.PreApplicationStartMethod(typeof(TestWebApp.TestStartupCode.MyStartupCode), "Start",Order = 1)] 6 | 7 | namespace TestWebApp.TestStartupCode 8 | { 9 | public static class MyStartupCode 10 | { 11 | public static bool StartCalled { get; set; } 12 | 13 | public static void Start() 14 | { 15 | StartCalled = true; 16 | Debug.WriteLine("MyStartUpCode1"); 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /TestWebApp/TestStartupCode/MyStartupCode2.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics; 2 | using System.Web.Mvc; 3 | using System.Web.Routing; 4 | 5 | [assembly: WebActivatorEx.PreApplicationStartMethod(typeof(TestWebApp.TestStartupCode.MyStartupCode2), "Start", Order = 0)] 6 | 7 | namespace TestWebApp.TestStartupCode 8 | { 9 | public static class MyStartupCode2 10 | { 11 | public static bool StartCalled { get; set; } 12 | 13 | public static void Start() 14 | { 15 | StartCalled = true; 16 | Debug.WriteLine("MyStartUpCode2"); 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /TestWebApp/TestWebApp.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | 8 | 9 | 2.0 10 | {BEAE1B92-B497-4179-8EC5-BCABCE303078} 11 | {E53F8FEA-EAE0-44A6-8774-FFD645390401};{349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc} 12 | Library 13 | Properties 14 | TestWebApp 15 | TestWebApp 16 | v4.0 17 | true 18 | false 19 | ..\ 20 | true 21 | 22 | 23 | 24 | 25 | 4.0 26 | true 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | true 35 | full 36 | false 37 | bin\ 38 | DEBUG;TRACE 39 | prompt 40 | 4 41 | 42 | 43 | pdbonly 44 | true 45 | bin\ 46 | TRACE 47 | prompt 48 | 4 49 | 50 | 51 | 52 | 53 | ..\packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll 54 | True 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | ..\packages\Microsoft.AspNet.WebPages.1.0.20105.408\lib\net40\System.Web.Helpers.dll 66 | True 67 | 68 | 69 | ..\packages\Microsoft.AspNet.Mvc.3.0.50813.1\lib\net40\System.Web.Mvc.dll 70 | True 71 | 72 | 73 | ..\packages\Microsoft.AspNet.Razor.1.0.20105.408\lib\net40\System.Web.Razor.dll 74 | True 75 | 76 | 77 | ..\packages\Microsoft.AspNet.WebPages.1.0.20105.408\lib\net40\System.Web.WebPages.dll 78 | True 79 | 80 | 81 | ..\packages\Microsoft.AspNet.WebPages.1.0.20105.408\lib\net40\System.Web.WebPages.Deployment.dll 82 | True 83 | 84 | 85 | ..\packages\Microsoft.AspNet.WebPages.1.0.20105.408\lib\net40\System.Web.WebPages.Razor.dll 86 | True 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | Global.asax 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | Web.config 115 | 116 | 117 | Web.config 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | {3D5B026A-2E5F-4C03-8F70-945517215017} 149 | TestLibrary 150 | 151 | 152 | {339C42C9-C961-4E37-B64E-16F1EF03E4D9} 153 | WebActivator 154 | 155 | 156 | 157 | 158 | 159 | 160 | 10.0 161 | $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) 162 | 163 | 164 | 165 | 166 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | False 180 | True 181 | 6562 182 | / 183 | 184 | 185 | False 186 | False 187 | 188 | 189 | False 190 | 191 | 192 | 193 | 194 | 195 | -------------------------------------------------------------------------------- /TestWebApp/Views/Account/ChangePassword.aspx: -------------------------------------------------------------------------------- 1 | <%@ Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage" %> 2 | 3 | 4 | Change Password 5 | 6 | 7 | 8 |

Change Password

9 |

10 | Use the form below to change your password. 11 |

12 |

13 | New passwords are required to be a minimum of <%: ViewBag.PasswordLength %> characters in length. 14 |

15 | 16 | <% using (Html.BeginForm()) { %> 17 | <%: Html.ValidationSummary(true, "Password change was unsuccessful. Please correct the errors and try again.") %> 18 |
19 |
20 | Account Information 21 | 22 |
23 | <%: Html.LabelFor(m => m.OldPassword) %> 24 |
25 |
26 | <%: Html.PasswordFor(m => m.OldPassword) %> 27 | <%: Html.ValidationMessageFor(m => m.OldPassword) %> 28 |
29 | 30 |
31 | <%: Html.LabelFor(m => m.NewPassword) %> 32 |
33 |
34 | <%: Html.PasswordFor(m => m.NewPassword) %> 35 | <%: Html.ValidationMessageFor(m => m.NewPassword) %> 36 |
37 | 38 |
39 | <%: Html.LabelFor(m => m.ConfirmPassword) %> 40 |
41 |
42 | <%: Html.PasswordFor(m => m.ConfirmPassword) %> 43 | <%: Html.ValidationMessageFor(m => m.ConfirmPassword) %> 44 |
45 | 46 |

47 | 48 |

49 |
50 |
51 | <% } %> 52 |
53 | -------------------------------------------------------------------------------- /TestWebApp/Views/Account/ChangePasswordSuccess.aspx: -------------------------------------------------------------------------------- 1 | <%@ Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage" %> 2 | 3 | 4 | Change Password 5 | 6 | 7 | 8 |

Change Password

9 |

10 | Your password has been changed successfully. 11 |

12 |
13 | -------------------------------------------------------------------------------- /TestWebApp/Views/Account/LogOn.aspx: -------------------------------------------------------------------------------- 1 | <%@ Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage" %> 2 | 3 | 4 | Log On 5 | 6 | 7 | 8 |

Log On

9 |

10 | Please enter your username and password. <%: Html.ActionLink("Register", "Register") %> if you don't have an account. 11 |

12 | 13 | <% using (Html.BeginForm()) { %> 14 | <%: Html.ValidationSummary(true, "Login was unsuccessful. Please correct the errors and try again.") %> 15 |
16 |
17 | Account Information 18 | 19 |
20 | <%: Html.LabelFor(m => m.UserName) %> 21 |
22 |
23 | <%: Html.TextBoxFor(m => m.UserName) %> 24 | <%: Html.ValidationMessageFor(m => m.UserName) %> 25 |
26 | 27 |
28 | <%: Html.LabelFor(m => m.Password) %> 29 |
30 |
31 | <%: Html.PasswordFor(m => m.Password) %> 32 | <%: Html.ValidationMessageFor(m => m.Password) %> 33 |
34 | 35 |
36 | <%: Html.CheckBoxFor(m => m.RememberMe) %> 37 | <%: Html.LabelFor(m => m.RememberMe) %> 38 |
39 | 40 |

41 | 42 |

43 |
44 |
45 | <% } %> 46 |
47 | -------------------------------------------------------------------------------- /TestWebApp/Views/Account/Register.aspx: -------------------------------------------------------------------------------- 1 | <%@ Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage" %> 2 | 3 | 4 | Register 5 | 6 | 7 | 8 |

Create a New Account

9 |

10 | Use the form below to create a new account. 11 |

12 |

13 | Passwords are required to be a minimum of <%: ViewBag.PasswordLength %> characters in length. 14 |

15 | 16 | <% using (Html.BeginForm()) { %> 17 | <%: Html.ValidationSummary(true, "Account creation was unsuccessful. Please correct the errors and try again.") %> 18 |
19 |
20 | Account Information 21 | 22 |
23 | <%: Html.LabelFor(m => m.UserName) %> 24 |
25 |
26 | <%: Html.TextBoxFor(m => m.UserName) %> 27 | <%: Html.ValidationMessageFor(m => m.UserName) %> 28 |
29 | 30 |
31 | <%: Html.LabelFor(m => m.Email) %> 32 |
33 |
34 | <%: Html.TextBoxFor(m => m.Email) %> 35 | <%: Html.ValidationMessageFor(m => m.Email) %> 36 |
37 | 38 |
39 | <%: Html.LabelFor(m => m.Password) %> 40 |
41 |
42 | <%: Html.PasswordFor(m => m.Password) %> 43 | <%: Html.ValidationMessageFor(m => m.Password) %> 44 |
45 | 46 |
47 | <%: Html.LabelFor(m => m.ConfirmPassword) %> 48 |
49 |
50 | <%: Html.PasswordFor(m => m.ConfirmPassword) %> 51 | <%: Html.ValidationMessageFor(m => m.ConfirmPassword) %> 52 |
53 | 54 |

55 | 56 |

57 |
58 |
59 | <% } %> 60 |
61 | -------------------------------------------------------------------------------- /TestWebApp/Views/Home/About.aspx: -------------------------------------------------------------------------------- 1 | <%@ Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage" %> 2 | 3 | 4 | About Us 5 | 6 | 7 | 8 |

About

9 |

10 | Put content here. 11 |

12 |
13 | -------------------------------------------------------------------------------- /TestWebApp/Views/Home/Index.aspx: -------------------------------------------------------------------------------- 1 | <%@ Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage" %> 2 | 3 | 4 | Home Page 5 | 6 | 7 | 8 | <% 9 | if (!TestLibrary.MyStartupCode.StartCalled || !TestLibrary.MyStartupCode.Start2Called || 10 | !TestLibrary.MyStartupCode.CallMeAfterAppStartCalled || !TestWebApp.TestStartupCode.MyStartupCode.StartCalled || 11 | !AppCodeStartupCode.StartCalled || TestLibrary.MyStartupCode.CallMeWhenAppEndsCalled) { 12 | throw new Exception("Startup methods were not correctly called"); 13 | } 14 | %> 15 | 16 |

All startup methods were successfully called!

17 |
18 | -------------------------------------------------------------------------------- /TestWebApp/Views/Shared/Error.aspx: -------------------------------------------------------------------------------- 1 | <%@ Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage" %> 2 | 3 | 4 | Error 5 | 6 | 7 | 8 |

9 | Sorry, an error occurred while processing your request. 10 |

11 |
12 | -------------------------------------------------------------------------------- /TestWebApp/Views/Shared/LogOnUserControl.ascx: -------------------------------------------------------------------------------- 1 | <%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl" %> 2 | <% 3 | if (Request.IsAuthenticated) { 4 | %> 5 | Welcome <%: Page.User.Identity.Name %>! 6 | [ <%: Html.ActionLink("Log Off", "LogOff", "Account") %> ] 7 | <% 8 | } 9 | else { 10 | %> 11 | [ <%: Html.ActionLink("Log On", "LogOn", "Account") %> ] 12 | <% 13 | } 14 | %> 15 | -------------------------------------------------------------------------------- /TestWebApp/Views/Shared/Site.Master: -------------------------------------------------------------------------------- 1 | <%@ Master Language="C#" Inherits="System.Web.Mvc.ViewMasterPage" %> 2 | 3 | 4 | 5 | 6 | <asp:ContentPlaceHolder ID="TitleContent" runat="server" /> 7 | 8 | 9 | 10 | 11 |
12 | 13 | 31 | 32 |
33 | 34 | 35 | 37 |
38 |
39 | 40 | 41 | -------------------------------------------------------------------------------- /TestWebApp/Views/Web.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 16 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /TestWebApp/Web.Debug.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 17 | 18 | 29 | 30 | -------------------------------------------------------------------------------- /TestWebApp/Web.Release.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 17 | 18 | 19 | 30 | 31 | -------------------------------------------------------------------------------- /TestWebApp/Web.config: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | -------------------------------------------------------------------------------- /TestWebApp/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /TraceAndTestImpact.testsettings: -------------------------------------------------------------------------------- 1 |  2 | 3 | These are test settings for Trace and Test Impact. 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /WebActivator.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 14 4 | VisualStudioVersion = 14.0.24720.0 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{C2257462-7F5F-4C80-B04B-3D48026B109C}" 7 | ProjectSection(SolutionItems) = preProject 8 | Local.testsettings = Local.testsettings 9 | TraceAndTestImpact.testsettings = TraceAndTestImpact.testsettings 10 | WebActivator.vsmdi = WebActivator.vsmdi 11 | EndProjectSection 12 | EndProject 13 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WebActivator", "WebActivator\WebActivator.csproj", "{339C42C9-C961-4E37-B64E-16F1EF03E4D9}" 14 | EndProject 15 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestLibrary", "TestLibrary\TestLibrary.csproj", "{3D5B026A-2E5F-4C03-8F70-945517215017}" 16 | EndProject 17 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestWebApp", "TestWebApp\TestWebApp.csproj", "{BEAE1B92-B497-4179-8EC5-BCABCE303078}" 18 | EndProject 19 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WebActivatorTest", "WebActivatorTest\WebActivatorTest.csproj", "{1B623743-BE4E-4034-890F-D378E8C254F9}" 20 | EndProject 21 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestLibrary2", "TestLibrary2\TestLibrary2.csproj", "{638765A7-E010-495F-B325-821D735B2121}" 22 | EndProject 23 | Global 24 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 25 | Debug|Any CPU = Debug|Any CPU 26 | Debug|Mixed Platforms = Debug|Mixed Platforms 27 | Debug|x86 = Debug|x86 28 | Release|Any CPU = Release|Any CPU 29 | Release|Mixed Platforms = Release|Mixed Platforms 30 | Release|x86 = Release|x86 31 | EndGlobalSection 32 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 33 | {339C42C9-C961-4E37-B64E-16F1EF03E4D9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 34 | {339C42C9-C961-4E37-B64E-16F1EF03E4D9}.Debug|Any CPU.Build.0 = Debug|Any CPU 35 | {339C42C9-C961-4E37-B64E-16F1EF03E4D9}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU 36 | {339C42C9-C961-4E37-B64E-16F1EF03E4D9}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU 37 | {339C42C9-C961-4E37-B64E-16F1EF03E4D9}.Debug|x86.ActiveCfg = Debug|Any CPU 38 | {339C42C9-C961-4E37-B64E-16F1EF03E4D9}.Release|Any CPU.ActiveCfg = Release|Any CPU 39 | {339C42C9-C961-4E37-B64E-16F1EF03E4D9}.Release|Any CPU.Build.0 = Release|Any CPU 40 | {339C42C9-C961-4E37-B64E-16F1EF03E4D9}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU 41 | {339C42C9-C961-4E37-B64E-16F1EF03E4D9}.Release|Mixed Platforms.Build.0 = Release|Any CPU 42 | {339C42C9-C961-4E37-B64E-16F1EF03E4D9}.Release|x86.ActiveCfg = Release|Any CPU 43 | {3D5B026A-2E5F-4C03-8F70-945517215017}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 44 | {3D5B026A-2E5F-4C03-8F70-945517215017}.Debug|Any CPU.Build.0 = Debug|Any CPU 45 | {3D5B026A-2E5F-4C03-8F70-945517215017}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU 46 | {3D5B026A-2E5F-4C03-8F70-945517215017}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU 47 | {3D5B026A-2E5F-4C03-8F70-945517215017}.Debug|x86.ActiveCfg = Debug|Any CPU 48 | {3D5B026A-2E5F-4C03-8F70-945517215017}.Release|Any CPU.ActiveCfg = Release|Any CPU 49 | {3D5B026A-2E5F-4C03-8F70-945517215017}.Release|Any CPU.Build.0 = Release|Any CPU 50 | {3D5B026A-2E5F-4C03-8F70-945517215017}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU 51 | {3D5B026A-2E5F-4C03-8F70-945517215017}.Release|Mixed Platforms.Build.0 = Release|Any CPU 52 | {3D5B026A-2E5F-4C03-8F70-945517215017}.Release|x86.ActiveCfg = Release|Any CPU 53 | {BEAE1B92-B497-4179-8EC5-BCABCE303078}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 54 | {BEAE1B92-B497-4179-8EC5-BCABCE303078}.Debug|Any CPU.Build.0 = Debug|Any CPU 55 | {BEAE1B92-B497-4179-8EC5-BCABCE303078}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU 56 | {BEAE1B92-B497-4179-8EC5-BCABCE303078}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU 57 | {BEAE1B92-B497-4179-8EC5-BCABCE303078}.Debug|x86.ActiveCfg = Debug|Any CPU 58 | {BEAE1B92-B497-4179-8EC5-BCABCE303078}.Release|Any CPU.ActiveCfg = Release|Any CPU 59 | {BEAE1B92-B497-4179-8EC5-BCABCE303078}.Release|Any CPU.Build.0 = Release|Any CPU 60 | {BEAE1B92-B497-4179-8EC5-BCABCE303078}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU 61 | {BEAE1B92-B497-4179-8EC5-BCABCE303078}.Release|Mixed Platforms.Build.0 = Release|Any CPU 62 | {BEAE1B92-B497-4179-8EC5-BCABCE303078}.Release|x86.ActiveCfg = Release|Any CPU 63 | {1B623743-BE4E-4034-890F-D378E8C254F9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 64 | {1B623743-BE4E-4034-890F-D378E8C254F9}.Debug|Any CPU.Build.0 = Debug|Any CPU 65 | {1B623743-BE4E-4034-890F-D378E8C254F9}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU 66 | {1B623743-BE4E-4034-890F-D378E8C254F9}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU 67 | {1B623743-BE4E-4034-890F-D378E8C254F9}.Debug|x86.ActiveCfg = Debug|Any CPU 68 | {1B623743-BE4E-4034-890F-D378E8C254F9}.Release|Any CPU.ActiveCfg = Release|Any CPU 69 | {1B623743-BE4E-4034-890F-D378E8C254F9}.Release|Any CPU.Build.0 = Release|Any CPU 70 | {1B623743-BE4E-4034-890F-D378E8C254F9}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU 71 | {1B623743-BE4E-4034-890F-D378E8C254F9}.Release|Mixed Platforms.Build.0 = Release|Any CPU 72 | {1B623743-BE4E-4034-890F-D378E8C254F9}.Release|x86.ActiveCfg = Release|Any CPU 73 | {638765A7-E010-495F-B325-821D735B2121}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 74 | {638765A7-E010-495F-B325-821D735B2121}.Debug|Any CPU.Build.0 = Debug|Any CPU 75 | {638765A7-E010-495F-B325-821D735B2121}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU 76 | {638765A7-E010-495F-B325-821D735B2121}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU 77 | {638765A7-E010-495F-B325-821D735B2121}.Debug|x86.ActiveCfg = Debug|Any CPU 78 | {638765A7-E010-495F-B325-821D735B2121}.Release|Any CPU.ActiveCfg = Release|Any CPU 79 | {638765A7-E010-495F-B325-821D735B2121}.Release|Any CPU.Build.0 = Release|Any CPU 80 | {638765A7-E010-495F-B325-821D735B2121}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU 81 | {638765A7-E010-495F-B325-821D735B2121}.Release|Mixed Platforms.Build.0 = Release|Any CPU 82 | {638765A7-E010-495F-B325-821D735B2121}.Release|x86.ActiveCfg = Release|Any CPU 83 | EndGlobalSection 84 | GlobalSection(SolutionProperties) = preSolution 85 | HideSolutionNode = FALSE 86 | EndGlobalSection 87 | GlobalSection(TestCaseManagementSettings) = postSolution 88 | CategoryFile = WebActivator.vsmdi 89 | EndGlobalSection 90 | EndGlobal 91 | -------------------------------------------------------------------------------- /WebActivator.vsmdi: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /WebActivator/ActivationManager.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Configuration; 5 | using System.IO; 6 | using System.Linq; 7 | using System.Reflection; 8 | using System.Security; 9 | using System.Text.RegularExpressions; 10 | using System.Web; 11 | using System.Web.Compilation; 12 | using System.Web.Configuration; 13 | using System.Web.Hosting; 14 | 15 | namespace WebActivatorEx 16 | { 17 | public class ActivationManager 18 | { 19 | private static bool _hasInited; 20 | private static List _assemblies; 21 | private static Func _fileFilter = a => true; 22 | 23 | // For unit test purpose 24 | public static void Reset() 25 | { 26 | _hasInited = false; 27 | _assemblies = null; 28 | } 29 | 30 | public static void Run() 31 | { 32 | if (!_hasInited) 33 | { 34 | DetermineWhatFilesAndAssembliesToScan(); 35 | 36 | bool isRunningMono = Type.GetType("Mono.Runtime") != null; 37 | 38 | if (isRunningMono) 39 | { 40 | RunPreStartMethods(designerMode: false); 41 | } 42 | else 43 | { 44 | // In CBM mode, pass true so that only the methods that have RunInDesigner=true get called 45 | RunPreStartMethods(designerMode: IsInClientBuildManager()); 46 | } 47 | 48 | // Register our module to handle any Post Start methods. But outside of ASP.NET, just run them now 49 | if (HostingEnvironment.IsHosted) 50 | { 51 | Type startMethodType = typeof(StartMethodCallingModule); 52 | 53 | if (isRunningMono) 54 | { 55 | HttpModuleActionCollection modules = (WebConfigurationManager.GetWebApplicationSection("system.web/httpModules") as HttpModulesSection).Modules; 56 | modules.Add(new HttpModuleAction(startMethodType.FullName, startMethodType.AssemblyQualifiedName)); 57 | } 58 | else 59 | { 60 | Microsoft.Web.Infrastructure.DynamicModuleHelper.DynamicModuleUtility.RegisterModule(startMethodType); 61 | } 62 | } 63 | else 64 | { 65 | RunPostStartMethods(); 66 | } 67 | 68 | _hasInited = true; 69 | } 70 | } 71 | 72 | private static void DetermineWhatFilesAndAssembliesToScan() 73 | { 74 | var value = ConfigurationManager.AppSettings["webactivator:excludedFilesExpression"]; 75 | if (value != null) 76 | { 77 | var fileExpression = new Regex(value.Trim()); 78 | _fileFilter = file => !fileExpression.IsMatch(file); 79 | } 80 | } 81 | 82 | private static bool IsInClientBuildManager() 83 | { 84 | return HostingEnvironment.InClientBuildManager; 85 | } 86 | 87 | private static IEnumerable Assemblies 88 | { 89 | get 90 | { 91 | if (_assemblies == null) 92 | { 93 | // Cache the list of relevant assemblies, since we need it for both Pre and Post 94 | _assemblies = new List(); 95 | 96 | string assembliesToScanString = ConfigurationManager.AppSettings["webactivator:assembliesToScan"]; 97 | if (assembliesToScanString != null) 98 | { 99 | foreach (string assemblyName in assembliesToScanString.Split(',')) 100 | { 101 | _assemblies.Add(Assembly.Load(assemblyName)); 102 | } 103 | } 104 | else 105 | { 106 | foreach (var assemblyFile in GetAssemblyFiles().Where(file => _fileFilter(file))) 107 | { 108 | try 109 | { 110 | // Ignore assemblies we can't load. They could be native, etc... 111 | _assemblies.Add(Assembly.LoadFrom(assemblyFile)); 112 | } 113 | catch (Win32Exception) { } 114 | catch (ArgumentException) { } 115 | catch (FileNotFoundException) { } 116 | catch (PathTooLongException) { } 117 | catch (BadImageFormatException) { } 118 | catch (SecurityException) { } 119 | } 120 | } 121 | } 122 | 123 | return _assemblies; 124 | } 125 | } 126 | 127 | private static IEnumerable GetAssemblyFiles() 128 | { 129 | // When running under ASP.NET, find assemblies in the bin folder. 130 | // Outside of ASP.NET, use whatever folder WebActivator itself is in 131 | string directory = HostingEnvironment.IsHosted 132 | ? HttpRuntime.BinDirectory 133 | : Path.GetDirectoryName(new Uri(Assembly.GetExecutingAssembly().CodeBase).LocalPath); 134 | return Directory.GetFiles(directory, "*.dll"); 135 | } 136 | 137 | // Return all the App_Code assemblies 138 | private static IEnumerable AppCodeAssemblies 139 | { 140 | get 141 | { 142 | // Return an empty list if we're not hosted or there aren't any 143 | if (!HostingEnvironment.IsHosted || !_hasInited || BuildManager.CodeAssemblies == null) 144 | { 145 | return Enumerable.Empty(); 146 | } 147 | 148 | return BuildManager.CodeAssemblies.OfType(); 149 | } 150 | } 151 | 152 | public static void RunPreStartMethods(bool designerMode = false) 153 | { 154 | RunActivationMethods(designerMode); 155 | } 156 | 157 | public static void RunPostStartMethods() 158 | { 159 | RunActivationMethods(); 160 | } 161 | 162 | public static void RunShutdownMethods() 163 | { 164 | RunActivationMethods(); 165 | } 166 | 167 | // Call the relevant activation method from all assemblies 168 | private static void RunActivationMethods(bool designerMode = false) where T : BaseActivationMethodAttribute 169 | { 170 | var attribs = Assemblies.Concat(AppCodeAssemblies) 171 | .SelectMany(assembly => assembly.GetActivationAttributes()) 172 | .OrderBy(att => att.Order); 173 | 174 | foreach (var activationAttrib in attribs) 175 | { 176 | // Don't run it in designer mode, unless the attribute explicitly asks for that 177 | if (!designerMode || activationAttrib.ShouldRunInDesignerMode()) 178 | { 179 | activationAttrib.InvokeMethod(); 180 | } 181 | } 182 | } 183 | 184 | class StartMethodCallingModule : IHttpModule 185 | { 186 | private static object _lock = new object(); 187 | private static int _initializedModuleCount; 188 | 189 | public void Init(HttpApplication context) 190 | { 191 | 192 | lock (_lock) 193 | { 194 | // Keep track of the number of modules initialized and 195 | // make sure we only call the post start methods once per app domain 196 | if (_initializedModuleCount++ == 0) 197 | { 198 | RunPostStartMethods(); 199 | } 200 | } 201 | } 202 | 203 | public void Dispose() 204 | { 205 | lock (_lock) 206 | { 207 | // Call the shutdown methods when the last module is disposed 208 | if (--_initializedModuleCount == 0) 209 | { 210 | RunShutdownMethods(); 211 | } 212 | } 213 | } 214 | } 215 | } 216 | } 217 | -------------------------------------------------------------------------------- /WebActivator/ApplicationShutdownMethodAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace WebActivatorEx 4 | { 5 | // Same as PreApplicationStartMethodAttribute, but for methods to be called when the app shuts down 6 | [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] 7 | public sealed class ApplicationShutdownMethodAttribute : BaseActivationMethodAttribute 8 | { 9 | public ApplicationShutdownMethodAttribute(Type type, string methodName) 10 | : base(type, methodName) 11 | { 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /WebActivator/AssemblyExtensions.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using System.Reflection; 4 | 5 | namespace WebActivatorEx 6 | { 7 | static class AssemblyExtensions 8 | { 9 | // Return all the attributes of a given type from an assembly 10 | public static IEnumerable GetActivationAttributes(this Assembly assembly) where T : BaseActivationMethodAttribute 11 | { 12 | try 13 | { 14 | return assembly.GetCustomAttributes( 15 | typeof(T), 16 | inherit: false).OfType(); 17 | } 18 | catch 19 | { 20 | // In some very odd (and not well understood) cases, GetCustomAttributes throws. Just ignore it. 21 | // See https://github.com/davidebbo/WebActivator/issues/12 for details 22 | return Enumerable.Empty(); 23 | } 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /WebActivator/BaseActivationMethodAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Reflection; 3 | 4 | namespace WebActivatorEx 5 | { 6 | // Base class of all the activation attributes 7 | [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] 8 | public abstract class BaseActivationMethodAttribute : Attribute 9 | { 10 | private Type _type; 11 | private string _methodName; 12 | 13 | public BaseActivationMethodAttribute(Type type, string methodName) 14 | { 15 | _type = type; 16 | _methodName = methodName; 17 | } 18 | 19 | public Type Type 20 | { 21 | get 22 | { 23 | return _type; 24 | } 25 | } 26 | 27 | public string MethodName 28 | { 29 | get 30 | { 31 | return _methodName; 32 | } 33 | } 34 | 35 | public int Order { get; set; } 36 | 37 | 38 | public void InvokeMethod() 39 | { 40 | // Get the method 41 | MethodInfo method = Type.GetMethod( 42 | MethodName, 43 | BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public); 44 | 45 | if (method == null) 46 | { 47 | throw new ArgumentException( 48 | String.Format("The type {0} doesn't have a static method named {1}", 49 | Type, MethodName)); 50 | } 51 | 52 | // Invoke it 53 | method.Invoke(null, null); 54 | } 55 | 56 | public virtual bool ShouldRunInDesignerMode() 57 | { 58 | return false; 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /WebActivator/PostApplicationStartMethodAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace WebActivatorEx 4 | { 5 | // Same as PreApplicationStartMethodAttribute, but for methods to be called after App_Start 6 | [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] 7 | public sealed class PostApplicationStartMethodAttribute : BaseActivationMethodAttribute 8 | { 9 | public PostApplicationStartMethodAttribute(Type type, string methodName) 10 | : base(type, methodName) 11 | { 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /WebActivator/PreApplicationStartMethodAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace WebActivatorEx 4 | { 5 | // This attribute is similar to its System.Web namesake, except that 6 | // it can be used multiple times on an assembly. 7 | [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] 8 | public sealed class PreApplicationStartMethodAttribute : BaseActivationMethodAttribute 9 | { 10 | public PreApplicationStartMethodAttribute(Type type, string methodName) 11 | : base(type, methodName) 12 | { 13 | } 14 | 15 | // Set this to true to have the method run in designer mode (in addition to running at runtime) 16 | public bool RunInDesigner { get; set; } 17 | 18 | public override bool ShouldRunInDesignerMode() 19 | { 20 | return RunInDesigner; 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /WebActivator/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | using System.Web; 5 | 6 | // General Information about an assembly is controlled through the following 7 | // set of attributes. Change these attribute values to modify the information 8 | // associated with an assembly. 9 | [assembly: AssemblyTitle("WebActivator")] 10 | [assembly: AssemblyDescription("A package that allows other packages to execute some startup code in web apps. This package should be used over the older WebActivator, which was not strong named.")] 11 | [assembly: AssemblyConfiguration("")] 12 | [assembly: AssemblyCompany("David Ebbo")] 13 | [assembly: AssemblyProduct("WebActivator")] 14 | [assembly: AssemblyCopyright("Copyright © Microsoft 2010")] 15 | [assembly: AssemblyTrademark("")] 16 | [assembly: AssemblyCulture("")] 17 | 18 | // Setting ComVisible to false makes the types in this assembly not visible 19 | // to COM components. If you need to access a type in this assembly from 20 | // COM, set the ComVisible attribute to true on that type. 21 | [assembly: ComVisible(false)] 22 | 23 | // The following GUID is for the ID of the typelib if this project is exposed to COM 24 | [assembly: Guid("3bc078bd-ade4-4271-964f-1d041508c419")] 25 | 26 | // Version information for an assembly consists of the following four values: 27 | // 28 | // Major Version 29 | // Minor Version 30 | // Build Number 31 | // Revision 32 | // 33 | // You can specify all the values or you can default the Build and Revision Numbers 34 | // by using the '*' as shown below: 35 | // [assembly: AssemblyVersion("1.0.*")] 36 | [assembly: AssemblyVersion("2.0.0")] 37 | [assembly: AssemblyFileVersion("2.2.0")] 38 | 39 | [assembly: PreApplicationStartMethod(typeof(WebActivatorEx.ActivationManager), "Run")] 40 | -------------------------------------------------------------------------------- /WebActivator/Properties/WebActivator.nuspec: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | $id$ 5 | WebActivatorEx 6 | 2.2.0 7 | $author$ 8 | false 9 | $description$ 10 | http://opensource.org/licenses/Apache-2.0 11 | https://github.com/davidebbo/WebActivator 12 | 13 | -------------------------------------------------------------------------------- /WebActivator/WebActivator.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Debug 5 | AnyCPU 6 | 8.0.30703 7 | 2.0 8 | {339C42C9-C961-4E37-B64E-16F1EF03E4D9} 9 | Library 10 | Properties 11 | WebActivatorEx 12 | WebActivatorEx 13 | v4.0 14 | 512 15 | 16 | ..\ 17 | true 18 | true 19 | 20 | 21 | true 22 | full 23 | false 24 | bin\Debug\ 25 | DEBUG;TRACE 26 | prompt 27 | 4 28 | 29 | 30 | pdbonly 31 | true 32 | bin\Release\ 33 | TRACE 34 | prompt 35 | 4 36 | 37 | 38 | 39 | True 40 | ..\packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | Designer 64 | 65 | 66 | 67 | 68 | 69 | 70 | $(PRIVATE_SNK_FILE) 71 | true 72 | false 73 | 74 | 75 | -------------------------------------------------------------------------------- /WebActivator/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /WebActivatorTest/App.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /WebActivatorTest/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("WebActivatorTest")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("Microsoft")] 12 | [assembly: AssemblyProduct("WebActivatorTest")] 13 | [assembly: AssemblyCopyright("Copyright © Microsoft 2011")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("6dc63e28-8799-4072-be84-291e971dd9dd")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | [assembly: AssemblyVersion("1.0.0.0")] 35 | [assembly: AssemblyFileVersion("1.0.0.0")] 36 | -------------------------------------------------------------------------------- /WebActivatorTest/WebActivatorTest.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Debug 5 | AnyCPU 6 | 7 | 8 | 2.0 9 | {1B623743-BE4E-4034-890F-D378E8C254F9} 10 | Library 11 | Properties 12 | WebActivatorTest 13 | WebActivatorTest 14 | v4.0 15 | 512 16 | {3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 17 | ..\ 18 | true 19 | 20 | 21 | true 22 | full 23 | false 24 | bin\Debug\ 25 | DEBUG;TRACE 26 | prompt 27 | 4 28 | 29 | 30 | pdbonly 31 | true 32 | bin\Release\ 33 | TRACE 34 | prompt 35 | 4 36 | 37 | 38 | 39 | True 40 | 41 | 42 | True 43 | 44 | 45 | 3.5 46 | True 47 | 48 | 49 | 50 | 51 | False 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | {638765A7-E010-495F-B325-821D735B2121} 61 | TestLibrary2 62 | 63 | 64 | {3D5B026A-2E5F-4C03-8F70-945517215017} 65 | TestLibrary 66 | 67 | 68 | {339C42C9-C961-4E37-B64E-16F1EF03E4D9} 69 | WebActivator 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 84 | -------------------------------------------------------------------------------- /WebActivatorTest/WebActivatorUnitTest.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using System.Reflection; 4 | using Microsoft.VisualStudio.TestTools.UnitTesting; 5 | using TestLibrary; 6 | using TestLibrary2; 7 | using WebActivatorEx; 8 | 9 | namespace WebActivatorTest 10 | { 11 | [TestClass] 12 | public class WebActivatorUnitTest 13 | { 14 | [TestInitialize] 15 | public void TestInit() 16 | { 17 | ActivationManager.Reset(); 18 | ExecutionLogger.ExecutedOrder = ""; 19 | MyStartupCode.StartCalled = false; 20 | MyStartupCode.Start2Called = false; 21 | MyStartupCode.CallMeAfterAppStartCalled = false; 22 | MyStartupCode.CallMeWhenAppEndsCalled = false; 23 | 24 | MyOtherStartupCode.StartCalled = false; 25 | MyOtherStartupCode.Start2Called = false; 26 | } 27 | 28 | [TestMethod] 29 | public void TestWebActivatorAllStartMethodsGetCalled() 30 | { 31 | ActivationManager.Run(); 32 | 33 | Assert.IsTrue(TestLibrary.MyStartupCode.StartCalled); 34 | Assert.IsTrue(TestLibrary.MyStartupCode.Start2Called); 35 | Assert.IsTrue(TestLibrary.MyStartupCode.CallMeAfterAppStartCalled); 36 | Assert.IsTrue(TestLibrary2.MyOtherStartupCode.StartCalled); 37 | Assert.IsTrue(TestLibrary2.MyOtherStartupCode.Start2Called); 38 | } 39 | 40 | [TestMethod] 41 | public void TestSystemMicrosoftAndWebActivatorAssembliesAreIgnored() 42 | { 43 | ActivationManager.Run(); 44 | 45 | // we're using reflection here to avoid changing the API just for the test 46 | var assemblies = (List)typeof(ActivationManager) 47 | .GetField("_assemblies", BindingFlags.Static | BindingFlags.NonPublic) 48 | .GetValue(null); 49 | 50 | Assert.IsFalse(assemblies.Any(a => a.GetName().Name.StartsWith("System"))); 51 | Assert.IsFalse(assemblies.Any(a => a.GetName().Name.StartsWith("Microsoft"))); 52 | Assert.IsFalse(assemblies.Any(a => a.GetName().Name.StartsWith("WebActivator"))); 53 | } 54 | 55 | [TestMethod] 56 | public void TestWebActivatorPreStartMethodsGetCalled() 57 | { 58 | ActivationManager.RunPreStartMethods(); 59 | 60 | Assert.IsTrue(TestLibrary.MyStartupCode.StartCalled); 61 | Assert.IsTrue(TestLibrary.MyStartupCode.Start2Called); 62 | Assert.IsFalse(TestLibrary.MyStartupCode.CallMeAfterAppStartCalled); 63 | } 64 | 65 | [TestMethod] 66 | public void TestWebActivatorPreStartMethodsInDesignerModeGetCalled() 67 | { 68 | ActivationManager.RunPreStartMethods(designerMode: true); 69 | 70 | Assert.IsTrue(TestLibrary.MyStartupCode.StartCalled); 71 | Assert.IsFalse(TestLibrary.MyStartupCode.Start2Called); 72 | Assert.IsFalse(TestLibrary.MyStartupCode.CallMeAfterAppStartCalled); 73 | } 74 | 75 | [TestMethod] 76 | public void TestWebActivatorPostStartMethodsGetCalled() 77 | { 78 | ActivationManager.RunPostStartMethods(); 79 | 80 | Assert.IsFalse(TestLibrary.MyStartupCode.StartCalled); 81 | Assert.IsFalse(TestLibrary.MyStartupCode.Start2Called); 82 | Assert.IsTrue(TestLibrary.MyStartupCode.CallMeAfterAppStartCalled); 83 | } 84 | 85 | [TestMethod] 86 | public void TestWebActivatorShutdownMethodsGetCalled() 87 | { 88 | ActivationManager.RunShutdownMethods(); 89 | 90 | Assert.IsTrue(MyStartupCode.CallMeWhenAppEndsCalled); 91 | } 92 | 93 | [TestMethod] 94 | public void TestWebActivatorMethodsCalledBySpecifiedOrder() 95 | { 96 | ActivationManager.Run(); 97 | ActivationManager.RunShutdownMethods(); 98 | Assert.AreEqual("StartStart3OtherStartStart2OtherStart2CallMeAfterAppStartCallMeWhenAppEnds", ExecutionLogger.ExecutedOrder); 99 | } 100 | } 101 | } 102 | --------------------------------------------------------------------------------