├── .gitattributes ├── .gitignore ├── .nuget ├── NuGet.Config ├── NuGet.exe └── NuGet.targets ├── CheckForDotNet45 ├── CheckForDotNet45.csproj ├── Program.cs ├── Properties │ └── AssemblyInfo.cs └── app.config ├── README.md ├── SmallestDotNet.sln ├── SmallestDotNet ├── Default.aspx ├── Default.aspx.cs ├── Default.aspx.designer.cs ├── Properties │ └── AssemblyInfo.cs ├── SmallestDotNet.csproj ├── VersionCheck.ashx ├── VersionCheck.ashx.cs ├── Web.Debug.config ├── Web.Release.config ├── Web.config ├── css │ ├── bootstrap-responsive.min.css │ ├── bootstrap.min.css │ ├── font-awesome-ie7.css │ ├── font-awesome.css │ ├── m-buttons.min.css │ └── main.css ├── font │ ├── fontawesome-webfont.eot │ ├── fontawesome-webfont.svg │ ├── fontawesome-webfont.ttf │ └── fontawesome-webfont.woff ├── img │ ├── glyphicons-halflings-white.png │ ├── glyphicons-halflings.png │ └── hero_home.jpg ├── javascript.ashx ├── javascriptdom.ashx ├── js │ ├── bootstrap.min.js │ └── jquery-1.8.1.min.js └── testjs.html ├── SmallestDotNetLib ├── BrowserSupport.cs ├── CLRVersion.cs ├── CLRVersions.cs ├── Constants.cs ├── Helpers.cs ├── JsonVersions.cs ├── OperatingSystemSupport.cs ├── Properties │ └── AssemblyInfo.cs ├── SmallestDotNetLib.csproj └── UpdateInformationResponse.cs ├── SmallestTest ├── CLRVersionDictionaryTests.cs ├── JavascriptDomTests.cs ├── OperatingSystemVersionTests.cs ├── Properties │ └── AssemblyInfo.cs ├── SmallestTest.csproj ├── VersionCheckTest.cs └── VersionWriterTests.cs └── license.txt /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | *.sln merge=union 7 | *.csproj merge=union 8 | *.vbproj merge=union 9 | *.fsproj merge=union 10 | *.dbproj merge=union 11 | 12 | # Standard to msysgit 13 | *.doc diff=astextplain 14 | *.DOC diff=astextplain 15 | *.docx diff=astextplain 16 | *.DOCX diff=astextplain 17 | *.dot diff=astextplain 18 | *.DOT diff=astextplain 19 | *.pdf diff=astextplain 20 | *.PDF diff=astextplain 21 | *.rtf diff=astextplain 22 | *.RTF diff=astextplain 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Build Folders (you can keep bin if you'd like, to store dlls and pdbs) 2 | bin 3 | obj 4 | 5 | #VSArtifacts 6 | *suo 7 | 8 | # mstest test results 9 | TestResults 10 | 11 | *suo 12 | *user 13 | 14 | [Pp]ackages 15 | 16 | # Visual Studio 2015/17 cache/options directory 17 | .vs/ -------------------------------------------------------------------------------- /.nuget/NuGet.Config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.nuget/NuGet.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shanselman/SmallestDotNet/8a60a223929137d036b0730f24b44c83ecb8cbe4/.nuget/NuGet.exe -------------------------------------------------------------------------------- /.nuget/NuGet.targets: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | $(MSBuildProjectDirectory)\..\ 5 | 6 | 7 | false 8 | 9 | 10 | false 11 | 12 | 13 | true 14 | 15 | 16 | false 17 | 18 | 19 | 20 | 21 | 25 | 26 | 27 | 28 | 29 | $([System.IO.Path]::Combine($(SolutionDir), ".nuget")) 30 | $([System.IO.Path]::Combine($(ProjectDir), "packages.config")) 31 | $([System.IO.Path]::Combine($(SolutionDir), "packages")) 32 | 33 | 34 | 35 | 36 | $(SolutionDir).nuget 37 | packages.config 38 | $(SolutionDir)packages 39 | 40 | 41 | 42 | 43 | $(NuGetToolsPath)\nuget.exe 44 | @(PackageSource) 45 | 46 | "$(NuGetExePath)" 47 | mono --runtime=v4.0.30319 $(NuGetExePath) 48 | 49 | $(TargetDir.Trim('\\')) 50 | 51 | -RequireConsent 52 | 53 | $(NuGetCommand) install "$(PackagesConfig)" -source "$(PackageSources)" $(RequireConsentSwitch) -o "$(PackagesDir)" 54 | $(NuGetCommand) pack "$(ProjectPath)" -p Configuration=$(Configuration) -o "$(PackageOutputDir)" -symbols 55 | 56 | 57 | 58 | RestorePackages; 59 | $(BuildDependsOn); 60 | 61 | 62 | 63 | 64 | $(BuildDependsOn); 65 | BuildPackage; 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 79 | 80 | 83 | 84 | 85 | 86 | 88 | 89 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 140 | 141 | 142 | 143 | -------------------------------------------------------------------------------- /CheckForDotNet45/CheckForDotNet45.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {2D8463F4-3C7A-42C8-9A2D-8F585460EE74} 8 | Exe 9 | Properties 10 | CheckForDotNet45 11 | CheckForDotNet45 12 | v4.0 13 | 512 14 | Client 15 | 16 | 17 | AnyCPU 18 | true 19 | full 20 | false 21 | bin\Debug\ 22 | DEBUG;TRACE 23 | prompt 24 | 4 25 | 26 | 27 | AnyCPU 28 | pdbonly 29 | true 30 | bin\Release\ 31 | TRACE 32 | prompt 33 | 4 34 | 35 | 36 | false 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 62 | -------------------------------------------------------------------------------- /CheckForDotNet45/Program.cs: -------------------------------------------------------------------------------- 1 | // ----------------------------------------------------------------------- 2 | // 3 | // Copyright © Scott Hanselman, Michael Sarchet and Friends 2012. All rights reserved. 4 | // 5 | // ----------------------------------------------------------------------- 6 | namespace CheckForDotNet45 7 | { 8 | using System; 9 | using System.Diagnostics; 10 | 11 | using Microsoft.Win32; 12 | 13 | /// 14 | /// Class containing all application logic 15 | /// 16 | public class Program 17 | { 18 | #region Fields 19 | 20 | /// Site URL with release key parameter 21 | private const string SiteWithReleaseKey = "https://smallestdotnet.com/?releaseKey={0}"; 22 | 23 | /// Site URL with version parameter 24 | private const string SiteWithVersion = "https://smallestdotnet.com/?realversion={0}"; 25 | 26 | #endregion Fields 27 | 28 | #region Methods 29 | 30 | /// 31 | /// Main entry point for program. 32 | /// 33 | public static void Main() 34 | { 35 | try 36 | { 37 | Console.Write("Checking .NET version..."); 38 | 39 | int releaseKey = 0; 40 | string version = null; 41 | if (IsNet45OrNewer()) 42 | { 43 | releaseKey = GetDotnetReleaseKeyFromRegistry(); 44 | } 45 | else 46 | { 47 | version = Environment.Version.ToString(); 48 | } 49 | 50 | string url = string.IsNullOrEmpty(version) 51 | ? string.Format(SiteWithReleaseKey, releaseKey) 52 | : string.Format(SiteWithVersion, version); 53 | try 54 | { 55 | Process.Start(url); 56 | } 57 | catch (Exception) 58 | { 59 | Console.WriteLine("\nApplication was unable to launch browser to go to {0}", url); 60 | if (version != null) 61 | { 62 | Console.WriteLine("Your current .NET version is: " + version); 63 | } 64 | else 65 | { 66 | Console.WriteLine("Please browse to the URL to get version information."); 67 | } 68 | 69 | Console.ReadLine(); // Pause 70 | } 71 | } 72 | catch (Exception ex) 73 | { 74 | Console.WriteLine("An error occurred:"); 75 | Console.ForegroundColor = ConsoleColor.Red; 76 | Console.WriteLine(ex.ToString()); 77 | Console.ResetColor(); 78 | Console.WriteLine("Please log an issue including the error information at https://github.com/shanselman/SmallestDotNet/issues/"); 79 | Console.ReadLine(); // Pause 80 | } 81 | } 82 | 83 | /// 84 | /// Gets the .Net release key from registry "SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full\". 85 | /// 86 | /// Release key or -1 if not found 87 | private static int GetDotnetReleaseKeyFromRegistry() 88 | { 89 | int releaseKey = -1; 90 | 91 | // Based on http://msdn.microsoft.com/en-us/library/hh925568%28v=vs.110%29.aspx#net_d 92 | using ( 93 | RegistryKey ndpKey = 94 | RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry32) 95 | .OpenSubKey(@"SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full\")) 96 | { 97 | if (ndpKey != null) 98 | { 99 | object releaseKeyValue = ndpKey.GetValue("Release") ?? "-1"; 100 | int.TryParse(releaseKeyValue.ToString(), out releaseKey); 101 | } 102 | 103 | return releaseKey; 104 | } 105 | } 106 | 107 | /// 108 | /// Determines whether we have .net 4.5 or newer. 109 | /// 110 | /// true if we have .net 4.5 or newer 111 | private static bool IsNet45OrNewer() 112 | { 113 | // Class "ReflectionContext" exists in .NET 4.5 . 114 | return Type.GetType("System.Reflection.ReflectionContext", false) != null; 115 | } 116 | 117 | #endregion Methods 118 | } 119 | } -------------------------------------------------------------------------------- /CheckForDotNet45/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | 4 | // General Information about an assembly is controlled through the following 5 | // set of attributes. Change these attribute values to modify the information 6 | // associated with an assembly. 7 | [assembly: AssemblyTitle("CheckForDotNet45")] 8 | [assembly: AssemblyDescription("")] 9 | [assembly: AssemblyConfiguration("")] 10 | [assembly: AssemblyCompany("")] 11 | [assembly: AssemblyProduct("CheckForDotNet45")] 12 | [assembly: AssemblyCopyright("Copyright © 2012")] 13 | [assembly: AssemblyTrademark("")] 14 | [assembly: AssemblyCulture("")] 15 | 16 | // Setting ComVisible to false makes the types in this assembly not visible 17 | // to COM components. If you need to access a type in this assembly from 18 | // COM, set the ComVisible attribute to true on that type. 19 | [assembly: ComVisible(false)] 20 | 21 | // The following GUID is for the ID of the typelib if this project is exposed to COM 22 | [assembly: Guid("19ff6b37-745e-4dec-826c-540d921e2acb")] 23 | 24 | // Version information for an assembly consists of the following four values: 25 | // 26 | // Major Version 27 | // Minor Version 28 | // Build Number 29 | // Revision 30 | // 31 | // You can specify all the values or you can default the Build and Revision Numbers 32 | // by using the '*' as shown below: 33 | // [assembly: AssemblyVersion("1.0.*")] 34 | [assembly: AssemblyVersion("1.0.0.0")] 35 | [assembly: AssemblyFileVersion("1.0.0.0")] 36 | -------------------------------------------------------------------------------- /CheckForDotNet45/app.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2Fshanselman%2FSmallestDotNet.svg?type=shield)](https://app.fossa.io/projects/git%2Bgithub.com%2Fshanselman%2FSmallestDotNet?ref=badge_shield) 2 | 3 | SmallestDotNet 4 | ============== 5 | 6 | SmallestDotNet - [SmallestDotNet.com](https://smallestdotnet.com) is a single page site that does one thing. It tells you the smallest, easiest download you'd need to get the .NET Framework on your system. 7 | 8 | The code sucks. I did it in an hour and I'm sad. 9 | 10 | Thanks to Calin Balauru for his help. Anything good here is him. All the bad is me. 11 | 12 | 13 | ## License 14 | [![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2Fshanselman%2FSmallestDotNet.svg?type=large)](https://app.fossa.io/projects/git%2Bgithub.com%2Fshanselman%2FSmallestDotNet?ref=badge_large) -------------------------------------------------------------------------------- /SmallestDotNet.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 2012 4 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SmallestDotNet", "SmallestDotNet\SmallestDotNet.csproj", "{F80F0719-0AC1-4B4D-9F44-7D78C90FAEE3}" 5 | EndProject 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SmallestDotNetLib", "SmallestDotNetLib\SmallestDotNetLib.csproj", "{3ECC85DC-EBC0-4A2E-930D-711ABC481388}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CheckForDotNet45", "CheckForDotNet45\CheckForDotNet45.csproj", "{2D8463F4-3C7A-42C8-9A2D-8F585460EE74}" 9 | EndProject 10 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SmallestTest", "SmallestTest\SmallestTest.csproj", "{21BD13C9-725E-447D-8CF9-07E8CBE797B1}" 11 | EndProject 12 | Global 13 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 14 | Debug|Any CPU = Debug|Any CPU 15 | Release|Any CPU = Release|Any CPU 16 | EndGlobalSection 17 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 18 | {F80F0719-0AC1-4B4D-9F44-7D78C90FAEE3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 19 | {F80F0719-0AC1-4B4D-9F44-7D78C90FAEE3}.Debug|Any CPU.Build.0 = Debug|Any CPU 20 | {F80F0719-0AC1-4B4D-9F44-7D78C90FAEE3}.Release|Any CPU.ActiveCfg = Release|Any CPU 21 | {F80F0719-0AC1-4B4D-9F44-7D78C90FAEE3}.Release|Any CPU.Build.0 = Release|Any CPU 22 | {3ECC85DC-EBC0-4A2E-930D-711ABC481388}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 23 | {3ECC85DC-EBC0-4A2E-930D-711ABC481388}.Debug|Any CPU.Build.0 = Debug|Any CPU 24 | {3ECC85DC-EBC0-4A2E-930D-711ABC481388}.Release|Any CPU.ActiveCfg = Release|Any CPU 25 | {3ECC85DC-EBC0-4A2E-930D-711ABC481388}.Release|Any CPU.Build.0 = Release|Any CPU 26 | {2D8463F4-3C7A-42C8-9A2D-8F585460EE74}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 27 | {2D8463F4-3C7A-42C8-9A2D-8F585460EE74}.Debug|Any CPU.Build.0 = Debug|Any CPU 28 | {2D8463F4-3C7A-42C8-9A2D-8F585460EE74}.Release|Any CPU.ActiveCfg = Release|Any CPU 29 | {2D8463F4-3C7A-42C8-9A2D-8F585460EE74}.Release|Any CPU.Build.0 = Release|Any CPU 30 | {21BD13C9-725E-447D-8CF9-07E8CBE797B1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 31 | {21BD13C9-725E-447D-8CF9-07E8CBE797B1}.Debug|Any CPU.Build.0 = Debug|Any CPU 32 | {21BD13C9-725E-447D-8CF9-07E8CBE797B1}.Release|Any CPU.ActiveCfg = Release|Any CPU 33 | {21BD13C9-725E-447D-8CF9-07E8CBE797B1}.Release|Any CPU.Build.0 = Release|Any CPU 34 | EndGlobalSection 35 | GlobalSection(SolutionProperties) = preSolution 36 | HideSolutionNode = FALSE 37 | EndGlobalSection 38 | EndGlobal 39 | -------------------------------------------------------------------------------- /SmallestDotNet/Default.aspx: -------------------------------------------------------------------------------- 1 | <%@ Page Language="C#" AutoEventWireup="true" Inherits="_Default" CodeBehind="Default.aspx.cs" %> 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | Get the .NET Framework Fast - Download the smallest .NET Framework Distribution possible 19 | 20 | 21 | 37 | 38 | 39 | 40 | 60 | 61 |
62 | 63 |
64 |
65 |
66 |

Do you have .NET?

67 |

68 | 69 |

70 |
71 | Get .NET 72 | 73 | .NET Checker 74 | 75 |
76 |
77 |
78 | 79 |
80 |
81 |

What about .NET 4.5 or later?

82 | 83 | Download this application .NET Checker and run it. 84 | This harmless code signed application will tell us if you have .NET 4.5, 4.6, 4.7 or 4.8 (including minor versions). Don't trust us? Here's the code. 85 |
86 |
87 | 88 |
89 |
90 |

What happened

91 | This site looked at your browser's "UserAgent" and figured out what version (if any) of the .NET Framework you have (or don't have) installed, then calculated the total size if you chose to download the .NET Framework. 92 |
93 |
94 | There's no database, no cookies, and nothing about your computer has been stored or kept. We just look at the information your browser already reports about your computer and make a suggestion as to the best .NET Framework download for you. 95 |
96 |
97 |
98 |
99 |

Offline Download

100 | 101 |

Online Download

102 | 103 |
104 |
105 |
106 |
107 |

Are you a .NET Programmer?

108 | If you're a programmer/developer, you might be trying to figure out which .NET Framework for your users to use. 109 |
110 |
111 | Sometimes finding the right .NET Framework is confusing because different kinds of machines (x86, x64, ia64) that may or may not have different versions of .NET already on them. 112 |
113 |
114 | If you look for .NET Downloads on Microsoft's site, it might look like the .NET Framework is 200+ megs. It's not. Those big downloads are the Complete Offline Versions of every version of the .NET Framework for every kind of machine possible. The big .NET download includes x86, x64, and ia64. It includes .NET 2.0, 3.0, and 3.5 code for all systems all in one super-archive. The downloads for .NET 4.5, 4.6, 4.7 and 4.8 are even smaller. 115 |
116 |
117 | Why would you EVER want to download the whole archive? Only if you're a developer and you want to distribute the .NET Framework the widest possible audience in a format like a CD or DVD. 118 |
119 |
120 |

Your User Agent

121 | For technical or debugging purposes, this is exactly what your browser said about itself: 122 |
123 |
124 |
125 |
126 | 127 |
128 |
129 |

Integration

130 | Want SmallestDotNet functionality for your own site? Add this chunk of JavaScript, it'll spit out HTML and you can style to taste. 131 |
132 |
<script type="text/javascript" src="https://www.smallestdotnet.com/javascript.ashx"></script>
133 | 134 |
135 |
136 |
137 |
138 | Prefer a JavaScript Object (JSON) to detect .NET Framework installations? Try this instead: 139 |
140 |
<script type="text/javascript" src="https://www.smallestdotnet.com/javascriptdom.ashx"></script>
141 | Get examples on how to use the JSON object on Scott's Blog. 142 | 143 | 144 |
145 |
146 | 147 | 148 |
149 |
150 | 155 |
156 |
157 |
158 | 159 | 160 | 161 | 164 | 165 | 166 | 186 | 187 | 198 | 199 | 200 | -------------------------------------------------------------------------------- /SmallestDotNet/Default.aspx.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Web; 3 | 4 | using SmallestDotNetLib; 5 | 6 | public partial class _Default : System.Web.UI.Page 7 | { 8 | protected void Page_Load(object sender, EventArgs e) 9 | { 10 | string realVersion = null; 11 | int releaseKey = 0; 12 | bool runFromChecker = false; 13 | string userAgentText = this.Request.UserAgent ?? string.Empty; 14 | 15 | // set the Get.NET link button to the latest offline version 16 | getdotnet.HRef = HttpUtility.HtmlEncode(Constants.LatestDotNetRawUrl); 17 | getdotnet.Target = "_blank"; 18 | 19 | userAgent.Text = HttpUtility.HtmlEncode(userAgentText); 20 | 21 | if (Request.QueryString["realversion"] != null || this.Request.QueryString["releaseKey"] != null) 22 | { 23 | realVersion = this.Request.QueryString["realversion"]; 24 | int.TryParse(this.Request.QueryString["releaseKey"], out releaseKey); 25 | runFromChecker = true; 26 | } 27 | 28 | 29 | UpdateInformationResponse response = Helpers.GetUpdateInformation(userAgentText, realVersion, releaseKey); 30 | 31 | userResult.Text = response.Text; 32 | developerOnline.Text = String.Format(@"If your users have internet connectivity, the .NET Framework is only between {1} and {2} megs. Why such a wide range? Well, it depends on if they already have some version of .NET. 33 | If you point your users to the online setup for the {0}, that {3} MB download will automatically detect and download the smallest archive possible to get the job done.", Constants.DotNetOnline, Constants.DotNetOfflineMB - Constants.Version3OfflineMB, Constants.DotNetOfflineMB, Constants.DotNetOnlineMB); 34 | 35 | developerOfflineResult.Text = String.Format(@"If you are a developer and are distributing your code on CD or DVD, you might want to download the 36 | {0} on your media. The download is about {1} MB", Constants.DotNetOffline, Constants.DotNetOfflineMB); 37 | getdotnet.Visible = response.VersionCanBeDetermined; 38 | 39 | if (response.VersionIsLatest) 40 | getdotnet.Visible = false; 41 | 42 | checkdotnet.Visible = response.CanRunCheckApp; 43 | 44 | // Hide the 4.5 checker section if 45 | // (a) we can't determine the dotnet version or 46 | // (b) we're on an OS that doesn't support .Net or 47 | // (c) the user has already run the checker so we know exactly what version they're on. 48 | // Note that the checkdotnet section in the header will still be displayed as long as the OS supports it 49 | dotnet45.Visible = response.VersionCanBeDetermined && response.CanRunCheckApp && !runFromChecker; 50 | } 51 | 52 | } 53 | -------------------------------------------------------------------------------- /SmallestDotNet/Default.aspx.designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // 5 | // Changes to this file may cause incorrect behavior and will be lost if 6 | // the code is regenerated. 7 | // 8 | //------------------------------------------------------------------------------ 9 | 10 | 11 | 12 | public partial class _Default { 13 | 14 | /// 15 | /// userResult control. 16 | /// 17 | /// 18 | /// Auto-generated field. 19 | /// To modify move field declaration from designer file to code-behind file. 20 | /// 21 | protected global::System.Web.UI.WebControls.Literal userResult; 22 | 23 | /// 24 | /// getdotnet control. 25 | /// 26 | /// 27 | /// Auto-generated field. 28 | /// To modify move field declaration from designer file to code-behind file. 29 | /// 30 | protected global::System.Web.UI.HtmlControls.HtmlAnchor getdotnet; 31 | 32 | /// 33 | /// checkdotnet control. 34 | /// 35 | /// 36 | /// Auto-generated field. 37 | /// To modify move field declaration from designer file to code-behind file. 38 | /// 39 | protected global::System.Web.UI.HtmlControls.HtmlAnchor checkdotnet; 40 | 41 | /// 42 | /// dotnet45 control. 43 | /// 44 | /// 45 | /// Auto-generated field. 46 | /// To modify move field declaration from designer file to code-behind file. 47 | /// 48 | protected global::System.Web.UI.HtmlControls.HtmlGenericControl dotnet45; 49 | 50 | /// 51 | /// developerOfflineResult control. 52 | /// 53 | /// 54 | /// Auto-generated field. 55 | /// To modify move field declaration from designer file to code-behind file. 56 | /// 57 | protected global::System.Web.UI.WebControls.Literal developerOfflineResult; 58 | 59 | /// 60 | /// developerOnline control. 61 | /// 62 | /// 63 | /// Auto-generated field. 64 | /// To modify move field declaration from designer file to code-behind file. 65 | /// 66 | protected global::System.Web.UI.WebControls.Literal developerOnline; 67 | 68 | /// 69 | /// userAgent control. 70 | /// 71 | /// 72 | /// Auto-generated field. 73 | /// To modify move field declaration from designer file to code-behind file. 74 | /// 75 | protected global::System.Web.UI.WebControls.Literal userAgent; 76 | } 77 | -------------------------------------------------------------------------------- /SmallestDotNet/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | 4 | // General Information about an assembly is controlled through the following 5 | // set of attributes. Change these attribute values to modify the information 6 | // associated with an assembly. 7 | [assembly: AssemblyTitle("SmallestDotNet")] 8 | [assembly: AssemblyDescription("")] 9 | [assembly: AssemblyConfiguration("")] 10 | [assembly: AssemblyCompany("")] 11 | [assembly: AssemblyProduct("SmallestDotNet")] 12 | [assembly: AssemblyCopyright("Copyright © 2012")] 13 | [assembly: AssemblyTrademark("")] 14 | [assembly: AssemblyCulture("")] 15 | 16 | // Setting ComVisible to false makes the types in this assembly not visible 17 | // to COM components. If you need to access a type in this assembly from 18 | // COM, set the ComVisible attribute to true on that type. 19 | [assembly: ComVisible(false)] 20 | 21 | // The following GUID is for the ID of the typelib if this project is exposed to COM 22 | [assembly: Guid("e6cfcac0-158c-48ba-bf1f-71b0c81cc456")] 23 | 24 | // Version information for an assembly consists of the following four values: 25 | // 26 | // Major Version 27 | // Minor Version 28 | // Build Number 29 | // Revision 30 | // 31 | // You can specify all the values or you can default the Revision and Build Numbers 32 | // by using the '*' as shown below: 33 | [assembly: AssemblyVersion("1.0.0.0")] 34 | [assembly: AssemblyFileVersion("1.0.0.0")] 35 | -------------------------------------------------------------------------------- /SmallestDotNet/SmallestDotNet.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | 8 | 9 | 2.0 10 | {F80F0719-0AC1-4B4D-9F44-7D78C90FAEE3} 11 | {349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc} 12 | Library 13 | Properties 14 | SmallestDotNet 15 | SmallestDotNet 16 | v4.5 17 | true 18 | 19 | 20 | 21 | 22 | 23 | 24 | true 25 | full 26 | false 27 | bin\ 28 | DEBUG;TRACE 29 | prompt 30 | 4 31 | false 32 | 33 | 34 | pdbonly 35 | true 36 | bin\ 37 | TRACE 38 | prompt 39 | 4 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 | 71 | 72 | 73 | 74 | 75 | 76 | Designer 77 | 78 | 79 | 80 | 81 | Default.aspx 82 | 83 | 84 | Default.aspx 85 | ASPXCodeBehind 86 | 87 | 88 | 89 | VersionCheck.ashx 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | Web.config 101 | 102 | 103 | Web.config 104 | 105 | 106 | 107 | 108 | {3ecc85dc-ebc0-4a2e-930d-711abc481388} 109 | SmallestDotNetLib 110 | 111 | 112 | 113 | 10.0 114 | $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | True 124 | True 125 | 0 126 | / 127 | http://localhost:57099/ 128 | False 129 | False 130 | 131 | 132 | False 133 | 134 | 135 | 136 | 137 | 144 | -------------------------------------------------------------------------------- /SmallestDotNet/VersionCheck.ashx: -------------------------------------------------------------------------------- 1 | <%@ WebHandler Language="C#" CodeBehind="VersionCheck.ashx.cs" Class="SmallestDotNet.VersionCheck" %> 2 | -------------------------------------------------------------------------------- /SmallestDotNet/VersionCheck.ashx.cs: -------------------------------------------------------------------------------- 1 | using System.Web; 2 | 3 | namespace SmallestDotNet 4 | { 5 | /// 6 | /// Summary description for VersionCheck 7 | /// 8 | public class VersionCheck : IHttpHandler 9 | { 10 | 11 | public void ProcessRequest(HttpContext context) 12 | { 13 | if (context.Request.RequestType == "GET") 14 | { 15 | var userAgent = context.Request["userAgent"]; 16 | context.Response.ContentType = "text/plain"; 17 | context.Response.Write(Helpers.GetUpdateInformation(userAgent).Text); 18 | } 19 | } 20 | 21 | public bool IsReusable 22 | { 23 | get 24 | { 25 | return false; 26 | } 27 | } 28 | } 29 | } -------------------------------------------------------------------------------- /SmallestDotNet/Web.Debug.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 17 | 18 | 29 | 30 | -------------------------------------------------------------------------------- /SmallestDotNet/Web.Release.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 17 | 18 | 19 | 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 | -------------------------------------------------------------------------------- /SmallestDotNet/Web.config: -------------------------------------------------------------------------------- 1 |  2 | 10 | 11 | 12 | 13 | 14 | 20 | 21 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /SmallestDotNet/css/bootstrap-responsive.min.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap Responsive v2.1.1 3 | * 4 | * Copyright 2012 Twitter, Inc 5 | * Licensed under the Apache License v2.0 6 | * http://www.apache.org/licenses/LICENSE-2.0 7 | * 8 | * Designed and built with all the love in the world @twitter by @mdo and @fat. 9 | */.clearfix{*zoom:1}.clearfix:before,.clearfix:after{display:table;line-height:0;content:""}.clearfix:after{clear:both}.hide-text{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.input-block-level{display:block;width:100%;min-height:30px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.hidden{display:none;visibility:hidden}.visible-phone{display:none!important}.visible-tablet{display:none!important}.hidden-desktop{display:none!important}.visible-desktop{display:inherit!important}@media(min-width:768px) and (max-width:979px){.hidden-desktop{display:inherit!important}.visible-desktop{display:none!important}.visible-tablet{display:inherit!important}.hidden-tablet{display:none!important}}@media(max-width:767px){.hidden-desktop{display:inherit!important}.visible-desktop{display:none!important}.visible-phone{display:inherit!important}.hidden-phone{display:none!important}}@media(min-width:1200px){.row{margin-left:-30px;*zoom:1}.row:before,.row:after{display:table;line-height:0;content:""}.row:after{clear:both}[class*="span"]{float:left;min-height:1px;margin-left:30px}.container,.navbar-static-top .container,.navbar-fixed-top .container,.navbar-fixed-bottom .container{width:1170px}.span12{width:1170px}.span11{width:1070px}.span10{width:970px}.span9{width:870px}.span8{width:770px}.span7{width:670px}.span6{width:570px}.span5{width:470px}.span4{width:370px}.span3{width:270px}.span2{width:170px}.span1{width:70px}.offset12{margin-left:1230px}.offset11{margin-left:1130px}.offset10{margin-left:1030px}.offset9{margin-left:930px}.offset8{margin-left:830px}.offset7{margin-left:730px}.offset6{margin-left:630px}.offset5{margin-left:530px}.offset4{margin-left:430px}.offset3{margin-left:330px}.offset2{margin-left:230px}.offset1{margin-left:130px}.row-fluid{width:100%;*zoom:1}.row-fluid:before,.row-fluid:after{display:table;line-height:0;content:""}.row-fluid:after{clear:both}.row-fluid [class*="span"]{display:block;float:left;width:100%;min-height:30px;margin-left:2.564102564102564%;*margin-left:2.5109110747408616%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.row-fluid [class*="span"]:first-child{margin-left:0}.row-fluid .span12{width:100%;*width:99.94680851063829%}.row-fluid .span11{width:91.45299145299145%;*width:91.39979996362975%}.row-fluid .span10{width:82.90598290598291%;*width:82.8527914166212%}.row-fluid .span9{width:74.35897435897436%;*width:74.30578286961266%}.row-fluid .span8{width:65.81196581196582%;*width:65.75877432260411%}.row-fluid .span7{width:57.26495726495726%;*width:57.21176577559556%}.row-fluid .span6{width:48.717948717948715%;*width:48.664757228587014%}.row-fluid .span5{width:40.17094017094017%;*width:40.11774868157847%}.row-fluid .span4{width:31.623931623931625%;*width:31.570740134569924%}.row-fluid .span3{width:23.076923076923077%;*width:23.023731587561375%}.row-fluid .span2{width:14.52991452991453%;*width:14.476723040552828%}.row-fluid .span1{width:5.982905982905983%;*width:5.929714493544281%}.row-fluid .offset12{margin-left:105.12820512820512%;*margin-left:105.02182214948171%}.row-fluid .offset12:first-child{margin-left:102.56410256410257%;*margin-left:102.45771958537915%}.row-fluid .offset11{margin-left:96.58119658119658%;*margin-left:96.47481360247316%}.row-fluid .offset11:first-child{margin-left:94.01709401709402%;*margin-left:93.91071103837061%}.row-fluid .offset10{margin-left:88.03418803418803%;*margin-left:87.92780505546462%}.row-fluid .offset10:first-child{margin-left:85.47008547008548%;*margin-left:85.36370249136206%}.row-fluid .offset9{margin-left:79.48717948717949%;*margin-left:79.38079650845607%}.row-fluid .offset9:first-child{margin-left:76.92307692307693%;*margin-left:76.81669394435352%}.row-fluid .offset8{margin-left:70.94017094017094%;*margin-left:70.83378796144753%}.row-fluid .offset8:first-child{margin-left:68.37606837606839%;*margin-left:68.26968539734497%}.row-fluid .offset7{margin-left:62.393162393162385%;*margin-left:62.28677941443899%}.row-fluid .offset7:first-child{margin-left:59.82905982905982%;*margin-left:59.72267685033642%}.row-fluid .offset6{margin-left:53.84615384615384%;*margin-left:53.739770867430444%}.row-fluid .offset6:first-child{margin-left:51.28205128205128%;*margin-left:51.175668303327875%}.row-fluid .offset5{margin-left:45.299145299145295%;*margin-left:45.1927623204219%}.row-fluid .offset5:first-child{margin-left:42.73504273504273%;*margin-left:42.62865975631933%}.row-fluid .offset4{margin-left:36.75213675213675%;*margin-left:36.645753773413354%}.row-fluid .offset4:first-child{margin-left:34.18803418803419%;*margin-left:34.081651209310785%}.row-fluid .offset3{margin-left:28.205128205128204%;*margin-left:28.0987452264048%}.row-fluid .offset3:first-child{margin-left:25.641025641025642%;*margin-left:25.53464266230224%}.row-fluid .offset2{margin-left:19.65811965811966%;*margin-left:19.551736679396257%}.row-fluid .offset2:first-child{margin-left:17.094017094017094%;*margin-left:16.98763411529369%}.row-fluid .offset1{margin-left:11.11111111111111%;*margin-left:11.004728132387708%}.row-fluid .offset1:first-child{margin-left:8.547008547008547%;*margin-left:8.440625568285142%}input,textarea,.uneditable-input{margin-left:0}.controls-row [class*="span"]+[class*="span"]{margin-left:30px}input.span12,textarea.span12,.uneditable-input.span12{width:1156px}input.span11,textarea.span11,.uneditable-input.span11{width:1056px}input.span10,textarea.span10,.uneditable-input.span10{width:956px}input.span9,textarea.span9,.uneditable-input.span9{width:856px}input.span8,textarea.span8,.uneditable-input.span8{width:756px}input.span7,textarea.span7,.uneditable-input.span7{width:656px}input.span6,textarea.span6,.uneditable-input.span6{width:556px}input.span5,textarea.span5,.uneditable-input.span5{width:456px}input.span4,textarea.span4,.uneditable-input.span4{width:356px}input.span3,textarea.span3,.uneditable-input.span3{width:256px}input.span2,textarea.span2,.uneditable-input.span2{width:156px}input.span1,textarea.span1,.uneditable-input.span1{width:56px}.thumbnails{margin-left:-30px}.thumbnails>li{margin-left:30px}.row-fluid .thumbnails{margin-left:0}}@media(min-width:768px) and (max-width:979px){.row{margin-left:-20px;*zoom:1}.row:before,.row:after{display:table;line-height:0;content:""}.row:after{clear:both}[class*="span"]{float:left;min-height:1px;margin-left:20px}.container,.navbar-static-top .container,.navbar-fixed-top .container,.navbar-fixed-bottom .container{width:724px}.span12{width:724px}.span11{width:662px}.span10{width:600px}.span9{width:538px}.span8{width:476px}.span7{width:414px}.span6{width:352px}.span5{width:290px}.span4{width:228px}.span3{width:166px}.span2{width:104px}.span1{width:42px}.offset12{margin-left:764px}.offset11{margin-left:702px}.offset10{margin-left:640px}.offset9{margin-left:578px}.offset8{margin-left:516px}.offset7{margin-left:454px}.offset6{margin-left:392px}.offset5{margin-left:330px}.offset4{margin-left:268px}.offset3{margin-left:206px}.offset2{margin-left:144px}.offset1{margin-left:82px}.row-fluid{width:100%;*zoom:1}.row-fluid:before,.row-fluid:after{display:table;line-height:0;content:""}.row-fluid:after{clear:both}.row-fluid [class*="span"]{display:block;float:left;width:100%;min-height:30px;margin-left:2.7624309392265194%;*margin-left:2.709239449864817%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.row-fluid [class*="span"]:first-child{margin-left:0}.row-fluid .span12{width:100%;*width:99.94680851063829%}.row-fluid .span11{width:91.43646408839778%;*width:91.38327259903608%}.row-fluid .span10{width:82.87292817679558%;*width:82.81973668743387%}.row-fluid .span9{width:74.30939226519337%;*width:74.25620077583166%}.row-fluid .span8{width:65.74585635359117%;*width:65.69266486422946%}.row-fluid .span7{width:57.18232044198895%;*width:57.12912895262725%}.row-fluid .span6{width:48.61878453038674%;*width:48.56559304102504%}.row-fluid .span5{width:40.05524861878453%;*width:40.00205712942283%}.row-fluid .span4{width:31.491712707182323%;*width:31.43852121782062%}.row-fluid .span3{width:22.92817679558011%;*width:22.87498530621841%}.row-fluid .span2{width:14.3646408839779%;*width:14.311449394616199%}.row-fluid .span1{width:5.801104972375691%;*width:5.747913483013988%}.row-fluid .offset12{margin-left:105.52486187845304%;*margin-left:105.41847889972962%}.row-fluid .offset12:first-child{margin-left:102.76243093922652%;*margin-left:102.6560479605031%}.row-fluid .offset11{margin-left:96.96132596685082%;*margin-left:96.8549429881274%}.row-fluid .offset11:first-child{margin-left:94.1988950276243%;*margin-left:94.09251204890089%}.row-fluid .offset10{margin-left:88.39779005524862%;*margin-left:88.2914070765252%}.row-fluid .offset10:first-child{margin-left:85.6353591160221%;*margin-left:85.52897613729868%}.row-fluid .offset9{margin-left:79.8342541436464%;*margin-left:79.72787116492299%}.row-fluid .offset9:first-child{margin-left:77.07182320441989%;*margin-left:76.96544022569647%}.row-fluid .offset8{margin-left:71.2707182320442%;*margin-left:71.16433525332079%}.row-fluid .offset8:first-child{margin-left:68.50828729281768%;*margin-left:68.40190431409427%}.row-fluid .offset7{margin-left:62.70718232044199%;*margin-left:62.600799341718584%}.row-fluid .offset7:first-child{margin-left:59.94475138121547%;*margin-left:59.838368402492065%}.row-fluid .offset6{margin-left:54.14364640883978%;*margin-left:54.037263430116376%}.row-fluid .offset6:first-child{margin-left:51.38121546961326%;*margin-left:51.27483249088986%}.row-fluid .offset5{margin-left:45.58011049723757%;*margin-left:45.47372751851417%}.row-fluid .offset5:first-child{margin-left:42.81767955801105%;*margin-left:42.71129657928765%}.row-fluid .offset4{margin-left:37.01657458563536%;*margin-left:36.91019160691196%}.row-fluid .offset4:first-child{margin-left:34.25414364640884%;*margin-left:34.14776066768544%}.row-fluid .offset3{margin-left:28.45303867403315%;*margin-left:28.346655695309746%}.row-fluid .offset3:first-child{margin-left:25.69060773480663%;*margin-left:25.584224756083227%}.row-fluid .offset2{margin-left:19.88950276243094%;*margin-left:19.783119783707537%}.row-fluid .offset2:first-child{margin-left:17.12707182320442%;*margin-left:17.02068884448102%}.row-fluid .offset1{margin-left:11.32596685082873%;*margin-left:11.219583872105325%}.row-fluid .offset1:first-child{margin-left:8.56353591160221%;*margin-left:8.457152932878806%}input,textarea,.uneditable-input{margin-left:0}.controls-row [class*="span"]+[class*="span"]{margin-left:20px}input.span12,textarea.span12,.uneditable-input.span12{width:710px}input.span11,textarea.span11,.uneditable-input.span11{width:648px}input.span10,textarea.span10,.uneditable-input.span10{width:586px}input.span9,textarea.span9,.uneditable-input.span9{width:524px}input.span8,textarea.span8,.uneditable-input.span8{width:462px}input.span7,textarea.span7,.uneditable-input.span7{width:400px}input.span6,textarea.span6,.uneditable-input.span6{width:338px}input.span5,textarea.span5,.uneditable-input.span5{width:276px}input.span4,textarea.span4,.uneditable-input.span4{width:214px}input.span3,textarea.span3,.uneditable-input.span3{width:152px}input.span2,textarea.span2,.uneditable-input.span2{width:90px}input.span1,textarea.span1,.uneditable-input.span1{width:28px}}@media(max-width:767px){body{padding-right:20px;padding-left:20px}.navbar-fixed-top,.navbar-fixed-bottom,.navbar-static-top{margin-right:-20px;margin-left:-20px}.container-fluid{padding:0}.dl-horizontal dt{float:none;width:auto;clear:none;text-align:left}.dl-horizontal dd{margin-left:0}.container{width:auto}.row-fluid{width:100%}.row,.thumbnails{margin-left:0}.thumbnails>li{float:none;margin-left:0}[class*="span"],.row-fluid [class*="span"]{display:block;float:none;width:100%;margin-left:0;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.span12,.row-fluid .span12{width:100%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.input-large,.input-xlarge,.input-xxlarge,input[class*="span"],select[class*="span"],textarea[class*="span"],.uneditable-input{display:block;width:100%;min-height:30px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.input-prepend input,.input-append input,.input-prepend input[class*="span"],.input-append input[class*="span"]{display:inline-block;width:auto}.controls-row [class*="span"]+[class*="span"]{margin-left:0}.modal{position:fixed;top:20px;right:20px;left:20px;width:auto;margin:0}.modal.fade.in{top:auto}}@media(max-width:480px){.nav-collapse{-webkit-transform:translate3d(0,0,0)}.page-header h1 small{display:block;line-height:20px}input[type="checkbox"],input[type="radio"]{border:1px solid #ccc}.form-horizontal .control-label{float:none;width:auto;padding-top:0;text-align:left}.form-horizontal .controls{margin-left:0}.form-horizontal .control-list{padding-top:0}.form-horizontal .form-actions{padding-right:10px;padding-left:10px}.modal{top:10px;right:10px;left:10px}.modal-header .close{padding:10px;margin:-10px}.carousel-caption{position:static}}@media(max-width:979px){body{padding-top:0}.navbar-fixed-top,.navbar-fixed-bottom{position:static}.navbar-fixed-top{margin-bottom:20px}.navbar-fixed-bottom{margin-top:20px}.navbar-fixed-top .navbar-inner,.navbar-fixed-bottom .navbar-inner{padding:5px}.navbar .container{width:auto;padding:0}.navbar .brand{padding-right:10px;padding-left:10px;margin:0 0 0 -5px}.nav-collapse{clear:both}.nav-collapse .nav{float:none;margin:0 0 10px}.nav-collapse .nav>li{float:none}.nav-collapse .nav>li>a{margin-bottom:2px}.nav-collapse .nav>.divider-vertical{display:none}.nav-collapse .nav .nav-header{color:#777;text-shadow:none}.nav-collapse .nav>li>a,.nav-collapse .dropdown-menu a{padding:9px 15px;font-weight:bold;color:#777;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.nav-collapse .btn{padding:4px 10px 4px;font-weight:normal;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.nav-collapse .dropdown-menu li+li a{margin-bottom:2px}.nav-collapse .nav>li>a:hover,.nav-collapse .dropdown-menu a:hover{background-color:#f2f2f2}.navbar-inverse .nav-collapse .nav>li>a:hover,.navbar-inverse .nav-collapse .dropdown-menu a:hover{background-color:#111}.nav-collapse.in .btn-group{padding:0;margin-top:5px}.nav-collapse .dropdown-menu{position:static;top:auto;left:auto;display:block;float:none;max-width:none;padding:0;margin:0 15px;background-color:transparent;border:0;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none}.nav-collapse .dropdown-menu:before,.nav-collapse .dropdown-menu:after{display:none}.nav-collapse .dropdown-menu .divider{display:none}.nav-collapse .nav>li>.dropdown-menu:before,.nav-collapse .nav>li>.dropdown-menu:after{display:none}.nav-collapse .navbar-form,.nav-collapse .navbar-search{float:none;padding:10px 15px;margin:10px 0;border-top:1px solid #f2f2f2;border-bottom:1px solid #f2f2f2;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.1);-moz-box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.1);box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.1)}.navbar-inverse .nav-collapse .navbar-form,.navbar-inverse .nav-collapse .navbar-search{border-top-color:#111;border-bottom-color:#111}.navbar .nav-collapse .nav.pull-right{float:none;margin-left:0}.nav-collapse,.nav-collapse.collapse{height:0;overflow:hidden}.navbar .btn-navbar{display:block}.navbar-static .navbar-inner{padding-right:10px;padding-left:10px}}@media(min-width:980px){.nav-collapse.collapse{height:auto!important;overflow:visible!important}} 10 | -------------------------------------------------------------------------------- /SmallestDotNet/css/font-awesome-ie7.css: -------------------------------------------------------------------------------- 1 | [class^="icon-"], 2 | [class*=" icon-"] { 3 | font-family: FontAwesome; 4 | font-style: normal; 5 | font-weight: normal; 6 | } 7 | .btn.dropdown-toggle [class^="icon-"], 8 | .btn.dropdown-toggle [class*=" icon-"] { 9 | /* keeps button heights with and without icons the same */ 10 | 11 | line-height: 1.4em; 12 | } 13 | .icon-large { 14 | font-size: 1.3333em; 15 | } 16 | .icon-glass { 17 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 18 | } 19 | .icon-music { 20 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 21 | } 22 | .icon-search { 23 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 24 | } 25 | .icon-envelope { 26 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 27 | } 28 | .icon-heart { 29 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 30 | } 31 | .icon-star { 32 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 33 | } 34 | .icon-star-empty { 35 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 36 | } 37 | .icon-user { 38 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 39 | } 40 | .icon-film { 41 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 42 | } 43 | .icon-th-large { 44 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 45 | } 46 | .icon-th { 47 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 48 | } 49 | .icon-th-list { 50 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 51 | } 52 | .icon-ok { 53 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 54 | } 55 | .icon-remove { 56 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 57 | } 58 | .icon-zoom-in { 59 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 60 | } 61 | .icon-zoom-out { 62 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 63 | } 64 | .icon-off { 65 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 66 | } 67 | .icon-signal { 68 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 69 | } 70 | .icon-cog { 71 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 72 | } 73 | .icon-trash { 74 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 75 | } 76 | .icon-home { 77 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 78 | } 79 | .icon-file { 80 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 81 | } 82 | .icon-time { 83 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 84 | } 85 | .icon-road { 86 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 87 | } 88 | .icon-download-alt { 89 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 90 | } 91 | .icon-download { 92 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 93 | } 94 | .icon-upload { 95 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 96 | } 97 | .icon-inbox { 98 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 99 | } 100 | .icon-play-circle { 101 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 102 | } 103 | .icon-repeat { 104 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 105 | } 106 | .icon-refresh { 107 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 108 | } 109 | .icon-list-alt { 110 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 111 | } 112 | .icon-lock { 113 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 114 | } 115 | .icon-flag { 116 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 117 | } 118 | .icon-headphones { 119 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 120 | } 121 | .icon-volume-off { 122 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 123 | } 124 | .icon-volume-down { 125 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 126 | } 127 | .icon-volume-up { 128 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 129 | } 130 | .icon-qrcode { 131 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 132 | } 133 | .icon-barcode { 134 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 135 | } 136 | .icon-tag { 137 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 138 | } 139 | .icon-tags { 140 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 141 | } 142 | .icon-book { 143 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 144 | } 145 | .icon-bookmark { 146 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 147 | } 148 | .icon-print { 149 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 150 | } 151 | .icon-camera { 152 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 153 | } 154 | .icon-font { 155 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 156 | } 157 | .icon-bold { 158 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 159 | } 160 | .icon-italic { 161 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 162 | } 163 | .icon-text-height { 164 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 165 | } 166 | .icon-text-width { 167 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 168 | } 169 | .icon-align-left { 170 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 171 | } 172 | .icon-align-center { 173 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 174 | } 175 | .icon-align-right { 176 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 177 | } 178 | .icon-align-justify { 179 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 180 | } 181 | .icon-list { 182 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 183 | } 184 | .icon-indent-left { 185 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 186 | } 187 | .icon-indent-right { 188 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 189 | } 190 | .icon-facetime-video { 191 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 192 | } 193 | .icon-picture { 194 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 195 | } 196 | .icon-pencil { 197 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 198 | } 199 | .icon-map-marker { 200 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 201 | } 202 | .icon-adjust { 203 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 204 | } 205 | .icon-tint { 206 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 207 | } 208 | .icon-edit { 209 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 210 | } 211 | .icon-share { 212 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 213 | } 214 | .icon-check { 215 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 216 | } 217 | .icon-move { 218 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 219 | } 220 | .icon-step-backward { 221 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 222 | } 223 | .icon-fast-backward { 224 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 225 | } 226 | .icon-backward { 227 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 228 | } 229 | .icon-play { 230 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 231 | } 232 | .icon-pause { 233 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 234 | } 235 | .icon-stop { 236 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 237 | } 238 | .icon-forward { 239 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 240 | } 241 | .icon-fast-forward { 242 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 243 | } 244 | .icon-step-forward { 245 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 246 | } 247 | .icon-eject { 248 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 249 | } 250 | .icon-chevron-left { 251 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 252 | } 253 | .icon-chevron-right { 254 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 255 | } 256 | .icon-plus-sign { 257 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 258 | } 259 | .icon-minus-sign { 260 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 261 | } 262 | .icon-remove-sign { 263 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 264 | } 265 | .icon-ok-sign { 266 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 267 | } 268 | .icon-question-sign { 269 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 270 | } 271 | .icon-info-sign { 272 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 273 | } 274 | .icon-screenshot { 275 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 276 | } 277 | .icon-remove-circle { 278 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 279 | } 280 | .icon-ok-circle { 281 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 282 | } 283 | .icon-ban-circle { 284 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 285 | } 286 | .icon-arrow-left { 287 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 288 | } 289 | .icon-arrow-right { 290 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 291 | } 292 | .icon-arrow-up { 293 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 294 | } 295 | .icon-arrow-down { 296 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 297 | } 298 | .icon-share-alt { 299 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 300 | } 301 | .icon-resize-full { 302 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 303 | } 304 | .icon-resize-small { 305 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 306 | } 307 | .icon-plus { 308 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 309 | } 310 | .icon-minus { 311 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 312 | } 313 | .icon-asterisk { 314 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 315 | } 316 | .icon-exclamation-sign { 317 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 318 | } 319 | .icon-gift { 320 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 321 | } 322 | .icon-leaf { 323 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 324 | } 325 | .icon-fire { 326 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 327 | } 328 | .icon-eye-open { 329 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 330 | } 331 | .icon-eye-close { 332 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 333 | } 334 | .icon-warning-sign { 335 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 336 | } 337 | .icon-plane { 338 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 339 | } 340 | .icon-calendar { 341 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 342 | } 343 | .icon-random { 344 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 345 | } 346 | .icon-comment { 347 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 348 | } 349 | .icon-magnet { 350 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 351 | } 352 | .icon-chevron-up { 353 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 354 | } 355 | .icon-chevron-down { 356 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 357 | } 358 | .icon-retweet { 359 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 360 | } 361 | .icon-shopping-cart { 362 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 363 | } 364 | .icon-folder-close { 365 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 366 | } 367 | .icon-folder-open { 368 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 369 | } 370 | .icon-resize-vertical { 371 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 372 | } 373 | .icon-resize-horizontal { 374 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 375 | } 376 | .icon-bar-chart { 377 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 378 | } 379 | .icon-twitter-sign { 380 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 381 | } 382 | .icon-facebook-sign { 383 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 384 | } 385 | .icon-camera-retro { 386 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 387 | } 388 | .icon-key { 389 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 390 | } 391 | .icon-cogs { 392 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 393 | } 394 | .icon-comments { 395 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 396 | } 397 | .icon-thumbs-up { 398 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 399 | } 400 | .icon-thumbs-down { 401 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 402 | } 403 | .icon-star-half { 404 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 405 | } 406 | .icon-heart-empty { 407 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 408 | } 409 | .icon-signout { 410 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 411 | } 412 | .icon-linkedin-sign { 413 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 414 | } 415 | .icon-pushpin { 416 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 417 | } 418 | .icon-external-link { 419 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 420 | } 421 | .icon-signin { 422 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 423 | } 424 | .icon-trophy { 425 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 426 | } 427 | .icon-github-sign { 428 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 429 | } 430 | .icon-upload-alt { 431 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 432 | } 433 | .icon-lemon { 434 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 435 | } 436 | .icon-phone { 437 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 438 | } 439 | .icon-check-empty { 440 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 441 | } 442 | .icon-bookmark-empty { 443 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 444 | } 445 | .icon-phone-sign { 446 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 447 | } 448 | .icon-twitter { 449 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 450 | } 451 | .icon-facebook { 452 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 453 | } 454 | .icon-github { 455 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 456 | } 457 | .icon-unlock { 458 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 459 | } 460 | .icon-credit-card { 461 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 462 | } 463 | .icon-rss { 464 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 465 | } 466 | .icon-hdd { 467 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 468 | } 469 | .icon-bullhorn { 470 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 471 | } 472 | .icon-bell { 473 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 474 | } 475 | .icon-certificate { 476 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 477 | } 478 | .icon-hand-right { 479 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 480 | } 481 | .icon-hand-left { 482 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 483 | } 484 | .icon-hand-up { 485 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 486 | } 487 | .icon-hand-down { 488 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 489 | } 490 | .icon-circle-arrow-left { 491 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 492 | } 493 | .icon-circle-arrow-right { 494 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 495 | } 496 | .icon-circle-arrow-up { 497 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 498 | } 499 | .icon-circle-arrow-down { 500 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 501 | } 502 | .icon-globe { 503 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 504 | } 505 | .icon-wrench { 506 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 507 | } 508 | .icon-tasks { 509 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 510 | } 511 | .icon-filter { 512 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 513 | } 514 | .icon-briefcase { 515 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 516 | } 517 | .icon-fullscreen { 518 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 519 | } 520 | .icon-group { 521 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 522 | } 523 | .icon-link { 524 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 525 | } 526 | .icon-cloud { 527 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 528 | } 529 | .icon-beaker { 530 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 531 | } 532 | .icon-cut { 533 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 534 | } 535 | .icon-copy { 536 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 537 | } 538 | .icon-paper-clip { 539 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 540 | } 541 | .icon-save { 542 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 543 | } 544 | .icon-sign-blank { 545 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 546 | } 547 | .icon-reorder { 548 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 549 | } 550 | .icon-list-ul { 551 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 552 | } 553 | .icon-list-ol { 554 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 555 | } 556 | .icon-strikethrough { 557 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 558 | } 559 | .icon-underline { 560 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 561 | } 562 | .icon-table { 563 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 564 | } 565 | .icon-magic { 566 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 567 | } 568 | .icon-truck { 569 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 570 | } 571 | .icon-pinterest { 572 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 573 | } 574 | .icon-pinterest-sign { 575 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 576 | } 577 | .icon-google-plus-sign { 578 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 579 | } 580 | .icon-google-plus { 581 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 582 | } 583 | .icon-money { 584 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 585 | } 586 | .icon-caret-down { 587 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 588 | } 589 | .icon-caret-up { 590 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 591 | } 592 | .icon-caret-left { 593 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 594 | } 595 | .icon-caret-right { 596 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 597 | } 598 | .icon-columns { 599 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 600 | } 601 | .icon-sort { 602 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 603 | } 604 | .icon-sort-down { 605 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 606 | } 607 | .icon-sort-up { 608 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 609 | } 610 | .icon-envelope-alt { 611 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 612 | } 613 | .icon-linkedin { 614 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 615 | } 616 | .icon-undo { 617 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 618 | } 619 | .icon-legal { 620 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 621 | } 622 | .icon-dashboard { 623 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 624 | } 625 | .icon-comment-alt { 626 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 627 | } 628 | .icon-comments-alt { 629 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 630 | } 631 | .icon-bolt { 632 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 633 | } 634 | .icon-sitemap { 635 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 636 | } 637 | .icon-umbrella { 638 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 639 | } 640 | .icon-paste { 641 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 642 | } 643 | .icon-user-md { 644 | *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); 645 | } 646 | -------------------------------------------------------------------------------- /SmallestDotNet/css/font-awesome.css: -------------------------------------------------------------------------------- 1 | /* Font Awesome 2 | the iconic font designed for use with Twitter Bootstrap 3 | ------------------------------------------------------- 4 | The full suite of pictographic icons, examples, and documentation 5 | can be found at: http://fortawesome.github.com/Font-Awesome/ 6 | 7 | License 8 | ------------------------------------------------------- 9 | The Font Awesome webfont, CSS, and LESS files are licensed under CC BY 3.0: 10 | http://creativecommons.org/licenses/by/3.0/ A mention of 11 | 'Font Awesome - http://fortawesome.github.com/Font-Awesome' in human-readable 12 | source code is considered acceptable attribution (most common on the web). 13 | If human readable source code is not available to the end user, a mention in 14 | an 'About' or 'Credits' screen is considered acceptable (most common in desktop 15 | or mobile software). 16 | 17 | Contact 18 | ------------------------------------------------------- 19 | Email: dave@davegandy.com 20 | Twitter: http://twitter.com/fortaweso_me 21 | Work: http://lemonwi.se co-founder 22 | 23 | */ 24 | @font-face { 25 | font-family: "FontAwesome"; 26 | src: url('../font/fontawesome-webfont.eot'); 27 | src: url('../font/fontawesome-webfont.eot?#iefix') format('eot'), url('../font/fontawesome-webfont.woff') format('woff'), url('../font/fontawesome-webfont.ttf') format('truetype'), url('../font/fontawesome-webfont.svg#FontAwesome') format('svg'); 28 | font-weight: normal; 29 | font-style: normal; 30 | } 31 | 32 | /* Font Awesome styles 33 | ------------------------------------------------------- */ 34 | [class^="icon-"]:before, [class*=" icon-"]:before { 35 | font-family: FontAwesome; 36 | font-weight: normal; 37 | font-style: normal; 38 | display: inline-block; 39 | text-decoration: inherit; 40 | } 41 | a [class^="icon-"], a [class*=" icon-"] { 42 | display: inline-block; 43 | text-decoration: inherit; 44 | } 45 | /* makes the font 33% larger relative to the icon container */ 46 | .icon-large:before { 47 | vertical-align: top; 48 | font-size: 1.3333333333333333em; 49 | } 50 | .btn [class^="icon-"], .btn [class*=" icon-"] { 51 | /* keeps button heights with and without icons the same */ 52 | 53 | line-height: .9em; 54 | } 55 | li [class^="icon-"], li [class*=" icon-"] { 56 | display: inline-block; 57 | width: 1.25em; 58 | text-align: center; 59 | } 60 | li .icon-large[class^="icon-"], li .icon-large[class*=" icon-"] { 61 | /* 1.5 increased font size for icon-large * 1.25 width */ 62 | 63 | width: 1.875em; 64 | } 65 | li[class^="icon-"], li[class*=" icon-"] { 66 | margin-left: 0; 67 | list-style-type: none; 68 | } 69 | li[class^="icon-"]:before, li[class*=" icon-"]:before { 70 | text-indent: -2em; 71 | text-align: center; 72 | } 73 | li[class^="icon-"].icon-large:before, li[class*=" icon-"].icon-large:before { 74 | text-indent: -1.3333333333333333em; 75 | } 76 | /* Font Awesome uses the Unicode Private Use Area (PUA) to ensure screen 77 | readers do not read off random characters that represent icons */ 78 | .icon-glass:before { content: "\f000"; } 79 | .icon-music:before { content: "\f001"; } 80 | .icon-search:before { content: "\f002"; } 81 | .icon-envelope:before { content: "\f003"; } 82 | .icon-heart:before { content: "\f004"; } 83 | .icon-star:before { content: "\f005"; } 84 | .icon-star-empty:before { content: "\f006"; } 85 | .icon-user:before { content: "\f007"; } 86 | .icon-film:before { content: "\f008"; } 87 | .icon-th-large:before { content: "\f009"; } 88 | .icon-th:before { content: "\f00a"; } 89 | .icon-th-list:before { content: "\f00b"; } 90 | .icon-ok:before { content: "\f00c"; } 91 | .icon-remove:before { content: "\f00d"; } 92 | .icon-zoom-in:before { content: "\f00e"; } 93 | 94 | .icon-zoom-out:before { content: "\f010"; } 95 | .icon-off:before { content: "\f011"; } 96 | .icon-signal:before { content: "\f012"; } 97 | .icon-cog:before { content: "\f013"; } 98 | .icon-trash:before { content: "\f014"; } 99 | .icon-home:before { content: "\f015"; } 100 | .icon-file:before { content: "\f016"; } 101 | .icon-time:before { content: "\f017"; } 102 | .icon-road:before { content: "\f018"; } 103 | .icon-download-alt:before { content: "\f019"; } 104 | .icon-download:before { content: "\f01a"; } 105 | .icon-upload:before { content: "\f01b"; } 106 | .icon-inbox:before { content: "\f01c"; } 107 | .icon-play-circle:before { content: "\f01d"; } 108 | .icon-repeat:before { content: "\f01e"; } 109 | 110 | /* \f020 doesn't work in Safari. all shifted one down */ 111 | .icon-refresh:before { content: "\f021"; } 112 | .icon-list-alt:before { content: "\f022"; } 113 | .icon-lock:before { content: "\f023"; } 114 | .icon-flag:before { content: "\f024"; } 115 | .icon-headphones:before { content: "\f025"; } 116 | .icon-volume-off:before { content: "\f026"; } 117 | .icon-volume-down:before { content: "\f027"; } 118 | .icon-volume-up:before { content: "\f028"; } 119 | .icon-qrcode:before { content: "\f029"; } 120 | .icon-barcode:before { content: "\f02a"; } 121 | .icon-tag:before { content: "\f02b"; } 122 | .icon-tags:before { content: "\f02c"; } 123 | .icon-book:before { content: "\f02d"; } 124 | .icon-bookmark:before { content: "\f02e"; } 125 | .icon-print:before { content: "\f02f"; } 126 | 127 | .icon-camera:before { content: "\f030"; } 128 | .icon-font:before { content: "\f031"; } 129 | .icon-bold:before { content: "\f032"; } 130 | .icon-italic:before { content: "\f033"; } 131 | .icon-text-height:before { content: "\f034"; } 132 | .icon-text-width:before { content: "\f035"; } 133 | .icon-align-left:before { content: "\f036"; } 134 | .icon-align-center:before { content: "\f037"; } 135 | .icon-align-right:before { content: "\f038"; } 136 | .icon-align-justify:before { content: "\f039"; } 137 | .icon-list:before { content: "\f03a"; } 138 | .icon-indent-left:before { content: "\f03b"; } 139 | .icon-indent-right:before { content: "\f03c"; } 140 | .icon-facetime-video:before { content: "\f03d"; } 141 | .icon-picture:before { content: "\f03e"; } 142 | 143 | .icon-pencil:before { content: "\f040"; } 144 | .icon-map-marker:before { content: "\f041"; } 145 | .icon-adjust:before { content: "\f042"; } 146 | .icon-tint:before { content: "\f043"; } 147 | .icon-edit:before { content: "\f044"; } 148 | .icon-share:before { content: "\f045"; } 149 | .icon-check:before { content: "\f046"; } 150 | .icon-move:before { content: "\f047"; } 151 | .icon-step-backward:before { content: "\f048"; } 152 | .icon-fast-backward:before { content: "\f049"; } 153 | .icon-backward:before { content: "\f04a"; } 154 | .icon-play:before { content: "\f04b"; } 155 | .icon-pause:before { content: "\f04c"; } 156 | .icon-stop:before { content: "\f04d"; } 157 | .icon-forward:before { content: "\f04e"; } 158 | 159 | .icon-fast-forward:before { content: "\f050"; } 160 | .icon-step-forward:before { content: "\f051"; } 161 | .icon-eject:before { content: "\f052"; } 162 | .icon-chevron-left:before { content: "\f053"; } 163 | .icon-chevron-right:before { content: "\f054"; } 164 | .icon-plus-sign:before { content: "\f055"; } 165 | .icon-minus-sign:before { content: "\f056"; } 166 | .icon-remove-sign:before { content: "\f057"; } 167 | .icon-ok-sign:before { content: "\f058"; } 168 | .icon-question-sign:before { content: "\f059"; } 169 | .icon-info-sign:before { content: "\f05a"; } 170 | .icon-screenshot:before { content: "\f05b"; } 171 | .icon-remove-circle:before { content: "\f05c"; } 172 | .icon-ok-circle:before { content: "\f05d"; } 173 | .icon-ban-circle:before { content: "\f05e"; } 174 | 175 | .icon-arrow-left:before { content: "\f060"; } 176 | .icon-arrow-right:before { content: "\f061"; } 177 | .icon-arrow-up:before { content: "\f062"; } 178 | .icon-arrow-down:before { content: "\f063"; } 179 | .icon-share-alt:before { content: "\f064"; } 180 | .icon-resize-full:before { content: "\f065"; } 181 | .icon-resize-small:before { content: "\f066"; } 182 | .icon-plus:before { content: "\f067"; } 183 | .icon-minus:before { content: "\f068"; } 184 | .icon-asterisk:before { content: "\f069"; } 185 | .icon-exclamation-sign:before { content: "\f06a"; } 186 | .icon-gift:before { content: "\f06b"; } 187 | .icon-leaf:before { content: "\f06c"; } 188 | .icon-fire:before { content: "\f06d"; } 189 | .icon-eye-open:before { content: "\f06e"; } 190 | 191 | .icon-eye-close:before { content: "\f070"; } 192 | .icon-warning-sign:before { content: "\f071"; } 193 | .icon-plane:before { content: "\f072"; } 194 | .icon-calendar:before { content: "\f073"; } 195 | .icon-random:before { content: "\f074"; } 196 | .icon-comment:before { content: "\f075"; } 197 | .icon-magnet:before { content: "\f076"; } 198 | .icon-chevron-up:before { content: "\f077"; } 199 | .icon-chevron-down:before { content: "\f078"; } 200 | .icon-retweet:before { content: "\f079"; } 201 | .icon-shopping-cart:before { content: "\f07a"; } 202 | .icon-folder-close:before { content: "\f07b"; } 203 | .icon-folder-open:before { content: "\f07c"; } 204 | .icon-resize-vertical:before { content: "\f07d"; } 205 | .icon-resize-horizontal:before { content: "\f07e"; } 206 | 207 | .icon-bar-chart:before { content: "\f080"; } 208 | .icon-twitter-sign:before { content: "\f081"; } 209 | .icon-facebook-sign:before { content: "\f082"; } 210 | .icon-camera-retro:before { content: "\f083"; } 211 | .icon-key:before { content: "\f084"; } 212 | .icon-cogs:before { content: "\f085"; } 213 | .icon-comments:before { content: "\f086"; } 214 | .icon-thumbs-up:before { content: "\f087"; } 215 | .icon-thumbs-down:before { content: "\f088"; } 216 | .icon-star-half:before { content: "\f089"; } 217 | .icon-heart-empty:before { content: "\f08a"; } 218 | .icon-signout:before { content: "\f08b"; } 219 | .icon-linkedin-sign:before { content: "\f08c"; } 220 | .icon-pushpin:before { content: "\f08d"; } 221 | .icon-external-link:before { content: "\f08e"; } 222 | 223 | .icon-signin:before { content: "\f090"; } 224 | .icon-trophy:before { content: "\f091"; } 225 | .icon-github-sign:before { content: "\f092"; } 226 | .icon-upload-alt:before { content: "\f093"; } 227 | .icon-lemon:before { content: "\f094"; } 228 | .icon-phone:before { content: "\f095"; } 229 | .icon-check-empty:before { content: "\f096"; } 230 | .icon-bookmark-empty:before { content: "\f097"; } 231 | .icon-phone-sign:before { content: "\f098"; } 232 | .icon-twitter:before { content: "\f099"; } 233 | .icon-facebook:before { content: "\f09a"; } 234 | .icon-github:before { content: "\f09b"; } 235 | .icon-unlock:before { content: "\f09c"; } 236 | .icon-credit-card:before { content: "\f09d"; } 237 | .icon-rss:before { content: "\f09e"; } 238 | 239 | .icon-hdd:before { content: "\f0a0"; } 240 | .icon-bullhorn:before { content: "\f0a1"; } 241 | .icon-bell:before { content: "\f0a2"; } 242 | .icon-certificate:before { content: "\f0a3"; } 243 | .icon-hand-right:before { content: "\f0a4"; } 244 | .icon-hand-left:before { content: "\f0a5"; } 245 | .icon-hand-up:before { content: "\f0a6"; } 246 | .icon-hand-down:before { content: "\f0a7"; } 247 | .icon-circle-arrow-left:before { content: "\f0a8"; } 248 | .icon-circle-arrow-right:before { content: "\f0a9"; } 249 | .icon-circle-arrow-up:before { content: "\f0aa"; } 250 | .icon-circle-arrow-down:before { content: "\f0ab"; } 251 | .icon-globe:before { content: "\f0ac"; } 252 | .icon-wrench:before { content: "\f0ad"; } 253 | .icon-tasks:before { content: "\f0ae"; } 254 | 255 | .icon-filter:before { content: "\f0b0"; } 256 | .icon-briefcase:before { content: "\f0b1"; } 257 | .icon-fullscreen:before { content: "\f0b2"; } 258 | 259 | .icon-group:before { content: "\f0c0"; } 260 | .icon-link:before { content: "\f0c1"; } 261 | .icon-cloud:before { content: "\f0c2"; } 262 | .icon-beaker:before { content: "\f0c3"; } 263 | .icon-cut:before { content: "\f0c4"; } 264 | .icon-copy:before { content: "\f0c5"; } 265 | .icon-paper-clip:before { content: "\f0c6"; } 266 | .icon-save:before { content: "\f0c7"; } 267 | .icon-sign-blank:before { content: "\f0c8"; } 268 | .icon-reorder:before { content: "\f0c9"; } 269 | .icon-list-ul:before { content: "\f0ca"; } 270 | .icon-list-ol:before { content: "\f0cb"; } 271 | .icon-strikethrough:before { content: "\f0cc"; } 272 | .icon-underline:before { content: "\f0cd"; } 273 | .icon-table:before { content: "\f0ce"; } 274 | 275 | .icon-magic:before { content: "\f0d0"; } 276 | .icon-truck:before { content: "\f0d1"; } 277 | .icon-pinterest:before { content: "\f0d2"; } 278 | .icon-pinterest-sign:before { content: "\f0d3"; } 279 | .icon-google-plus-sign:before { content: "\f0d4"; } 280 | .icon-google-plus:before { content: "\f0d5"; } 281 | .icon-money:before { content: "\f0d6"; } 282 | .icon-caret-down:before { content: "\f0d7"; } 283 | .icon-caret-up:before { content: "\f0d8"; } 284 | .icon-caret-left:before { content: "\f0d9"; } 285 | .icon-caret-right:before { content: "\f0da"; } 286 | .icon-columns:before { content: "\f0db"; } 287 | .icon-sort:before { content: "\f0dc"; } 288 | .icon-sort-down:before { content: "\f0dd"; } 289 | .icon-sort-up:before { content: "\f0de"; } 290 | 291 | .icon-envelope-alt:before { content: "\f0e0"; } 292 | .icon-linkedin:before { content: "\f0e1"; } 293 | .icon-undo:before { content: "\f0e2"; } 294 | .icon-legal:before { content: "\f0e3"; } 295 | .icon-dashboard:before { content: "\f0e4"; } 296 | .icon-comment-alt:before { content: "\f0e5"; } 297 | .icon-comments-alt:before { content: "\f0e6"; } 298 | .icon-bolt:before { content: "\f0e7"; } 299 | .icon-sitemap:before { content: "\f0e8"; } 300 | .icon-umbrella:before { content: "\f0e9"; } 301 | .icon-paste:before { content: "\f0ea"; } 302 | 303 | .icon-user-md:before { content: "\f200"; } 304 | -------------------------------------------------------------------------------- /SmallestDotNet/css/m-buttons.min.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * CSS3 Microsoft Metro Buttons 3 | * Inspired by Tim O'Donnell's CSS3 Google Buttons, Twitter Bootstrap, and Microsoft. Icons from glyphicons.com and Syncfusion's Metro Studio. 4 | * I do not claim ownership on the origin of design and icons. 5 | * Built by Ace Subido (http://github.com/ace-subido) 6 | */article,aside,details,figcaption,figure,footer,header,hgroup,nav,section{display:block}audio,canvas,video{display:inline-block;*display:inline;*zoom:1}audio:not([controls]){display:none}html{font-size:100%;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}a:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}a:hover,a:active{outline:0}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sup{top:-0.5em}sub{bottom:-0.25em}img{max-width:100%;height:auto;border:0;-ms-interpolation-mode:bicubic}button,input,select,textarea{margin:0;font-size:100%}button,input{*overflow:visible;line-height:normal}button::-moz-focus-inner,input::-moz-focus-inner{padding:0;border:0}button,input[type="button"],input[type="reset"],input[type="submit"]{cursor:pointer;-webkit-appearance:button;-moz-appearance:none}@-moz-document url-prefix(){button,input[type="button"],input[type="reset"],input[type="submit"]{cursor:pointer;padding:6px 14px}}input[type="search"]{-webkit-appearance:textfield;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}input[type="search"]::-webkit-search-decoration,input[type="search"]::-webkit-search-cancel-button{-webkit-appearance:none}textarea{overflow:auto;vertical-align:top}.dropdown{position:relative}.dropdown-toggle{*margin-bottom:-3px}.dropdown-toggle:active,.open .dropdown-toggle{outline:0}.caret{display:inline-block;width:0;height:0;text-indent:-99999px;*text-indent:0;vertical-align:top;margin-top:5px;margin-left:2px;margin-right:2px;border-left:4px solid transparent;border-right:4px solid transparent;border-top:4px solid black;opacity:.5;filter:alpha(opacity=50);content:"\2193"}.caret.white{border-left:4px solid transparent;border-right:4px solid transparent;border-top:4px solid white;opacity:.95;filter:alpha(opacity=95)}.dropdown .caret{margin-top:8px;margin-left:2px}.dropdown:hover .caret,.open.dropdown .caret{opacity:1;filter:alpha(opacity=100)}.m-dropdown-menu{position:absolute;top:98%;left:0;z-index:1000;float:left;display:none;min-width:225px;max-width:225px;padding:0 0 6px 0;margin:0;list-style:none;background-color:white;-webkit-box-shadow:0 1px 8px rgba(0,0,0,0.1);-moz-box-shadow:0 1px 8px rgba(0,0,0,0.1);box-shadow:0 1px 8px rgba(0,0,0,0.1);font-size:14px;font-family:"Segoe UI",Helvetica,Arial,sans-serif;border:1px solid #eee}.m-dropdown-menu.bottom-up{top:auto;bottom:100%;margin-bottom:2px}.m-dropdown-menu .divider{border-top:1px solid #ebebeb;margin-top:9px;margin-bottom:10px;padding:0;cursor:default}.m-dropdown-menu a{position:relative;padding:6px 0 6px 30px;color:#333;text-decoration:none;display:block;clear:both;font-weight:normal;line-height:18px;white-space:nowrap}.m-dropdown-menu a [class^="icon-"]{position:absolute;left:7px;top:9px}.m-dropdown-menu li>a:hover,.m-dropdown-menu .active>a,.m-dropdown-menu .active>a:hover{text-decoration:none;background-color:#eee}.dropdown.open{*z-index:1000}.dropdown.open .dropdown-toggle{color:#08c;background:#ccc;background:rgba(0,0,0,0.3)}.dropdown.open .m-dropdown-menu{display:block}.m-btn{border-style: none; 7 | border-color: inherit; 8 | border-width: 0; 9 | position:relative;display:inline-block;overflow:visible;padding:10px 14px;margin-top:8px;cursor:pointer;outline:0;background-color:#eee;background-repeat: repeat-x; 10 | -webkit-background-clip: padding; 11 | -moz-background-clip: padding; 12 | background-clip: padding; 13 | zoom: 1; 14 | z-index: 1; 15 | display: inline; 16 | font-family: "Segoe UI", Helvetica, Arial, sans-serif; 17 | font-size: 14px; 18 | line-height: 14px; 19 | color: #333; 20 | min-width: 42px; 21 | text-shadow: #fff 0 1px 0; 22 | text-align: center; 23 | text-decoration: none; 24 | white-space: nowrap; 25 | vertical-align: inherit; 26 | background-image: linear-gradient(top,#eee,#eee); 27 | *margin-left: 0; 28 | margin-right: 0; 29 | margin-bottom: 0; 30 | }.m-btn:hover,.m-btn:focus,.m-btn:active,.m-btn.active{color:#333;text-decoration:none;background-color:#dcdcdc;background-repeat: repeat-x; 31 | z-index: 100; 32 | outline: 0; 33 | background-image: linear-gradient(top,#dcdcdc,#dcdcdc); 34 | }.m-btn:active,.m-btn.active{background-color:#eee;background-repeat: repeat-x; 35 | -webkit-box-shadow: inset 0 1px 8px rgba(0, 0, 0, 0.25); 36 | -moz-box-shadow: inset 0 1px 8px rgba(0, 0, 0, 0.25); 37 | box-shadow: inset 0 1px 8px rgba(0, 0, 0, 0.25); 38 | background-image: linear-gradient(top,#eee,#dcdcdc); 39 | }.m-btn:focus{border-color:#4d90fe}.m-btn::-moz-focus-inner{padding:0;border:0}.m-btn.red-stripe{border-left:3px solid #d84a38}.m-btn.blue-stripe{border-left:3px solid #4d90fe}.m-btn.purple-stripe{border-left:3px solid #852b99}.m-btn.green-stripe{border-left:3px solid #35aa47}.m-btn.red:active,.m-btn.red.active,.m-btn.red.disabled,.m-btn.red[disabled],.m-btn.blue:active,.m-btn.blue.active,.m-btn.blue.disabled,.m-btn.blue[disabled],.m-btn.purple:active,.m-btn.purple.active,.m-btn.purple.disabled,.m-btn.purple[disabled],.m-btn.green:active,.m-btn.green.active,.m-btn.green.disabled,.m-btn.green[disabled]{-webkit-box-shadow:inset 0 1px 8px rgba(0,0,0,0.25);-moz-box-shadow:inset 0 1px 8px rgba(0,0,0,0.25);box-shadow:inset 0 1px 8px rgba(0,0,0,0.25);color:white!important}.m-btn.red.disabled,.m-btn.red[disabled],.m-btn.blue.disabled,.m-btn.blue[disabled],.m-btn.purple.disabled,.m-btn.purple[disabled],.m-btn.green.disabled,.m-btn.green[disabled]{opacity:.7}.m-btn.red{color:white;text-shadow:none;background-color:#d84a38;background-repeat: repeat-x; 40 | background-image: linear-gradient(top,#dd4b39,#d14836); 41 | }.m-btn.red:hover,.m-btn.red:focus,.m-btn.red:active,.m-btn.red.active,.m-btn.red[disabled],.m-btn.red.disabled{background-color:#c53727;background-repeat: repeat-x; 42 | background-image: linear-gradient(top,#c53727,#c53727); 43 | }.m-btn.red:active,.m-btn.red.active{background-color:#dd4b39;background-repeat: repeat-x; 44 | background-image: linear-gradient(top,#dd4b39,#c53727); 45 | }.m-btn.blue{color:white;text-shadow:none;background-color:#4d90fe;background-repeat: repeat-x; 46 | background-image: linear-gradient(top,#4d90fe,#4787ed); 47 | }.m-btn.blue:hover,.m-btn.blue:focus,.m-btn.blue:active,.m-btn.blue.active,.m-btn.blue[disabled],.m-btn.blue.disabled{background-color:#0072bb;background-repeat: repeat-x; 48 | background-image: linear-gradient(top,#0072bb,#0072bb); 49 | }.m-btn.blue:active,.m-btn.blue.active{background-color:#4d90fe;background-repeat: repeat-x; 50 | background-image: linear-gradient(top,#4d90fe,#0072bb); 51 | }.m-btn.green{color:white;text-shadow:none;background-color:#35aa47;background-repeat: repeat-x; 52 | background-image: linear-gradient(top,#35aa47,#35aa47); 53 | }.m-btn.green:hover,.m-btn.green:focus,.m-btn.green:active,.m-btn.green.active,.m-btn.green.disabled,.m-btn.green[disabled]{background-color:#1d943b;background-repeat: repeat-x; 54 | background-image: linear-gradient(top,#1d943b,#1d943b); 55 | }.m-btn.green:active,.m-btn.green.active{background-color:#35aa47;background-repeat: repeat-x; 56 | background-image: linear-gradient(top,#35aa47,#1d943b); 57 | }.m-btn.purple{color:white;text-shadow:none;background-color:#852b99;background-repeat: repeat-x; 58 | background-image: linear-gradient(top,#852b99,#852b99); 59 | }.m-btn.purple:hover,.m-btn.purple:focus,.m-btn.purple:active,.m-btn.purple.active,.m-btn.purple.disabled,.m-btn.purple[disabled]{background-color:#6d1b81;background-repeat: repeat-x; 60 | background-image: linear-gradient(top,#6d1b81,#6d1b81); 61 | }.m-btn.purple:active,.m-btn.purple.active{background-color:#35aa47;background-repeat: repeat-x; 62 | background-image: linear-gradient(top,#852b99,#6d1b81); 63 | }.sm{font-size:11px}.mini{height:13px;font-size:11px;line-height:13px;padding:4px 10px}.big{height:38px;font-size:18px;line-height:38px;padding:20px 26px}.m-btn.disabled,.m-btn[disabled]{color:#999;background-color:#f5f5f5;background-repeat: repeat-x; 64 | cursor: default; 65 | -webkit-box-shadow: inset 0 1px 6px rgba(0, 0, 0, 0.25); 66 | -moz-box-shadow: inset 0 1px 6px rgba(0, 0, 0, 0.25); 67 | box-shadow: inset 0 1px 6px rgba(0, 0, 0, 0.25); 68 | background-image: linear-gradient(top,#eee,#ddd); 69 | }.m-btn.icn-only{min-width:14px}.m-btn.bigicn-only{min-width:34px}.m-btn-group{position:relative;display:inline-block;list-style:none;padding:0;margin:0;zoom:1;*display:inline}.m-btn+.m-btn,.m-btn+.m-btn-group,.m-btn-group+.m-btn,.m-btn-group+.m-btn-group{margin-left:15px}.m-btn.dropdown-carettoggle{min-width:5px;height:18px;padding:8px}.m-btn.dropdown-carettoggle>.caret{margin-top:8px}.m-btn.caret:hover{opacity:1}.m-btn-group .m-btn{position:relative;float:left;margin-left:-1px;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.m-btn-group .m-btn:first-child{margin-left:0}.m-btn-strip .m-btn,.m-btn-strip .m-btn-group{vertical-align:top}.m-btn-group.open{*z-index:1000}.m-btn-group.open .dropdown-carettoggle,.m-btn-group.open .dropdown-toggle{background-image:none;-webkit-box-shadow:inset 0 1px 6px rgba(0,0,0,0.2);-moz-box-shadow:inset 0 1px 6px rgba(0,0,0,0.2);box-shadow:inset 0 1px 6px rgba(0,0,0,0.2)}.m-btn-group.open .m-dropdown-menu{display:block;margin-top:1px} -------------------------------------------------------------------------------- /SmallestDotNet/css/main.css: -------------------------------------------------------------------------------- 1 | .green 2 | { 3 | color: #9EC630; 4 | } 5 | 6 | .gray 7 | { 8 | color: #BFBFBF; 9 | } 10 | 11 | #header h1#logo 12 | { 13 | margin: 0; 14 | padding: 0; 15 | font: bolder 4.1em 'Trebuchet MS', Arial, Sans-serif; 16 | letter-spacing: -2px; 17 | text-transform: lowercase; 18 | top: 0; 19 | left: 5px; 20 | } 21 | 22 | #header h2#slogan 23 | { 24 | color: #666666; 25 | text-indent: 0; 26 | font: bold 11px Tahoma, 'trebuchet MS', Sans-serif; 27 | text-transform: none; 28 | } 29 | 30 | .result-header 31 | { 32 | background-image: url(/img/hero_home.jpg); 33 | -moz-background-size: 100%; 34 | -o-background-size: 100%; 35 | -webkit-background-size: 100%; 36 | background-size: 100%; 37 | color: #fff; 38 | padding: 15px 15px 30px 15px 39 | } 40 | 41 | .result-header a 42 | { 43 | color: #fff; 44 | text-decoration: underline; 45 | } 46 | 47 | .result-header a:hover 48 | { 49 | color: #aaa; 50 | } 51 | 52 | #getdotnet, #checkdotnet 53 | { 54 | color: #000; 55 | text-decoration: none; 56 | font-size: 40px; 57 | } 58 | 59 | body 60 | { 61 | margin-top: 50px; 62 | } 63 | 64 | 65 | @media (max-width: 980px) 66 | { 67 | body 68 | { 69 | margin-top: 0; 70 | } 71 | .result-header 72 | { 73 | background: #2080c0; 74 | 75 | } 76 | 77 | .m-btn.blue 78 | { 79 | clear: both; 80 | float: left; 81 | margin: 20px; 82 | } 83 | 84 | #getdotnet, #checkdotnet 85 | { 86 | color: #000; 87 | text-decoration: none; 88 | font-size: 24px; 89 | } 90 | 91 | } 92 | -------------------------------------------------------------------------------- /SmallestDotNet/font/fontawesome-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shanselman/SmallestDotNet/8a60a223929137d036b0730f24b44c83ecb8cbe4/SmallestDotNet/font/fontawesome-webfont.eot -------------------------------------------------------------------------------- /SmallestDotNet/font/fontawesome-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shanselman/SmallestDotNet/8a60a223929137d036b0730f24b44c83ecb8cbe4/SmallestDotNet/font/fontawesome-webfont.ttf -------------------------------------------------------------------------------- /SmallestDotNet/font/fontawesome-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shanselman/SmallestDotNet/8a60a223929137d036b0730f24b44c83ecb8cbe4/SmallestDotNet/font/fontawesome-webfont.woff -------------------------------------------------------------------------------- /SmallestDotNet/img/glyphicons-halflings-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shanselman/SmallestDotNet/8a60a223929137d036b0730f24b44c83ecb8cbe4/SmallestDotNet/img/glyphicons-halflings-white.png -------------------------------------------------------------------------------- /SmallestDotNet/img/glyphicons-halflings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shanselman/SmallestDotNet/8a60a223929137d036b0730f24b44c83ecb8cbe4/SmallestDotNet/img/glyphicons-halflings.png -------------------------------------------------------------------------------- /SmallestDotNet/img/hero_home.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shanselman/SmallestDotNet/8a60a223929137d036b0730f24b44c83ecb8cbe4/SmallestDotNet/img/hero_home.jpg -------------------------------------------------------------------------------- /SmallestDotNet/javascript.ashx: -------------------------------------------------------------------------------- 1 | <%@ WebHandler Language="C#" Class="SmallestDotNet" %> 2 | 3 | using System; 4 | using System.Web; 5 | 6 | public class SmallestDotNet : IHttpHandler 7 | { 8 | 9 | public void ProcessRequest(HttpContext context) 10 | { 11 | WriteToResponse(""); 12 | context.Response.ContentType = "text/javascript"; 13 | 14 | WriteToResponse(Helpers.GetUpdateInformation(context.Request.UserAgent, context.Request.Browser.ClrVersion.ToString()).Text.Replace("'", @"\'").Replace(Environment.NewLine, "
")); 15 | WriteToResponse("
"); 16 | } 17 | 18 | private void WriteToResponse(string s) 19 | { 20 | HttpResponse r = HttpContext.Current.Response; 21 | r.Write(String.Format("document.write('{0}')\r\n", s)); 22 | } 23 | 24 | public bool IsReusable 25 | { 26 | get 27 | { 28 | return false; 29 | } 30 | } 31 | 32 | } -------------------------------------------------------------------------------- /SmallestDotNet/javascriptdom.ashx: -------------------------------------------------------------------------------- 1 | <%@ WebHandler Language="C#" Class="SmallestDotNet" %> 2 | 3 | using System; 4 | using System.Web; 5 | using SmallestDotNetLib; 6 | 7 | public class SmallestDotNet : IHttpHandler 8 | { 9 | 10 | public void ProcessRequest(HttpContext context) 11 | { 12 | context.Response.ContentType = "text/javascript"; 13 | 14 | dr("SmallestDotNet = {};"); 15 | 16 | dr(JsonVersions.WriteLatestVersions(context.Request.UserAgent)); 17 | 18 | dr(JsonVersions.WriteAllVersions(context.Request.UserAgent)); 19 | 20 | dr(JsonVersions.WriteDownloads().Trim()); 21 | 22 | 23 | if (context.Request.UserAgent.Contains("Mac") || context.Request.UserAgent.Contains("nix")) 24 | { 25 | dr(@" 26 | SmallestDotNet = {}; 27 | SmallestDotNet.latestVersion = null; 28 | SmallestDotNet.allVersions = []; 29 | "); 30 | } 31 | 32 | } 33 | 34 | private static void dr(string s) 35 | { 36 | HttpResponse r = HttpContext.Current.Response; 37 | r.Write(s); 38 | } 39 | 40 | public bool IsReusable 41 | { 42 | get 43 | { 44 | return false; 45 | } 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /SmallestDotNet/js/bootstrap.min.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap.js by @fat & @mdo 3 | * Copyright 2012 Twitter, Inc. 4 | * http://www.apache.org/licenses/LICENSE-2.0.txt 5 | */ 6 | !function(e){e(function(){"use strict";e.support.transition=function(){var e=function(){var e=document.createElement("bootstrap"),t={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"},n;for(n in t)if(e.style[n]!==undefined)return t[n]}();return e&&{end:e}}()})}(window.jQuery),!function(e){"use strict";var t='[data-dismiss="alert"]',n=function(n){e(n).on("click",t,this.close)};n.prototype.close=function(t){function s(){i.trigger("closed").remove()}var n=e(this),r=n.attr("data-target"),i;r||(r=n.attr("href"),r=r&&r.replace(/.*(?=#[^\s]*$)/,"")),i=e(r),t&&t.preventDefault(),i.length||(i=n.hasClass("alert")?n:n.parent()),i.trigger(t=e.Event("close"));if(t.isDefaultPrevented())return;i.removeClass("in"),e.support.transition&&i.hasClass("fade")?i.on(e.support.transition.end,s):s()},e.fn.alert=function(t){return this.each(function(){var r=e(this),i=r.data("alert");i||r.data("alert",i=new n(this)),typeof t=="string"&&i[t].call(r)})},e.fn.alert.Constructor=n,e(function(){e("body").on("click.alert.data-api",t,n.prototype.close)})}(window.jQuery),!function(e){"use strict";var t=function(t,n){this.$element=e(t),this.options=e.extend({},e.fn.button.defaults,n)};t.prototype.setState=function(e){var t="disabled",n=this.$element,r=n.data(),i=n.is("input")?"val":"html";e+="Text",r.resetText||n.data("resetText",n[i]()),n[i](r[e]||this.options[e]),setTimeout(function(){e=="loadingText"?n.addClass(t).attr(t,t):n.removeClass(t).removeAttr(t)},0)},t.prototype.toggle=function(){var e=this.$element.closest('[data-toggle="buttons-radio"]');e&&e.find(".active").removeClass("active"),this.$element.toggleClass("active")},e.fn.button=function(n){return this.each(function(){var r=e(this),i=r.data("button"),s=typeof n=="object"&&n;i||r.data("button",i=new t(this,s)),n=="toggle"?i.toggle():n&&i.setState(n)})},e.fn.button.defaults={loadingText:"loading..."},e.fn.button.Constructor=t,e(function(){e("body").on("click.button.data-api","[data-toggle^=button]",function(t){var n=e(t.target);n.hasClass("btn")||(n=n.closest(".btn")),n.button("toggle")})})}(window.jQuery),!function(e){"use strict";var t=function(t,n){this.$element=e(t),this.options=n,this.options.slide&&this.slide(this.options.slide),this.options.pause=="hover"&&this.$element.on("mouseenter",e.proxy(this.pause,this)).on("mouseleave",e.proxy(this.cycle,this))};t.prototype={cycle:function(t){return t||(this.paused=!1),this.options.interval&&!this.paused&&(this.interval=setInterval(e.proxy(this.next,this),this.options.interval)),this},to:function(t){var n=this.$element.find(".item.active"),r=n.parent().children(),i=r.index(n),s=this;if(t>r.length-1||t<0)return;return this.sliding?this.$element.one("slid",function(){s.to(t)}):i==t?this.pause().cycle():this.slide(t>i?"next":"prev",e(r[t]))},pause:function(t){return t||(this.paused=!0),this.$element.find(".next, .prev").length&&e.support.transition.end&&(this.$element.trigger(e.support.transition.end),this.cycle()),clearInterval(this.interval),this.interval=null,this},next:function(){if(this.sliding)return;return this.slide("next")},prev:function(){if(this.sliding)return;return this.slide("prev")},slide:function(t,n){var r=this.$element.find(".item.active"),i=n||r[t](),s=this.interval,o=t=="next"?"left":"right",u=t=="next"?"first":"last",a=this,f=e.Event("slide",{relatedTarget:i[0]});this.sliding=!0,s&&this.pause(),i=i.length?i:this.$element.find(".item")[u]();if(i.hasClass("active"))return;if(e.support.transition&&this.$element.hasClass("slide")){this.$element.trigger(f);if(f.isDefaultPrevented())return;i.addClass(t),i[0].offsetWidth,r.addClass(o),i.addClass(o),this.$element.one(e.support.transition.end,function(){i.removeClass([t,o].join(" ")).addClass("active"),r.removeClass(["active",o].join(" ")),a.sliding=!1,setTimeout(function(){a.$element.trigger("slid")},0)})}else{this.$element.trigger(f);if(f.isDefaultPrevented())return;r.removeClass("active"),i.addClass("active"),this.sliding=!1,this.$element.trigger("slid")}return s&&this.cycle(),this}},e.fn.carousel=function(n){return this.each(function(){var r=e(this),i=r.data("carousel"),s=e.extend({},e.fn.carousel.defaults,typeof n=="object"&&n),o=typeof n=="string"?n:s.slide;i||r.data("carousel",i=new t(this,s)),typeof n=="number"?i.to(n):o?i[o]():s.interval&&i.cycle()})},e.fn.carousel.defaults={interval:5e3,pause:"hover"},e.fn.carousel.Constructor=t,e(function(){e("body").on("click.carousel.data-api","[data-slide]",function(t){var n=e(this),r,i=e(n.attr("data-target")||(r=n.attr("href"))&&r.replace(/.*(?=#[^\s]+$)/,"")),s=!i.data("modal")&&e.extend({},i.data(),n.data());i.carousel(s),t.preventDefault()})})}(window.jQuery),!function(e){"use strict";var t=function(t,n){this.$element=e(t),this.options=e.extend({},e.fn.collapse.defaults,n),this.options.parent&&(this.$parent=e(this.options.parent)),this.options.toggle&&this.toggle()};t.prototype={constructor:t,dimension:function(){var e=this.$element.hasClass("width");return e?"width":"height"},show:function(){var t,n,r,i;if(this.transitioning)return;t=this.dimension(),n=e.camelCase(["scroll",t].join("-")),r=this.$parent&&this.$parent.find("> .accordion-group > .in");if(r&&r.length){i=r.data("collapse");if(i&&i.transitioning)return;r.collapse("hide"),i||r.data("collapse",null)}this.$element[t](0),this.transition("addClass",e.Event("show"),"shown"),e.support.transition&&this.$element[t](this.$element[0][n])},hide:function(){var t;if(this.transitioning)return;t=this.dimension(),this.reset(this.$element[t]()),this.transition("removeClass",e.Event("hide"),"hidden"),this.$element[t](0)},reset:function(e){var t=this.dimension();return this.$element.removeClass("collapse")[t](e||"auto")[0].offsetWidth,this.$element[e!==null?"addClass":"removeClass"]("collapse"),this},transition:function(t,n,r){var i=this,s=function(){n.type=="show"&&i.reset(),i.transitioning=0,i.$element.trigger(r)};this.$element.trigger(n);if(n.isDefaultPrevented())return;this.transitioning=1,this.$element[t]("in"),e.support.transition&&this.$element.hasClass("collapse")?this.$element.one(e.support.transition.end,s):s()},toggle:function(){this[this.$element.hasClass("in")?"hide":"show"]()}},e.fn.collapse=function(n){return this.each(function(){var r=e(this),i=r.data("collapse"),s=typeof n=="object"&&n;i||r.data("collapse",i=new t(this,s)),typeof n=="string"&&i[n]()})},e.fn.collapse.defaults={toggle:!0},e.fn.collapse.Constructor=t,e(function(){e("body").on("click.collapse.data-api","[data-toggle=collapse]",function(t){var n=e(this),r,i=n.attr("data-target")||t.preventDefault()||(r=n.attr("href"))&&r.replace(/.*(?=#[^\s]+$)/,""),s=e(i).data("collapse")?"toggle":n.data();n[e(i).hasClass("in")?"addClass":"removeClass"]("collapsed"),e(i).collapse(s)})})}(window.jQuery),!function(e){"use strict";function r(){i(e(t)).removeClass("open")}function i(t){var n=t.attr("data-target"),r;return n||(n=t.attr("href"),n=n&&/#/.test(n)&&n.replace(/.*(?=#[^\s]*$)/,"")),r=e(n),r.length||(r=t.parent()),r}var t="[data-toggle=dropdown]",n=function(t){var n=e(t).on("click.dropdown.data-api",this.toggle);e("html").on("click.dropdown.data-api",function(){n.parent().removeClass("open")})};n.prototype={constructor:n,toggle:function(t){var n=e(this),s,o;if(n.is(".disabled, :disabled"))return;return s=i(n),o=s.hasClass("open"),r(),o||(s.toggleClass("open"),n.focus()),!1},keydown:function(t){var n,r,s,o,u,a;if(!/(38|40|27)/.test(t.keyCode))return;n=e(this),t.preventDefault(),t.stopPropagation();if(n.is(".disabled, :disabled"))return;o=i(n),u=o.hasClass("open");if(!u||u&&t.keyCode==27)return n.click();r=e("[role=menu] li:not(.divider) a",o);if(!r.length)return;a=r.index(r.filter(":focus")),t.keyCode==38&&a>0&&a--,t.keyCode==40&&a').appendTo(document.body),this.options.backdrop!="static"&&this.$backdrop.click(e.proxy(this.hide,this)),i&&this.$backdrop[0].offsetWidth,this.$backdrop.addClass("in"),i?this.$backdrop.one(e.support.transition.end,t):t()}else!this.isShown&&this.$backdrop?(this.$backdrop.removeClass("in"),e.support.transition&&this.$element.hasClass("fade")?this.$backdrop.one(e.support.transition.end,e.proxy(this.removeBackdrop,this)):this.removeBackdrop()):t&&t()}},e.fn.modal=function(n){return this.each(function(){var r=e(this),i=r.data("modal"),s=e.extend({},e.fn.modal.defaults,r.data(),typeof n=="object"&&n);i||r.data("modal",i=new t(this,s)),typeof n=="string"?i[n]():s.show&&i.show()})},e.fn.modal.defaults={backdrop:!0,keyboard:!0,show:!0},e.fn.modal.Constructor=t,e(function(){e("body").on("click.modal.data-api",'[data-toggle="modal"]',function(t){var n=e(this),r=n.attr("href"),i=e(n.attr("data-target")||r&&r.replace(/.*(?=#[^\s]+$)/,"")),s=i.data("modal")?"toggle":e.extend({remote:!/#/.test(r)&&r},i.data(),n.data());t.preventDefault(),i.modal(s).one("hide",function(){n.focus()})})})}(window.jQuery),!function(e){"use strict";var t=function(e,t){this.init("tooltip",e,t)};t.prototype={constructor:t,init:function(t,n,r){var i,s;this.type=t,this.$element=e(n),this.options=this.getOptions(r),this.enabled=!0,this.options.trigger=="click"?this.$element.on("click."+this.type,this.options.selector,e.proxy(this.toggle,this)):this.options.trigger!="manual"&&(i=this.options.trigger=="hover"?"mouseenter":"focus",s=this.options.trigger=="hover"?"mouseleave":"blur",this.$element.on(i+"."+this.type,this.options.selector,e.proxy(this.enter,this)),this.$element.on(s+"."+this.type,this.options.selector,e.proxy(this.leave,this))),this.options.selector?this._options=e.extend({},this.options,{trigger:"manual",selector:""}):this.fixTitle()},getOptions:function(t){return t=e.extend({},e.fn[this.type].defaults,t,this.$element.data()),t.delay&&typeof t.delay=="number"&&(t.delay={show:t.delay,hide:t.delay}),t},enter:function(t){var n=e(t.currentTarget)[this.type](this._options).data(this.type);if(!n.options.delay||!n.options.delay.show)return n.show();clearTimeout(this.timeout),n.hoverState="in",this.timeout=setTimeout(function(){n.hoverState=="in"&&n.show()},n.options.delay.show)},leave:function(t){var n=e(t.currentTarget)[this.type](this._options).data(this.type);this.timeout&&clearTimeout(this.timeout);if(!n.options.delay||!n.options.delay.hide)return n.hide();n.hoverState="out",this.timeout=setTimeout(function(){n.hoverState=="out"&&n.hide()},n.options.delay.hide)},show:function(){var e,t,n,r,i,s,o;if(this.hasContent()&&this.enabled){e=this.tip(),this.setContent(),this.options.animation&&e.addClass("fade"),s=typeof this.options.placement=="function"?this.options.placement.call(this,e[0],this.$element[0]):this.options.placement,t=/in/.test(s),e.remove().css({top:0,left:0,display:"block"}).appendTo(t?this.$element:document.body),n=this.getPosition(t),r=e[0].offsetWidth,i=e[0].offsetHeight;switch(t?s.split(" ")[1]:s){case"bottom":o={top:n.top+n.height,left:n.left+n.width/2-r/2};break;case"top":o={top:n.top-i,left:n.left+n.width/2-r/2};break;case"left":o={top:n.top+n.height/2-i/2,left:n.left-r};break;case"right":o={top:n.top+n.height/2-i/2,left:n.left+n.width}}e.css(o).addClass(s).addClass("in")}},setContent:function(){var e=this.tip(),t=this.getTitle();e.find(".tooltip-inner")[this.options.html?"html":"text"](t),e.removeClass("fade in top bottom left right")},hide:function(){function r(){var t=setTimeout(function(){n.off(e.support.transition.end).remove()},500);n.one(e.support.transition.end,function(){clearTimeout(t),n.remove()})}var t=this,n=this.tip();return n.removeClass("in"),e.support.transition&&this.$tip.hasClass("fade")?r():n.remove(),this},fixTitle:function(){var e=this.$element;(e.attr("title")||typeof e.attr("data-original-title")!="string")&&e.attr("data-original-title",e.attr("title")||"").removeAttr("title")},hasContent:function(){return this.getTitle()},getPosition:function(t){return e.extend({},t?{top:0,left:0}:this.$element.offset(),{width:this.$element[0].offsetWidth,height:this.$element[0].offsetHeight})},getTitle:function(){var e,t=this.$element,n=this.options;return e=t.attr("data-original-title")||(typeof n.title=="function"?n.title.call(t[0]):n.title),e},tip:function(){return this.$tip=this.$tip||e(this.options.template)},validate:function(){this.$element[0].parentNode||(this.hide(),this.$element=null,this.options=null)},enable:function(){this.enabled=!0},disable:function(){this.enabled=!1},toggleEnabled:function(){this.enabled=!this.enabled},toggle:function(){this[this.tip().hasClass("in")?"hide":"show"]()},destroy:function(){this.hide().$element.off("."+this.type).removeData(this.type)}},e.fn.tooltip=function(n){return this.each(function(){var r=e(this),i=r.data("tooltip"),s=typeof n=="object"&&n;i||r.data("tooltip",i=new t(this,s)),typeof n=="string"&&i[n]()})},e.fn.tooltip.Constructor=t,e.fn.tooltip.defaults={animation:!0,placement:"top",selector:!1,template:'
',trigger:"hover",title:"",delay:0,html:!0}}(window.jQuery),!function(e){"use strict";var t=function(e,t){this.init("popover",e,t)};t.prototype=e.extend({},e.fn.tooltip.Constructor.prototype,{constructor:t,setContent:function(){var e=this.tip(),t=this.getTitle(),n=this.getContent();e.find(".popover-title")[this.options.html?"html":"text"](t),e.find(".popover-content > *")[this.options.html?"html":"text"](n),e.removeClass("fade top bottom left right in")},hasContent:function(){return this.getTitle()||this.getContent()},getContent:function(){var e,t=this.$element,n=this.options;return e=t.attr("data-content")||(typeof n.content=="function"?n.content.call(t[0]):n.content),e},tip:function(){return this.$tip||(this.$tip=e(this.options.template)),this.$tip},destroy:function(){this.hide().$element.off("."+this.type).removeData(this.type)}}),e.fn.popover=function(n){return this.each(function(){var r=e(this),i=r.data("popover"),s=typeof n=="object"&&n;i||r.data("popover",i=new t(this,s)),typeof n=="string"&&i[n]()})},e.fn.popover.Constructor=t,e.fn.popover.defaults=e.extend({},e.fn.tooltip.defaults,{placement:"right",trigger:"click",content:"",template:'

'})}(window.jQuery),!function(e){"use strict";function t(t,n){var r=e.proxy(this.process,this),i=e(t).is("body")?e(window):e(t),s;this.options=e.extend({},e.fn.scrollspy.defaults,n),this.$scrollElement=i.on("scroll.scroll-spy.data-api",r),this.selector=(this.options.target||(s=e(t).attr("href"))&&s.replace(/.*(?=#[^\s]+$)/,"")||"")+" .nav li > a",this.$body=e("body"),this.refresh(),this.process()}t.prototype={constructor:t,refresh:function(){var t=this,n;this.offsets=e([]),this.targets=e([]),n=this.$body.find(this.selector).map(function(){var t=e(this),n=t.data("target")||t.attr("href"),r=/^#\w/.test(n)&&e(n);return r&&r.length&&[[r.position().top,n]]||null}).sort(function(e,t){return e[0]-t[0]}).each(function(){t.offsets.push(this[0]),t.targets.push(this[1])})},process:function(){var e=this.$scrollElement.scrollTop()+this.options.offset,t=this.$scrollElement[0].scrollHeight||this.$body[0].scrollHeight,n=t-this.$scrollElement.height(),r=this.offsets,i=this.targets,s=this.activeTarget,o;if(e>=n)return s!=(o=i.last()[0])&&this.activate(o);for(o=r.length;o--;)s!=i[o]&&e>=r[o]&&(!r[o+1]||e<=r[o+1])&&this.activate(i[o])},activate:function(t){var n,r;this.activeTarget=t,e(this.selector).parent(".active").removeClass("active"),r=this.selector+'[data-target="'+t+'"],'+this.selector+'[href="'+t+'"]',n=e(r).parent("li").addClass("active"),n.parent(".dropdown-menu").length&&(n=n.closest("li.dropdown").addClass("active")),n.trigger("activate")}},e.fn.scrollspy=function(n){return this.each(function(){var r=e(this),i=r.data("scrollspy"),s=typeof n=="object"&&n;i||r.data("scrollspy",i=new t(this,s)),typeof n=="string"&&i[n]()})},e.fn.scrollspy.Constructor=t,e.fn.scrollspy.defaults={offset:10},e(window).on("load",function(){e('[data-spy="scroll"]').each(function(){var t=e(this);t.scrollspy(t.data())})})}(window.jQuery),!function(e){"use strict";var t=function(t){this.element=e(t)};t.prototype={constructor:t,show:function(){var t=this.element,n=t.closest("ul:not(.dropdown-menu)"),r=t.attr("data-target"),i,s,o;r||(r=t.attr("href"),r=r&&r.replace(/.*(?=#[^\s]*$)/,""));if(t.parent("li").hasClass("active"))return;i=n.find(".active a").last()[0],o=e.Event("show",{relatedTarget:i}),t.trigger(o);if(o.isDefaultPrevented())return;s=e(r),this.activate(t.parent("li"),n),this.activate(s,s.parent(),function(){t.trigger({type:"shown",relatedTarget:i})})},activate:function(t,n,r){function o(){i.removeClass("active").find("> .dropdown-menu > .active").removeClass("active"),t.addClass("active"),s?(t[0].offsetWidth,t.addClass("in")):t.removeClass("fade"),t.parent(".dropdown-menu")&&t.closest("li.dropdown").addClass("active"),r&&r()}var i=n.find("> .active"),s=r&&e.support.transition&&i.hasClass("fade");s?i.one(e.support.transition.end,o):o(),i.removeClass("in")}},e.fn.tab=function(n){return this.each(function(){var r=e(this),i=r.data("tab");i||r.data("tab",i=new t(this)),typeof n=="string"&&i[n]()})},e.fn.tab.Constructor=t,e(function(){e("body").on("click.tab.data-api",'[data-toggle="tab"], [data-toggle="pill"]',function(t){t.preventDefault(),e(this).tab("show")})})}(window.jQuery),!function(e){"use strict";var t=function(t,n){this.$element=e(t),this.options=e.extend({},e.fn.typeahead.defaults,n),this.matcher=this.options.matcher||this.matcher,this.sorter=this.options.sorter||this.sorter,this.highlighter=this.options.highlighter||this.highlighter,this.updater=this.options.updater||this.updater,this.$menu=e(this.options.menu).appendTo("body"),this.source=this.options.source,this.shown=!1,this.listen()};t.prototype={constructor:t,select:function(){var e=this.$menu.find(".active").attr("data-value");return this.$element.val(this.updater(e)).change(),this.hide()},updater:function(e){return e},show:function(){var t=e.extend({},this.$element.offset(),{height:this.$element[0].offsetHeight});return this.$menu.css({top:t.top+t.height,left:t.left}),this.$menu.show(),this.shown=!0,this},hide:function(){return this.$menu.hide(),this.shown=!1,this},lookup:function(t){var n;return this.query=this.$element.val(),!this.query||this.query.length"+t+""})},render:function(t){var n=this;return t=e(t).map(function(t,r){return t=e(n.options.item).attr("data-value",r),t.find("a").html(n.highlighter(r)),t[0]}),t.first().addClass("active"),this.$menu.html(t),this},next:function(t){var n=this.$menu.find(".active").removeClass("active"),r=n.next();r.length||(r=e(this.$menu.find("li")[0])),r.addClass("active")},prev:function(e){var t=this.$menu.find(".active").removeClass("active"),n=t.prev();n.length||(n=this.$menu.find("li").last()),n.addClass("active")},listen:function(){this.$element.on("blur",e.proxy(this.blur,this)).on("keypress",e.proxy(this.keypress,this)).on("keyup",e.proxy(this.keyup,this)),(e.browser.chrome||e.browser.webkit||e.browser.msie)&&this.$element.on("keydown",e.proxy(this.keydown,this)),this.$menu.on("click",e.proxy(this.click,this)).on("mouseenter","li",e.proxy(this.mouseenter,this))},move:function(e){if(!this.shown)return;switch(e.keyCode){case 9:case 13:case 27:e.preventDefault();break;case 38:e.preventDefault(),this.prev();break;case 40:e.preventDefault(),this.next()}e.stopPropagation()},keydown:function(t){this.suppressKeyPressRepeat=!~e.inArray(t.keyCode,[40,38,9,13,27]),this.move(t)},keypress:function(e){if(this.suppressKeyPressRepeat)return;this.move(e)},keyup:function(e){switch(e.keyCode){case 40:case 38:break;case 9:case 13:if(!this.shown)return;this.select();break;case 27:if(!this.shown)return;this.hide();break;default:this.lookup()}e.stopPropagation(),e.preventDefault()},blur:function(e){var t=this;setTimeout(function(){t.hide()},150)},click:function(e){e.stopPropagation(),e.preventDefault(),this.select()},mouseenter:function(t){this.$menu.find(".active").removeClass("active"),e(t.currentTarget).addClass("active")}},e.fn.typeahead=function(n){return this.each(function(){var r=e(this),i=r.data("typeahead"),s=typeof n=="object"&&n;i||r.data("typeahead",i=new t(this,s)),typeof n=="string"&&i[n]()})},e.fn.typeahead.defaults={source:[],items:8,menu:'',item:'
  • ',minLength:1},e.fn.typeahead.Constructor=t,e(function(){e("body").on("focus.typeahead.data-api",'[data-provide="typeahead"]',function(t){var n=e(this);if(n.data("typeahead"))return;t.preventDefault(),n.typeahead(n.data())})})}(window.jQuery),!function(e){"use strict";var t=function(t,n){this.options=e.extend({},e.fn.affix.defaults,n),this.$window=e(window).on("scroll.affix.data-api",e.proxy(this.checkPosition,this)),this.$element=e(t),this.checkPosition()};t.prototype.checkPosition=function(){if(!this.$element.is(":visible"))return;var t=e(document).height(),n=this.$window.scrollTop(),r=this.$element.offset(),i=this.options.offset,s=i.bottom,o=i.top,u="affix affix-top affix-bottom",a;typeof i!="object"&&(s=o=i),typeof o=="function"&&(o=i.top()),typeof s=="function"&&(s=i.bottom()),a=this.unpin!=null&&n+this.unpin<=r.top?!1:s!=null&&r.top+this.$element.height()>=t-s?"bottom":o!=null&&n<=o?"top":!1;if(this.affixed===a)return;this.affixed=a,this.unpin=a=="bottom"?r.top-n:null,this.$element.removeClass(u).addClass("affix"+(a?"-"+a:""))},e.fn.affix=function(n){return this.each(function(){var r=e(this),i=r.data("affix"),s=typeof n=="object"&&n;i||r.data("affix",i=new t(this,s)),typeof n=="string"&&i[n]()})},e.fn.affix.Constructor=t,e.fn.affix.defaults={offset:0},e(window).on("load",function(){e('[data-spy="affix"]').each(function(){var t=e(this),n=t.data();n.offset=n.offset||{},n.offsetBottom&&(n.offset.bottom=n.offsetBottom),n.offsetTop&&(n.offset.top=n.offsetTop),t.affix(n)})})}(window.jQuery); -------------------------------------------------------------------------------- /SmallestDotNet/testjs.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | SmallestDotNet - Get the Smallest .NET Framework Download possible 14 | 15 | 16 | 17 | 18 | 19 |
    20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 |
    28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /SmallestDotNetLib/BrowserSupport.cs: -------------------------------------------------------------------------------- 1 | namespace SmallestDotNetLib 2 | { 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | 6 | public class Browser 7 | { 8 | public string BrowserString { get; set; } 9 | public string BrowserPretty { get; set; } 10 | public bool CanGetCLRVersion { get; set; } 11 | } 12 | 13 | public class BrowserSupport 14 | { 15 | private static Browser Chrome = new Browser { BrowserPretty = "Google Chrome", BrowserString = "Chrome", CanGetCLRVersion = false }; 16 | private static Browser Firefox = new Browser { BrowserPretty = "Mozilla Firefox", BrowserString = "Firefox", CanGetCLRVersion = false }; 17 | private static Browser InternetExplorer = new Browser { BrowserPretty = "Internet Explorer", BrowserString = "Trident", CanGetCLRVersion = true }; 18 | public static List Browsers = new List 19 | { 20 | Chrome, 21 | Firefox, 22 | InternetExplorer 23 | }; 24 | 25 | public static Browser GetBrowser(string UserAgent) 26 | { 27 | return Browsers.FirstOrDefault(b => UserAgent.Contains(b.BrowserString)); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /SmallestDotNetLib/CLRVersion.cs: -------------------------------------------------------------------------------- 1 | namespace SmallestDotNetLib 2 | { 3 | /// 4 | /// Represent A .NET CLR Version 5 | /// 6 | public class CLRVersion 7 | { 8 | /// 9 | /// The Major Version 10 | /// 11 | public int Major { get; set; } 12 | 13 | /// 14 | /// The Minor Version 15 | /// 16 | public int Minor { get; set;} 17 | 18 | /// 19 | /// The .NET CLR Profile (Full or Client) 20 | /// 21 | public string Profile { get; set; } 22 | 23 | /// 24 | /// Service Pack Version, null if none 25 | /// 26 | public int? ServicePack { get; set; } 27 | 28 | /// 29 | /// A URL to download the CLR Version Installer 30 | /// 31 | public string Url { get; set; } 32 | 33 | /// 34 | /// A Human readable string of the .NET CLR Version 35 | /// 36 | public string PrettyVersion { get; set; } 37 | 38 | 39 | public override bool Equals(object obj) 40 | { 41 | var version = (CLRVersion)obj; 42 | 43 | return version.Major == this.Major && version.Minor == this.Minor && version.Profile == this.Profile && version.ServicePack == this.ServicePack; 44 | } 45 | 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /SmallestDotNetLib/CLRVersions.cs: -------------------------------------------------------------------------------- 1 | namespace SmallestDotNetLib 2 | { 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | 7 | /// 8 | /// Contains Methods for discovering information about CLR Versions 9 | /// 10 | public class CLRVersions 11 | { 12 | public static CLRVersion NET10Full = new CLRVersion() { Major = 1, Minor = 0, Profile = "full", PrettyVersion = ".NET 1.0" }; 13 | public static CLRVersion NET11Full = new CLRVersion() { Major = 1, Minor = 1, Profile = "full", Url = Constants.Version11URL, PrettyVersion = ".NET 1.1" }; 14 | public static CLRVersion NET20Full = new CLRVersion() { Major = 2, Minor = 0, Profile = "full", Url = Constants.Version20URL, PrettyVersion = ".NET 2.0" }; 15 | public static CLRVersion NET30Full = new CLRVersion() { Major = 3, Minor = 0, Profile = "full", Url = Constants.Version30URL, PrettyVersion = ".NET 3.0" }; 16 | public static CLRVersion NET35Full = new CLRVersion() { Major = 3, Minor = 5, Profile = "full", PrettyVersion = ".NET 3.5" }; 17 | public static CLRVersion NET35SP1Client = new CLRVersion() { Major = 3, Minor = 5, Profile = "client", ServicePack = 1, Url = Constants.Version35SP1ClientURL, PrettyVersion = ".NET 3.5 Client SP1" }; 18 | public static CLRVersion NET35SP1Full = new CLRVersion() { Major = 3, Minor = 5, Profile = "full", ServicePack = 1, Url = Constants.Version35SP1FullURL, PrettyVersion = ".NET 3.5 SP1" }; 19 | public static CLRVersion NET40Client = new CLRVersion() { Major = 4, Minor = 0, Profile = "client", Url = Constants.Version40ClientURL, PrettyVersion = ".NET 4.0 Client" }; 20 | public static CLRVersion NET40Full = new CLRVersion() { Major = 4, Minor = 0, Profile = "full", Url = Constants.Version40FullURL, PrettyVersion = ".NET 4.0" }; 21 | public static CLRVersion NET45Full = new CLRVersion() { Major = 4, Minor = 5, Profile = "full", Url = Constants.Version45URL, PrettyVersion = ".NET 4.5" }; 22 | public static CLRVersion NET46Full = new CLRVersion() { Major = 4, Minor = 6, Profile = "full", Url = Constants.Version46URL, PrettyVersion = ".NET 4.6" }; 23 | 24 | /// 25 | /// A Dictionary of CLR Versions with information 26 | /// 27 | public static Dictionary Versions = new Dictionary 28 | { 29 | {Constants.Version10Full, NET10Full}, 30 | {Constants.Version11Full, NET11Full}, 31 | {Constants.Version20Full, NET20Full}, 32 | {Constants.Version30Full, NET30Full}, 33 | {Constants.Version35Full, NET35Full}, 34 | {Constants.Version35SP1Client, NET35SP1Client}, 35 | {Constants.Version35SP1Full, NET35SP1Full}, 36 | {Constants.Version40Client, NET40Client}, 37 | {Constants.Version40Full, NET40Full}, 38 | {Constants.Version45Full, NET45Full}, 39 | {Constants.Version46Full, NET46Full} 40 | }; 41 | 42 | /// 43 | /// Gets all downloadable CLR Versions represented in the Versions Dictionary 44 | /// 45 | /// A Dictionary containing Versions with a download url 46 | public static Dictionary GetDownloadableVersions() 47 | { 48 | return Versions.Where(pair => pair.Value.Url != "").ToDictionary(pair => pair.Key, pair => pair.Value); 49 | } 50 | 51 | public string UserAgent { get; set; } 52 | public CLRVersions(string userAgent) 53 | { 54 | UserAgent = userAgent; 55 | } 56 | 57 | public Dictionary GetInstalledVersions() 58 | { 59 | var results = new Dictionary(); 60 | 61 | var foundVersions = UserAgent.Split(new[] { ";" }, StringSplitOptions.RemoveEmptyEntries).Where(s => s.Contains(".NET")); 62 | 63 | 64 | foreach (string match in foundVersions) 65 | { 66 | var v = match.Trim(); 67 | //this really sucks and makes me mad 68 | if (v.Contains(Constants.Version35Full) && !v.Contains(Constants.Version35SP1Client) && !v.Contains(Constants.Version35SP1Full)) v = Constants.Version35Full; 69 | if (v.Contains(Constants.Version30Full)) v = Constants.Version30Full; 70 | if (v.Contains(Constants.Version20Full)) v = Constants.Version20Full; 71 | if (v.Contains(Constants.Version11Full)) v = Constants.Version11Full; 72 | if (v.Contains(Constants.Version10Full)) v = Constants.Version10Full; 73 | if (Versions.ContainsKey(v)) 74 | { 75 | var version = Versions[v]; 76 | results.Add(v, version); 77 | } 78 | } 79 | 80 | if (Helpers.HasWindows8(UserAgent)) 81 | { 82 | results.Add(Constants.Version45Full, Versions[Constants.Version45Full]); 83 | } 84 | 85 | return results; 86 | } 87 | 88 | public CLRVersion GetLatestVersion() 89 | { 90 | var installedVersions = GetInstalledVersions(); 91 | 92 | installedVersions = installedVersions.OrderByDescending(p => p.Value.Major) 93 | .ThenByDescending(p => p.Value.Minor) 94 | .ThenByDescending(p => p.Value.Profile) 95 | .ThenByDescending(p => p.Value.ServicePack ?? 0) 96 | .ToDictionary(p => p.Key, p => p.Value); 97 | 98 | if (installedVersions.Any()) 99 | { 100 | return installedVersions.First().Value; 101 | } 102 | 103 | return null; 104 | } 105 | 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /SmallestDotNetLib/Constants.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | /// 5 | /// A Place for the Strings 6 | /// 7 | public static class Constants 8 | { 9 | public static readonly string DotNet = "4.8"; 10 | public static readonly string DotNetOnline = String.Format(".NET {1} Web", Version48WebUrl, DotNet); 11 | public static readonly string DotNetOffline = String.Format(".NET {1} Offline", Version48OfflineUrl, DotNet); 12 | 13 | // this variable can be updated with whatever constant is holiding the latest release URL and then should cascade to the Get.NET link 14 | public static readonly string LatestDotNetRawUrl = Version48OfflineUrl; 15 | 16 | 17 | public const double DotNetOnlineMB = Version48WebMB; 18 | public const double DotNetOfflineMB = Version48OfflineMB; 19 | 20 | public const string WindowsUpdate = "Windows Update"; 21 | public const string WhyItIsSmall = @" The .NET installer is smart enough to look at your system and automatically download the smallest upgrade package possible. 22 | For you, it'll probably be around {0} megabytes total."; 23 | 24 | public const string InferredText = "You have at least {0} on your machine. We can only infer this as the user agent of your browser doesn't give us the version. Try the .Net Checker application to get more accurate version information."; 25 | public const string CheckerFound = "The .Net Checker application determined that you have {0} on your machine. "; 26 | public const string CheckerFoundNotExact = "The application was not able to determine the exact version you have. Please log an issue including this information: releaseKey={1} so we can get it exact in the future."; 27 | 28 | public static readonly Dictionary OldWindows = new Dictionary 29 | { 30 | {"Windows NT 5.0", "Windows 2000"}, 31 | {"Windows 95", "Windows 95"}, 32 | {"Windows 98", "Windows 98"} 33 | }; 34 | 35 | /// 36 | /// The .Net versions (4.5 and above) keyed by the registry key value. 37 | /// 38 | public static readonly SortedDictionary ReleaseVersions = new SortedDictionary 39 | { 40 | { int.MinValue, "4.5" }, 41 | { 378389, "4.5" }, 42 | { 378675, "4.5.1" }, 43 | { 378758, "4.5.1" }, 44 | { 379893, "4.5.2" }, 45 | { 381029, "4.6 Preview" }, 46 | { 393273, "4.6 RC1" }, 47 | { 393292, "4.6 RC2" }, 48 | { 393295, "4.6" }, 49 | { 393297, "4.6" }, 50 | { 394254, "4.6.1" }, 51 | { 394271, "4.6.1" }, 52 | { 394747, "4.6.2 Preview" }, 53 | { 394748, "4.6.2 Preview" }, 54 | { 394757, "4.6.2 Preview" }, 55 | { 394802, "4.6.2" }, 56 | { 394806, "4.6.2" }, 57 | { 460798, "4.7" }, 58 | { 460805, "4.7" }, 59 | { 461308, "4.7.1" }, 60 | { 461310, "4.7.1" }, 61 | { 461808, "4.7.2" }, 62 | { 461814, "4.7.2" }, 63 | { 528040, "4.8" }, 64 | { 528049, "4.8" }, 65 | }; 66 | 67 | public const string Windows8 = "Windows NT 6.2"; 68 | public const string Windows81 = "Windows NT 6.3"; 69 | public const string Windows10 = "Windows NT 10"; 70 | 71 | public const string Version461Full = ".NET 4.6.1"; 72 | public const string Version46Full = ".NET 4.6"; 73 | public const string Version45Full = ".NET 4.5"; 74 | public const string Version40Full = ".NET4.0E"; 75 | public const string Version40Client = ".NET4.0C"; 76 | public const string Version35SP1Full = ".NET CLR 3.5.30729"; 77 | public const string Version35SP1Client = ".NET Client 3.5"; 78 | public const string Version35Full = ".NET CLR 3.5"; 79 | public const string Version30Full = ".NET CLR 3.0"; 80 | public const string Version20Full = ".NET CLR 2.0"; 81 | public const string Version11Full = ".NET CLR 1.1"; 82 | public const string Version10Full = ".NET CLR 1.0"; 83 | 84 | 85 | private const string Version48WebUrl = "https://dotnet.microsoft.com/download/thank-you/net48"; // or "https://go.microsoft.com/fwlink/?LinkId=2085155"; 86 | private const string Version48OfflineUrl = "https://dotnet.microsoft.com/download/thank-you/net48-offline"; // Or "https://go.microsoft.com/fwlink/?linkid=2088631" 87 | 88 | private const string Version472WebUrl = "https://go.microsoft.com/fwlink/?LinkId=863262"; 89 | private const string Version472OfflineUrl = "https://go.microsoft.com/fwlink/?LinkId=863265"; 90 | 91 | private const string Version461WebUrl = "https://www.microsoft.com/en-us/download/details.aspx?id=49981"; 92 | private const string Version461OfflineUrl = "https://www.microsoft.com/en-us/download/details.aspx?id=49982"; 93 | 94 | private const string Version46WebUrl = "https://go.microsoft.com/fwlink/?LinkId=528259"; 95 | private const string Version46OfflineUrl = "https://go.microsoft.com/fwlink/?LinkId=528233"; 96 | 97 | public const string Version11URL = "https://www.microsoft.com/downloads/details.aspx?FamilyID=a8f5654f-088e-40b2-bbdb-a83353618b38&DisplayLang=en"; 98 | public const string Version20URL = "https://www.microsoft.com/downloads/details.aspx?familyid=5B2C0358-915B-4EB5-9B1D-10E506DA9D0F&displaylang=en"; 99 | public const string Version30URL = "https://www.microsoft.com/downloads/details.aspx?FamilyId=10CC340B-F857-4A14-83F5-25634C3BF043&displaylang=en"; 100 | public const string Version35SP1FullURL = "https://www.microsoft.com/en-us/download/details.aspx?id=22"; 101 | public const string Version35SP1ClientURL = "https://www.microsoft.com/downloads/details.aspx?FamilyId=8CEA6CD1-15BC-4664-B27D-8CEBA808B28B&displaylang=en"; 102 | public const string Version40FullURL = "https://www.microsoft.com/downloads/details.aspx?FamilyID=9f5e8774-c8dc-4ff6-8285-03a4c387c0db&displaylang=en"; 103 | public const string Version40ClientURL = "https://www.microsoft.com/downloads/details.aspx?FamilyID=68a7173d-7ee5-4213-a06f-f2e943ec9249&displaylang=en"; 104 | public const string Version45URL = "https://www.microsoft.com/en-us/download/details.aspx?id=30653"; 105 | public const string Version46URL = "https://www.microsoft.com/en-us/download/details.aspx?id=30653"; 106 | 107 | private const double Version48WebMB = 1.4; 108 | private const double Version48OfflineMB = 69.3; 109 | private const double Version472WebMB = 1.4; 110 | private const double Version472OfflineMB = 63.8; 111 | private const double Version461WebMB = 1.4; 112 | private const double Version461OfflineMB = 64.5; 113 | private const double Version46WebMB = 1.4; 114 | private const int Version46OfflineMB = 63; 115 | public const int Version3OfflineMB = 38; 116 | public const int Version2OfflineMB = 15; 117 | public const int Version1OfflineMB = 7; 118 | } 119 | -------------------------------------------------------------------------------- /SmallestDotNetLib/Helpers.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using SmallestDotNetLib; 5 | 6 | /// 7 | /// A Class containing general purposes methods 8 | /// 9 | public class Helpers 10 | { 11 | public static UpdateInformationResponse GetUpdateInformation(string userAgent) 12 | { 13 | return GetUpdateInformation(userAgent, null, 0); 14 | } 15 | 16 | public static UpdateInformationResponse GetUpdateInformation(string UserAgent, string realVersion) 17 | { 18 | return GetUpdateInformation(UserAgent, realVersion, 0); 19 | } 20 | 21 | public static UpdateInformationResponse GetUpdateInformation(string UserAgent, string realVersion, int releaseKey) 22 | { 23 | bool net4 = false; 24 | string netInfoString = ""; 25 | var response = new UpdateInformationResponse(); 26 | 27 | // We should check this first since we don't need to check .NET versions if they can't have .NET versions 28 | // Check for windows phone first as it may contain 'Mac' in User Agent 29 | if (UserAgent.Contains("Windows Phone")) 30 | { 31 | response.Text = "It looks like you're running a Windows Phone, awesome! There's no .NET Framework download for the Windows phone, but you might check out the Windows Dev Center or the Windows Phone Store"; 32 | return response; 33 | } 34 | if (UserAgent.Contains("Mac")) 35 | { 36 | response.Text = "It looks like you're running a Mac or an iPhone. You currently have two options: .NET Core for Mac, or Mono, which is an Open Source platform that can run .NET code on a Mac. For your mobile devices, check out Xamarin and write .NET apps for iOS and Android!"; 37 | return response; 38 | } 39 | if (UserAgent.Contains("nix")) 40 | { 41 | response.Text = "It looks like you're running a Unix machine. There's no .NET Framework download from Microsoft for Unix, but you might check out Mono, which is an Open Source platform that can run .NET code on Unix."; 42 | return response; 43 | } 44 | 45 | response.CanRunCheckApp = true; 46 | response.VersionCanBeDetermined = true; 47 | 48 | net4 = GetWindows8Or10Message(UserAgent, ref netInfoString) || Get40Message(UserAgent, ref netInfoString); 49 | if (!string.IsNullOrEmpty(realVersion) || releaseKey != 0) 50 | { 51 | netInfoString = GetRealVersionMessage(ref realVersion, releaseKey); 52 | } 53 | else if (Helpers.Has35(UserAgent) || Helpers.Has35SP1C(UserAgent) || Helpers.Has35SP1E(UserAgent)) 54 | { 55 | netInfoString += DotNet3_5Message((Helpers.Has35SP1C(UserAgent) || Helpers.Has35SP1E(UserAgent)), net4); 56 | } 57 | else if (Helpers.Has30(UserAgent)) 58 | { 59 | netInfoString += DotNet3Message(net4); 60 | } 61 | else if (Helpers.Has20(UserAgent)) 62 | { 63 | netInfoString += DotNet2Message(net4); 64 | } 65 | else if (Helpers.Has11(UserAgent) || Helpers.Has10(UserAgent)) 66 | { 67 | netInfoString += DotNet1Message(net4); 68 | } 69 | else if (!net4) 70 | { 71 | if (UserAgent.Contains("fox")) 72 | { 73 | netInfoString += MessageForBrowser("Firefox"); 74 | } 75 | else if (UserAgent.Contains("Chrome")) 76 | { 77 | netInfoString += MessageForBrowser("Chrome"); 78 | } 79 | else if (UserAgent.Contains("Safari")) // Chrome also uses safari in the user agent so this check must come after 80 | { 81 | netInfoString += MessageForBrowser("Safari"); 82 | } 83 | else 84 | { 85 | netInfoString += UnknownBrowserMessage(); 86 | } 87 | 88 | response.VersionCanBeDetermined = false; 89 | } 90 | 91 | if (response.VersionCanBeDetermined) 92 | { 93 | response.VersionIsLatest = Helpers.CheckVersionLatest(realVersion, ref netInfoString); 94 | } 95 | 96 | //need to see if windows 2000 has the latest version 97 | foreach (KeyValuePair windowsVersion in Constants.OldWindows) 98 | { 99 | netInfoString += CheckDotNet3_5UnSupportedOs(UserAgent, windowsVersion.Key, windowsVersion.Value); 100 | } 101 | 102 | response.Text = netInfoString; 103 | return response; 104 | } 105 | 106 | /// 107 | /// Gets the .Net version based on release key. 108 | /// 109 | /// The release key found in registry. 110 | /// if set to true then an exact match was found; otherwise the return value will contain "X.Y or greater". 111 | /// Version number text e.g. "4.5.1" 112 | private static string GetDotnetVersionFromReleaseKey(int releaseKey, out bool exact) 113 | { 114 | string version; 115 | if (Constants.ReleaseVersions.TryGetValue(releaseKey, out version)) 116 | { 117 | exact = true; 118 | return version; 119 | } 120 | 121 | exact = false; 122 | var releaseVersion = Constants.ReleaseVersions.Last(kvp => kvp.Key < releaseKey); 123 | return releaseVersion.Value + " or greater"; 124 | } 125 | 126 | /// 127 | /// Gets a message based on the "real" version as determined by the .Net Checker application. 128 | /// 129 | /// The real version. 130 | /// The release key. 131 | /// A message like "The .Net Checker application determined that you've got X.Y on your machine." 132 | private static string GetRealVersionMessage(ref string realVersion, int releaseKey) 133 | { 134 | bool exact = true; 135 | if (releaseKey != 0) 136 | { 137 | realVersion = GetDotnetVersionFromReleaseKey(releaseKey, out exact); 138 | } 139 | 140 | return exact 141 | ? string.Format(Constants.CheckerFound, realVersion) 142 | : string.Format(Constants.CheckerFound + Constants.CheckerFoundNotExact, realVersion, releaseKey); 143 | } 144 | 145 | /// 146 | /// Gets a message for the Windows 8 OS. 147 | /// 148 | /// The user agent. 149 | /// The user message. 150 | /// True if the user agent has 151 | private static bool GetWindows8Or10Message(string userAgent, ref string userMessage) 152 | { 153 | bool hasWindows10 = Helpers.HasWindows10(userAgent); 154 | if (Helpers.HasWindows8(userAgent) || hasWindows10) 155 | { 156 | var version = hasWindows10 ? "4.6" : "4.5"; 157 | userMessage += string.Format(Constants.InferredText, version); 158 | return true; 159 | } 160 | 161 | return false; 162 | } 163 | 164 | private static bool Get40Message(string UserAgent, ref string userMessage) 165 | { 166 | 167 | var whichVersion = ""; 168 | var ret = false; 169 | if (Helpers.Has40E(UserAgent)) 170 | { 171 | whichVersion = ".NET 4.0"; 172 | ret = true; 173 | } 174 | else if (Helpers.Has40C(UserAgent)) 175 | { 176 | whichVersion = ".NET 4.0 Client Profile"; 177 | ret = true; 178 | } 179 | 180 | if (ret) 181 | { 182 | userMessage += String.Format(@"You have {0}, this is a recent version of .NET. Download an installer for the newest version {1}.", whichVersion, Constants.DotNetOnline); 183 | } 184 | 185 | return ret; 186 | } 187 | 188 | private static string MessageForBrowser(string browser) 189 | { 190 | return String.Format(@"Looks like you're running {0}. That's totally cool, but I can't tell if you've got .NET installed from {0}. 191 | Consider running this little application, just once, and we'll tell you what version of .NET you're running.", browser); 192 | } 193 | 194 | private static string UnknownBrowserMessage() 195 | { 196 | string explain = String.Format(Constants.WhyItIsSmall, Constants.DotNetOfflineMB); 197 | return String.Format(@"I can't see what browser you have. That's totally cool, but I can't tell if you've got .NET installed. 198 | Consider running this little application, just once, and we'll tell you what version of .NET you're running."); 199 | } 200 | 201 | private static string DotNet1Message(bool hasDotNet4) 202 | { 203 | string explain = String.Format(Constants.WhyItIsSmall, Constants.DotNetOfflineMB - Constants.Version1OfflineMB); 204 | return String.Format("Looks like you've {3} got a pretty old version of .NET. You should make sure your computer is up to date by visiting {0} then downloading the {1} from Microsoft. {2}", Constants.WindowsUpdate, Constants.DotNetOnline, explain, hasDotNet4 ? "also" : ""); 205 | } 206 | 207 | private static string DotNet2Message(bool hasDotNet4) 208 | { 209 | string explain = String.Format(Constants.WhyItIsSmall, Constants.DotNetOfflineMB - Constants.Version2OfflineMB); 210 | return String.Format(@"Looks like you {2} have .NET version 2.0. 211 | That's a fairly recent version of the .NET Framework, but you can upgrade fairly easily to the .NET {4} by downloading the {3} MB isntaller for {0}. {1}", Constants.DotNetOnline, explain, hasDotNet4 ? "also" : "", Constants.DotNetOnlineMB, Constants.DotNet); 212 | } 213 | 214 | private static string DotNet3Message(bool hasDotNet4) 215 | { 216 | string explain = String.Format(Constants.WhyItIsSmall, Constants.DotNetOfflineMB - Constants.Version3OfflineMB); 217 | return String.Format(@"Looks like you {2} have .NET version 3.0. 218 | That's a very recent version of the .NET Framework, but you can upgrade fairly easily to .NET {4} by downloading the {3} MB installer for {0}. {1}", Constants.DotNetOnline, explain, hasDotNet4 ? "also" : "", Constants.DotNetOnlineMB, Constants.DotNet); 219 | } 220 | 221 | private static string DotNet3_5Message(bool hasSp1, bool hasDotNet4) 222 | { 223 | 224 | if (!hasDotNet4) 225 | { 226 | return String.Format(@"You have .NET 3.5{0}, this is a recent version of .NET. Download an installer for the newest version {1}.", hasSp1 ? " Service Pack 1" : "", Constants.DotNetOnline); 227 | } 228 | 229 | return ""; 230 | } 231 | 232 | private static string CheckDotNet3_5UnSupportedOs(string UserAgent, string agent, string friendlyName) 233 | { 234 | if (UserAgent.Contains(agent)) 235 | { 236 | return String.Format("It looks like you're running {1}. Sorry, but .NET 3.5 isn't supported on {1}, but you can still run NET Framework 2.0 SP1", "https://www.microsoft.com/downloads/details.aspx?familyid=79BC3B77-E02C-4AD3-AACF-A7633F706BA5&displaylang=en", friendlyName); 237 | } 238 | 239 | return ""; 240 | } 241 | 242 | private static bool CheckVersionLatest(string realVersion, ref string netInfoString) 243 | { 244 | if (realVersion != null && realVersion.Contains(Constants.DotNet)) 245 | { 246 | netInfoString += String.Format(@"You have {0}, this is a recent version of .NET. Download an installer for the newest version {1}.", Constants.DotNet, Constants.DotNetOnline); 247 | return true; 248 | } 249 | return false; 250 | } 251 | 252 | public static bool Has45(String UserAgent) 253 | { 254 | return UserAgent.StartsWith("4.5"); 255 | } 256 | 257 | public static string GetJsonPayload(String UserAgent) 258 | { 259 | var OperatingSystem = OperatingSystems.GetOperatingSystem(UserAgent); 260 | if (OperatingSystem.LatestCLRVersion != null) 261 | { 262 | var Browser = BrowserSupport.GetBrowser(UserAgent); 263 | 264 | if (Browser.CanGetCLRVersion) 265 | { 266 | var parsedVersions = new CLRVersions(UserAgent); 267 | 268 | var LatestVersion = parsedVersions.GetLatestVersion(); 269 | 270 | var UpToDate = (LatestVersion == OperatingSystem.LatestCLRVersion); 271 | } 272 | } 273 | 274 | return "Not Implemented"; 275 | } 276 | 277 | /// 278 | /// Determines if the User Agent String indicates Windows 8 279 | /// 280 | /// A User Agent String 281 | /// True if user agent contains "Windows NT 6.2" or "Windows NT 6.3" 282 | public static bool HasWindows8(String userAgent) 283 | { 284 | // User Agent from Win 8.1 IE11: 285 | // Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; LCJB; rv:11.0) like Gecko 286 | // User Agent from Windows 10 build 10074 IE11: 287 | // "Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; Touch; MALCJS; rv:11.0) like Gecko"; 288 | return userAgent.Contains(Constants.Windows8) || 289 | (userAgent.Contains(Constants.Windows81) && !userAgent.Contains("MALCJS")); 290 | } 291 | 292 | /// 293 | /// Determines if the User Agent String indicates Windows 8 294 | /// 295 | /// A User Agent String 296 | /// True if user agent contains "Windows NT 10" 297 | public static bool HasWindows10(string userAgent) 298 | { 299 | // User Agent from Win 8.1 IE11: 300 | // Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; LCJB; rv:11.0) like Gecko 301 | // User Agent from Windows 10 build 10074 IE11: 302 | // "Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; Touch; MALCJS; rv:11.0) like Gecko"; 303 | return userAgent.Contains(Constants.Windows10) 304 | || (userAgent.Contains(Constants.Windows81) && userAgent.Contains("MALCJS")); 305 | } 306 | 307 | /// 308 | /// Determines if the User Agent String indicates .NET 4.0 Full 309 | /// 310 | /// A User Agent String 311 | /// 312 | public static bool Has40E(String UserAgent) 313 | { 314 | return UserAgent.Contains(Constants.Version40Full) || UserAgent.StartsWith("4.0"); 315 | } 316 | 317 | /// 318 | /// Determines if the User Agent String indicates .NET 40 Client 319 | /// 320 | /// A User Agent String 321 | /// 322 | public static bool Has40C(String UserAgent) 323 | { 324 | return UserAgent.Contains(Constants.Version40Client) || UserAgent.StartsWith("4.0"); 325 | } 326 | 327 | /// 328 | /// Determines if the User Agent String indicates .NET 3.5 SP1 Full 329 | /// 330 | /// A User Agent String 331 | /// 332 | public static bool Has35SP1E(String UserAgent) 333 | { 334 | return UserAgent.Contains(Constants.Version35SP1Full); 335 | } 336 | 337 | /// 338 | /// Determines if the User Agent String indicates .NET 3.5 SP1 Client 339 | /// 340 | /// A User Agent String 341 | /// 342 | public static bool Has35SP1C(String UserAgent) 343 | { 344 | return UserAgent.Contains(Constants.Version35SP1Client); 345 | } 346 | 347 | /// 348 | /// Determines if the User Agent String indicates .NET 3.5 349 | /// 350 | /// A User Agent String 351 | /// 352 | public static bool Has35(String UserAgent) 353 | { 354 | return UserAgent.Contains(Constants.Version35Full); 355 | } 356 | 357 | /// 358 | /// Determines if the User Agent String indicates .NET 3.0 359 | /// 360 | /// A User Agent String 361 | /// 362 | public static bool Has30(String UserAgent) 363 | { 364 | return UserAgent.Contains(Constants.Version30Full); 365 | } 366 | 367 | /// 368 | /// Determines if the User Agent String indicates .NET 2.0 369 | /// 370 | /// A User Agent String 371 | /// 372 | public static bool Has20(String UserAgent) 373 | { 374 | return UserAgent.Contains(Constants.Version20Full); 375 | } 376 | 377 | /// 378 | /// Determines if the User Agent String indicates .NET 1.1 379 | /// 380 | /// A User Agent String 381 | /// 382 | public static bool Has11(String UserAgent) 383 | { 384 | return UserAgent.Contains(Constants.Version11Full); 385 | } 386 | 387 | /// 388 | /// Determines if the User Agent String indicates .NET 1.0 389 | /// 390 | /// A User Agent String 391 | /// 392 | public static bool Has10(String UserAgent) 393 | { 394 | return UserAgent.Contains(Constants.Version10Full); 395 | } 396 | } 397 | -------------------------------------------------------------------------------- /SmallestDotNetLib/JsonVersions.cs: -------------------------------------------------------------------------------- 1 | namespace SmallestDotNetLib 2 | { 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | 7 | public class JsonVersions 8 | { 9 | /// 10 | /// Writes the Latest Version Json 11 | /// 12 | /// Major Version 13 | /// Minor Version 14 | /// Profile 15 | /// Service Pack 16 | /// A Json String Representing the latest version 17 | public static string WriteLatestVersion(int major, int minor, string profile, int? sp) 18 | { 19 | return String.Format(@"SmallestDotNet.latestVersion = {0};", WriteVersion(major, minor, profile, sp)); 20 | } 21 | 22 | /// 23 | /// Writes the Version Json 24 | /// 25 | /// Major Version 26 | /// Minor Version 27 | /// Profile 28 | /// Service Pack 29 | /// A Json string representing the version 30 | public static string WriteVersion(int major, int minor, string profile, int? sp) 31 | { 32 | return String.Format(@"{{ 33 | major: {0}, 34 | minor: {1}, 35 | profile: ""{2}"", 36 | servicePack: {3} 37 | }}", major, minor, profile, sp.HasValue ? sp.ToString() : "null"); 38 | } 39 | 40 | /// 41 | /// Writes the Version Json 42 | /// 43 | /// CLRVersion Struct 44 | /// A Json string representing the version 45 | public static string WriteVersion(CLRVersion version) 46 | { 47 | return String.Format(@"{{ 48 | major: {0}, 49 | minor: {1}, 50 | profile: ""{2}"", 51 | servicePack: {3} 52 | }}", version.Major, version.Minor, version.Profile, version.ServicePack.HasValue ? version.ServicePack.ToString() : "null"); 53 | } 54 | 55 | /// 56 | /// Write the Download Information Json 57 | /// 58 | /// Major Version 59 | /// Minor Version 60 | /// .NET CLR Profile 61 | /// Service Pack 62 | /// Download URL 63 | /// A Json string representing the version with a download url 64 | public static string WriteVersionWithDownload(int major, int minor, string profile, int? sp, string url) 65 | { 66 | return String.Format(@"{{ 67 | major: {0}, 68 | minor: {1}, 69 | profile: ""{2}"", 70 | servicePack: {3}, 71 | url: {4} 72 | }}", major, minor, profile, sp.HasValue ? sp.ToString() : "null", url); 73 | } 74 | 75 | /// 76 | /// Write the Download Information Json 77 | /// 78 | /// CLRVersion Struct 79 | /// A Json string representing the version with a download url 80 | public static string WriteVersionWithDownload(CLRVersion version) 81 | { 82 | return String.Format(@"{{ 83 | major: {0}, 84 | minor: {1}, 85 | profile: '{2}', 86 | servicePack: {3}, 87 | url: '{4}' 88 | }}", 89 | version.Major, 90 | version.Minor, 91 | version.Profile, 92 | version.ServicePack.HasValue ? version.ServicePack.Value.ToString() : "null", 93 | version.Url); 94 | } 95 | 96 | /// 97 | /// Writes the Latest Version Json 98 | /// 99 | /// CLRVersion Struct 100 | /// 101 | public static string WriteLatestVersion(CLRVersion version) 102 | { 103 | return String.Format(@"SmallestDotNet.latestVersion = {0};", version != null ? WriteVersion(version) : "null"); 104 | } 105 | 106 | /// 107 | /// Writes the latest .NET CLR Version found in the provided UserAgent String 108 | /// 109 | /// A User Agent String 110 | /// A Json string containing the latest .NET CLR Version 111 | public static string WriteLatestVersions(string userAgent) 112 | { 113 | var latestVersion = (new CLRVersions(userAgent)).GetLatestVersion(); 114 | 115 | return WriteLatestVersion(latestVersion); 116 | } 117 | 118 | /// 119 | /// Writes all .NET CLR VErsions found in the User Agent String 120 | /// 121 | /// A User Agent String 122 | /// A Json string containing all the CLR Versions found in the User Agent String 123 | public static string WriteAllVersions(string userAgent) 124 | { 125 | var versions = new List(); 126 | var detectedVersions = (new CLRVersions(userAgent)).GetInstalledVersions(); 127 | 128 | foreach (var version in detectedVersions) 129 | { 130 | versions.Add(WriteVersion(version.Value)); 131 | } 132 | 133 | return String.Format(@"SmallestDotNet.allVersions = [{0}];", String.Join(",", versions.ToArray())); 134 | 135 | } 136 | 137 | 138 | private static string _downloadString = ""; 139 | 140 | /// 141 | /// Writes a Json String Containing Download Information for all of the .NET CLR Versions 142 | /// 143 | /// A Json String 144 | public static string WriteDownloads() 145 | { 146 | if (_downloadString == "") 147 | { 148 | var DownloadableVersions = CLRVersions.GetDownloadableVersions().Select(p => JsonVersions.WriteVersionWithDownload(p.Value)).ToList(); 149 | 150 | _downloadString = String.Format(@"SmallestDotNet.downloadableVersions = [{0}];", String.Join(",", DownloadableVersions.ToArray())); 151 | } 152 | 153 | return _downloadString; 154 | } 155 | 156 | } 157 | 158 | } 159 | -------------------------------------------------------------------------------- /SmallestDotNetLib/OperatingSystemSupport.cs: -------------------------------------------------------------------------------- 1 | namespace SmallestDotNetLib 2 | { 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | 6 | public class OperatingSystem 7 | { 8 | public string UserAgentVersion { get; set; } 9 | public string PrettyVersion { get; set; } 10 | public CLRVersion LatestCLRVersion { get; set; } 11 | } 12 | 13 | public class OperatingSystems 14 | { 15 | public static OperatingSystem Windows81 = new OperatingSystem() { UserAgentVersion = "Windows NT 6.3", PrettyVersion = "Windows 8.1", LatestCLRVersion = CLRVersions.NET45Full }; 16 | public static OperatingSystem Windows8 = new OperatingSystem() { UserAgentVersion = "Windows NT 6.2", PrettyVersion = "Windows 8", LatestCLRVersion = CLRVersions.NET45Full }; 17 | public static OperatingSystem Windows7 = new OperatingSystem() { UserAgentVersion = "Windows NT 6.1", PrettyVersion = "Windows 7", LatestCLRVersion = CLRVersions.NET45Full }; 18 | public static OperatingSystem WindowsVista = new OperatingSystem() { UserAgentVersion = "Windows NT 6.0", PrettyVersion = "Windows Vista", LatestCLRVersion = CLRVersions.NET45Full }; 19 | public static OperatingSystem WindowsXP64ORServer2003 = new OperatingSystem { UserAgentVersion = "Windows NT 5.2", PrettyVersion = "Windows XP x64, Windows Server 2003", LatestCLRVersion = CLRVersions.NET40Full }; 20 | public static OperatingSystem WindowsXP = new OperatingSystem() { UserAgentVersion = "Windows NT 5.1", PrettyVersion = "Windows XP", LatestCLRVersion = CLRVersions.NET40Full }; 21 | public static OperatingSystem Windows2000SP1 = new OperatingSystem() { UserAgentVersion = "Windows NT 5.01", PrettyVersion = "Windows 2000 SP1", LatestCLRVersion = CLRVersions.NET20Full }; 22 | public static OperatingSystem Windows2000 = new OperatingSystem() { UserAgentVersion = "Windows NT 5.0", PrettyVersion = "Windows 2000", LatestCLRVersion = CLRVersions.NET20Full }; 23 | public static OperatingSystem Windows98 = new OperatingSystem() { UserAgentVersion = "Windows 98", PrettyVersion = "Windows 98", LatestCLRVersion = CLRVersions.NET20Full }; 24 | public static OperatingSystem Macintosh = new OperatingSystem() { UserAgentVersion = "Mac", PrettyVersion = "Macintosh", LatestCLRVersion = null }; 25 | public static OperatingSystem UnixBased = new OperatingSystem() { UserAgentVersion = "nix", PrettyVersion = "Unix/Linux", LatestCLRVersion = null }; 26 | public static OperatingSystem Android = new OperatingSystem() { UserAgentVersion = "Android", PrettyVersion = "Android", LatestCLRVersion = null }; 27 | 28 | public static List OSVersions = new List 29 | { 30 | Windows81, 31 | Windows8, 32 | Windows7, 33 | WindowsVista, 34 | WindowsXP64ORServer2003, 35 | WindowsXP, 36 | Windows2000SP1, 37 | Windows2000, 38 | Windows98, 39 | Macintosh, 40 | UnixBased 41 | }; 42 | 43 | public static OperatingSystem GetOperatingSystem(string UserAgent) 44 | { 45 | return OSVersions.FirstOrDefault(o => UserAgent.Contains(o.UserAgentVersion)); 46 | } 47 | 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /SmallestDotNetLib/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | 4 | // General Information about an assembly is controlled through the following 5 | // set of attributes. Change these attribute values to modify the information 6 | // associated with an assembly. 7 | [assembly: AssemblyTitle("SmallestDotNetLib")] 8 | [assembly: AssemblyDescription("")] 9 | [assembly: AssemblyConfiguration("")] 10 | [assembly: AssemblyCompany("")] 11 | [assembly: AssemblyProduct("SmallestDotNetLib")] 12 | [assembly: AssemblyCopyright("Copyright © 2012")] 13 | [assembly: AssemblyTrademark("")] 14 | [assembly: AssemblyCulture("")] 15 | 16 | // Setting ComVisible to false makes the types in this assembly not visible 17 | // to COM components. If you need to access a type in this assembly from 18 | // COM, set the ComVisible attribute to true on that type. 19 | [assembly: ComVisible(false)] 20 | 21 | // The following GUID is for the ID of the typelib if this project is exposed to COM 22 | [assembly: Guid("f4a45b35-6b84-4b47-a463-52e2843c7e17")] 23 | 24 | // Version information for an assembly consists of the following four values: 25 | // 26 | // Major Version 27 | // Minor Version 28 | // Build Number 29 | // Revision 30 | // 31 | // You can specify all the values or you can default the Build and Revision Numbers 32 | // by using the '*' as shown below: 33 | // [assembly: AssemblyVersion("1.0.*")] 34 | [assembly: AssemblyVersion("1.0.0.0")] 35 | [assembly: AssemblyFileVersion("1.0.0.0")] 36 | -------------------------------------------------------------------------------- /SmallestDotNetLib/SmallestDotNetLib.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {3ECC85DC-EBC0-4A2E-930D-711ABC481388} 8 | Library 9 | Properties 10 | SmallestDotNetLib 11 | SmallestDotNetLib 12 | v4.5 13 | 512 14 | ..\ 15 | true 16 | 17 | 18 | true 19 | full 20 | false 21 | bin\Debug\ 22 | DEBUG;TRACE 23 | prompt 24 | 4 25 | false 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 | 54 | 55 | 56 | 57 | 64 | -------------------------------------------------------------------------------- /SmallestDotNetLib/UpdateInformationResponse.cs: -------------------------------------------------------------------------------- 1 | namespace SmallestDotNetLib 2 | { 3 | /// 4 | /// Encapsulates the results from the parsing of user agent / version 5 | /// 6 | public class UpdateInformationResponse 7 | { 8 | #region Properties 9 | 10 | /// 11 | /// Gets or sets a value indicating whether the current OS can run the checker application. 12 | /// 13 | public bool CanRunCheckApp { get; set; } 14 | 15 | /// 16 | /// Gets or sets the text to be displayed to the user. 17 | /// 18 | public string Text { get; set; } 19 | 20 | /// 21 | /// Gets or sets a value indicating whether the CLR version was able to be detected. 22 | /// 23 | public bool VersionCanBeDetermined { get; set; } 24 | 25 | /// 26 | /// Gets or sets a value indicating whether the current dot net version is latest. 27 | /// 28 | public bool VersionIsLatest { get; set; } 29 | 30 | #endregion Properties 31 | } 32 | } -------------------------------------------------------------------------------- /SmallestTest/CLRVersionDictionaryTests.cs: -------------------------------------------------------------------------------- 1 | namespace SmallestTest 2 | { 3 | using System.Collections; 4 | using System.Collections.Generic; 5 | using Microsoft.VisualStudio.TestTools.UnitTesting; 6 | using SmallestDotNetLib; 7 | 8 | [TestClass] 9 | public class CLRVersionDictionaryTests 10 | { 11 | [TestMethod] 12 | public void ParseVersionsProperlyTest() 13 | { 14 | var UserAgent = @"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; WOW64; Trident/5.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E; InfoPath.3; MS-RTC LM 8)"; 15 | 16 | var expected = new Dictionary(); 17 | 18 | expected.Add(Constants.Version20Full, CLRVersions.Versions[Constants.Version20Full]); 19 | expected.Add(Constants.Version30Full, CLRVersions.Versions[Constants.Version30Full]); 20 | expected.Add(Constants.Version35SP1Full, CLRVersions.Versions[Constants.Version35SP1Full]); 21 | expected.Add(Constants.Version40Client, CLRVersions.Versions[Constants.Version40Client]); 22 | expected.Add(Constants.Version40Full, CLRVersions.Versions[Constants.Version40Full]); 23 | 24 | var CLRVersionFac = new CLRVersions(UserAgent); 25 | var actual = CLRVersionFac.GetInstalledVersions(); 26 | 27 | 28 | CollectionAssert.AreEquivalent((ICollection)expected, (ICollection)actual); 29 | 30 | var expectedLatestVersion = CLRVersions.Versions[Constants.Version40Full]; 31 | var actualLatestVersion = CLRVersionFac.GetLatestVersion(); 32 | Assert.IsTrue(actualLatestVersion != null, "Version is not null"); 33 | 34 | Assert.AreEqual(expectedLatestVersion.Major, actualLatestVersion.Major, "Major Versions Are the Same"); 35 | Assert.AreEqual(expectedLatestVersion.Minor, actualLatestVersion.Minor, "Minor Versions Are the Same"); 36 | Assert.AreEqual(expectedLatestVersion.Profile, actualLatestVersion.Profile, "Profile is the Same"); 37 | Assert.AreEqual(expectedLatestVersion.ServicePack, actualLatestVersion.ServicePack, "Service Pack is the Same"); 38 | 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /SmallestTest/JavascriptDomTests.cs: -------------------------------------------------------------------------------- 1 | namespace SmallestTest 2 | { 3 | using System; 4 | using System.Linq; 5 | using Microsoft.VisualStudio.TestTools.UnitTesting; 6 | using SmallestDotNetLib; 7 | 8 | [TestClass] 9 | public class JavascriptDomTests 10 | { 11 | private string generateLatestVersionString(int major, int minor, string profile, int? sp) 12 | { 13 | return String.Format(@"SmallestDotNet.latestVersion = {{ 14 | major: {0}, 15 | minor: {1}, 16 | profile: ""{2}"", 17 | servicePack: {3} 18 | }};", major, minor, profile, sp.HasValue ? sp.ToString() : "null"); 19 | } 20 | 21 | [TestMethod] 22 | public void WriteOnlyVersionsThatHaveLinksForDownload() 23 | { 24 | var downloadableVersions = CLRVersions.GetDownloadableVersions(); 25 | 26 | Assert.IsTrue(downloadableVersions.All(pair => pair.Value.Url != "")); 27 | 28 | } 29 | 30 | 31 | [TestMethod] 32 | public void Write40AsLatestVersion() 33 | { 34 | var userAgent = ".NET4.0E; .NET4.0C"; 35 | 36 | var expectedVersion = generateLatestVersionString(4, 0, "full", null); 37 | 38 | var actualVersion = JsonVersions.WriteLatestVersions(userAgent); 39 | 40 | Assert.AreEqual(expectedVersion, actualVersion); 41 | 42 | } 43 | 44 | [TestMethod] 45 | public void Write40ClientAsLatestVersion() 46 | { 47 | var userAgent = ".NET4.0C; .NET CLR 2.0"; 48 | 49 | var expectedVersion = generateLatestVersionString(4, 0, "client", null); 50 | 51 | var actualVersion = JsonVersions.WriteLatestVersions(userAgent); 52 | 53 | Assert.AreEqual(expectedVersion, actualVersion); 54 | } 55 | 56 | [TestMethod] 57 | public void Write35SP1AsLatestVersion() 58 | { 59 | var userAgent = ".NET CLR 3.5.30729"; 60 | 61 | var expectedVersion = generateLatestVersionString(3, 5, "full", 1); 62 | 63 | var actualVersion = JsonVersions.WriteLatestVersions(userAgent); 64 | 65 | Assert.AreEqual(expectedVersion, actualVersion); 66 | } 67 | 68 | [TestMethod] 69 | public void Write35SP1ClientAsLatestVersion() 70 | { 71 | var userAgent = ".NET Client 3.5"; 72 | 73 | var expectedVersion = generateLatestVersionString(3, 5, "client", 1); 74 | 75 | var actualVersion = JsonVersions.WriteLatestVersions(userAgent); 76 | 77 | Assert.AreEqual(expectedVersion, actualVersion); 78 | } 79 | 80 | [TestMethod] 81 | public void Write35AsLatestVersion() 82 | { 83 | var userAgent = ".NET CLR 3.5.21022"; 84 | 85 | var expectedVersion = generateLatestVersionString(3, 5, "full", null); 86 | 87 | var actualVersion = JsonVersions.WriteLatestVersions(userAgent); 88 | 89 | Assert.AreEqual(expectedVersion, actualVersion); 90 | } 91 | 92 | [TestMethod] 93 | public void Write20AsLatestVersion() 94 | { 95 | var userAgent = ".NET CLR 2.0"; 96 | 97 | var expectedVersion = generateLatestVersionString(2, 0, "full", null); 98 | 99 | var actualVersion = JsonVersions.WriteLatestVersions(userAgent); 100 | 101 | Assert.AreEqual(expectedVersion, actualVersion); 102 | } 103 | 104 | [TestMethod] 105 | public void Write11AsLatestVersion() 106 | { 107 | var userAgent = ".NET CLR 1.1"; 108 | 109 | var expectedVersion = generateLatestVersionString(1, 1, "full", null); 110 | 111 | var actualVersion = JsonVersions.WriteLatestVersions(userAgent); 112 | 113 | Assert.AreEqual(expectedVersion, actualVersion); 114 | } 115 | 116 | [TestMethod] 117 | public void Write10AsLatestVersion() 118 | { 119 | var userAgent = ".NET CLR 1.0"; 120 | 121 | var expectedVersion = generateLatestVersionString(1, 0, "full", null); 122 | 123 | var actualVersion = JsonVersions.WriteLatestVersions(userAgent); 124 | 125 | Assert.AreEqual(expectedVersion, actualVersion); 126 | } 127 | 128 | [TestMethod] 129 | public void WriteNullAsLatestVersion() 130 | { 131 | var userAgent = ""; 132 | 133 | var expectedVersion = "SmallestDotNet.latestVersion = null;"; 134 | 135 | var actualVersion = JsonVersions.WriteLatestVersions(userAgent); 136 | 137 | Assert.AreEqual(expectedVersion, actualVersion); 138 | } 139 | 140 | } 141 | } 142 | -------------------------------------------------------------------------------- /SmallestTest/OperatingSystemVersionTests.cs: -------------------------------------------------------------------------------- 1 | namespace SmallestTest 2 | { 3 | using Microsoft.VisualStudio.TestTools.UnitTesting; 4 | using SmallestDotNetLib; 5 | 6 | [TestClass] 7 | public class OperatingSystemVersionTests 8 | { 9 | [TestMethod] 10 | public void CheckNoMatch() 11 | { 12 | var UserAgent = "Apeture"; 13 | 14 | var actualOS = OperatingSystems.GetOperatingSystem(UserAgent); 15 | 16 | Assert.IsNull(actualOS); 17 | 18 | } 19 | 20 | 21 | [TestMethod] 22 | public void CheckWindows8() 23 | { 24 | var UserAgent = "Windows NT 6.2"; 25 | var Windows8OperatingSystem = OperatingSystems.Windows8; 26 | 27 | var actualOS = OperatingSystems.GetOperatingSystem(UserAgent); 28 | 29 | Assert.AreEqual(Windows8OperatingSystem, actualOS); 30 | } 31 | 32 | [TestMethod] 33 | public void CheckWindows81() 34 | { 35 | var UserAgent = "Windows NT 6.3"; 36 | var Windows8OperatingSystem = OperatingSystems.Windows81; 37 | 38 | var actualOS = OperatingSystems.GetOperatingSystem(UserAgent); 39 | 40 | Assert.AreEqual(Windows8OperatingSystem, actualOS); 41 | } 42 | 43 | [TestMethod] 44 | public void CheckWindows7() 45 | { 46 | var UserAgent = "Windows NT 6.1"; 47 | var Windows7OperatingSystem = OperatingSystems.Windows7; 48 | 49 | var actualOS = OperatingSystems.GetOperatingSystem(UserAgent); 50 | 51 | Assert.AreEqual(Windows7OperatingSystem, actualOS); 52 | } 53 | 54 | [TestMethod] 55 | public void CheckWindowsVista() 56 | { 57 | var UserAgent = "Windows NT 6.0"; 58 | var WinodwsVistaOperatingSytem = OperatingSystems.WindowsVista; 59 | 60 | var actualOS = OperatingSystems.GetOperatingSystem(UserAgent); 61 | 62 | Assert.AreEqual(WinodwsVistaOperatingSytem, actualOS); 63 | } 64 | 65 | [TestMethod] 66 | public void CheckoutWindowsServer2003() 67 | { 68 | var UserAgent = "Windows NT 5.2"; 69 | var WindowsServer2003OperatingSystem = OperatingSystems.WindowsXP64ORServer2003; 70 | 71 | var actualOS = OperatingSystems.GetOperatingSystem(UserAgent); 72 | 73 | Assert.AreEqual(WindowsServer2003OperatingSystem, actualOS); 74 | } 75 | 76 | 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /SmallestTest/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | 4 | // General Information about an assembly is controlled through the following 5 | // set of attributes. Change these attribute values to modify the information 6 | // associated with an assembly. 7 | [assembly: AssemblyTitle("SmallestTest")] 8 | [assembly: AssemblyDescription("")] 9 | [assembly: AssemblyConfiguration("")] 10 | [assembly: AssemblyCompany("")] 11 | [assembly: AssemblyProduct("SmallestTest")] 12 | [assembly: AssemblyCopyright("Copyright © 2012")] 13 | [assembly: AssemblyTrademark("")] 14 | [assembly: AssemblyCulture("")] 15 | 16 | // Setting ComVisible to false makes the types in this assembly not visible 17 | // to COM components. If you need to access a type in this assembly from 18 | // COM, set the ComVisible attribute to true on that type. 19 | [assembly: ComVisible(false)] 20 | 21 | // The following GUID is for the ID of the typelib if this project is exposed to COM 22 | [assembly: Guid("1e471b2b-9007-4d89-8772-ad09899dd728")] 23 | 24 | // Version information for an assembly consists of the following four values: 25 | // 26 | // Major Version 27 | // Minor Version 28 | // Build Number 29 | // Revision 30 | // 31 | // You can specify all the values or you can default the Build and Revision Numbers 32 | // by using the '*' as shown below: 33 | // [assembly: AssemblyVersion("1.0.*")] 34 | [assembly: AssemblyVersion("1.0.0.0")] 35 | [assembly: AssemblyFileVersion("1.0.0.0")] 36 | -------------------------------------------------------------------------------- /SmallestTest/SmallestTest.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Debug 5 | AnyCPU 6 | {21BD13C9-725E-447D-8CF9-07E8CBE797B1} 7 | Library 8 | Properties 9 | SmallestTest 10 | SmallestTest 11 | v4.5 12 | 512 13 | {3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 14 | 10.0 15 | $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) 16 | $(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages 17 | False 18 | UnitTest 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 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | {3ecc85dc-ebc0-4a2e-930d-711abc481388} 63 | SmallestDotNetLib 64 | 65 | 66 | 67 | 68 | 69 | 70 | False 71 | 72 | 73 | False 74 | 75 | 76 | False 77 | 78 | 79 | False 80 | 81 | 82 | 83 | 84 | 85 | 86 | 93 | -------------------------------------------------------------------------------- /SmallestTest/VersionCheckTest.cs: -------------------------------------------------------------------------------- 1 | namespace SmallestTest 2 | { 3 | 4 | using System; 5 | using System.Collections.Generic; 6 | using Microsoft.VisualStudio.TestTools.UnitTesting; 7 | 8 | [TestClass] 9 | public class VersionCheckTest 10 | { 11 | private static List CLRVersionStrings() 12 | { 13 | return new List 14 | { 15 | ".NET4.0E" 16 | , ".NET4.0C" 17 | , ".NET CLR 3.5.30729" 18 | , ".NET Client 3.5" 19 | , ".NET CLR 3.5.21022" 20 | , ".NET CLR 2.0" 21 | , ".NET CLR 1.1" 22 | , ".NET CLR 1.0" 23 | }; 24 | } 25 | 26 | [TestMethod] 27 | public void CheckAllCLRInUserAgentDetectionStrings() 28 | { 29 | var userAgentCLRString = String.Join(" ", CLRVersionStrings().ToArray()); 30 | 31 | Assert.IsTrue(Helpers.Has10(userAgentCLRString), ".NET Version 1.0"); 32 | Assert.IsTrue(Helpers.Has11(userAgentCLRString), ".NET Version 1.1"); 33 | Assert.IsTrue(Helpers.Has20(userAgentCLRString), ".NET Version 2.0"); 34 | Assert.IsTrue(Helpers.Has35(userAgentCLRString), ".NET Version 3.5"); 35 | Assert.IsTrue(Helpers.Has35SP1C(userAgentCLRString), ".NET Version 3.5 SP1 Client Profile"); 36 | Assert.IsTrue(Helpers.Has35SP1E(userAgentCLRString), ".NET Version 3.5 SP1 Full"); 37 | Assert.IsTrue(Helpers.Has40C(userAgentCLRString), ".NET Version 4.0 Client Profile"); 38 | Assert.IsTrue(Helpers.Has40E(userAgentCLRString), ".NET Version 4.0 Full"); 39 | } 40 | 41 | [TestMethod] 42 | public void CheckWindows8Detection() 43 | { 44 | var userAgent = "Windows NT 6.2"; 45 | 46 | Assert.IsTrue(Helpers.HasWindows8(userAgent), "Windows 8"); 47 | userAgent = "Windows NT 6.3"; 48 | 49 | Assert.IsTrue(Helpers.HasWindows8(userAgent), "Windows 8.1"); 50 | } 51 | 52 | /// 53 | /// Checks that the helper detects Windows 10 correctly. 54 | /// 55 | [TestMethod] 56 | public void CheckWindows10Detection() 57 | { 58 | // User agent from Edge (Windows 10 build 10074) 59 | var userAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.71 Safari/537.36 Edge/12.0"; 60 | 61 | Assert.IsTrue(Helpers.HasWindows10(userAgent), "Windows 10 detection failed"); 62 | 63 | // User agent from IE11 (Windows 10 build 10074) 64 | userAgent = "Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; Touch; MALCJS; rv:11.0) like Gecko"; 65 | 66 | Assert.IsTrue(Helpers.HasWindows10(userAgent), "Windows 10 detection failed"); 67 | Assert.IsFalse(Helpers.HasWindows8(userAgent), "Windows 8 incorrectly detected"); 68 | } 69 | 70 | /// 71 | /// Checks that the helper shows 4.6 when Windows 10 detected. 72 | /// 73 | [TestMethod] 74 | public void CheckWindows10Shows46() 75 | { 76 | // Arrange 77 | const string UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.71 Safari/537.36 Edge/12.0"; 78 | 79 | 80 | // Act 81 | string message = Helpers.GetUpdateInformation(UserAgent).Text; 82 | 83 | // Assert 84 | Assert.IsTrue(Helpers.HasWindows10(UserAgent), "Windows 10 detection failed"); 85 | StringAssert.Contains(message, "4.6", "Windows 10 must have at least 4.6"); 86 | } 87 | 88 | [TestMethod] 89 | public void CheckRealVersion() 90 | { 91 | // Arrange 92 | const string UserAgent = ".NET Version 1.0"; 93 | const string RealVersion = "4.5.1"; 94 | const string CheckerApplicationText = "The .Net Checker application determined that you have"; 95 | const string UnableToDetermineText = "The application was not able to determine the exact version you have."; 96 | var releaseKey = 0; 97 | 98 | // Act 99 | string message = Helpers.GetUpdateInformation(UserAgent, RealVersion, releaseKey).Text; 100 | 101 | // Assert 102 | StringAssert.StartsWith(message, CheckerApplicationText); 103 | StringAssert.Contains(message, RealVersion); 104 | Assert.IsFalse(message.Contains(UnableToDetermineText), "The '...not able to determine the exact version...' message should NOT appear if realVersion is present and releaseKey=0"); 105 | 106 | foreach (var releaseVersion in Constants.ReleaseVersions) 107 | { 108 | // Arrange 109 | releaseKey = releaseVersion.Key; 110 | 111 | // Act 112 | message = Helpers.GetUpdateInformation(UserAgent, null, releaseKey).Text; 113 | 114 | // Assert 115 | StringAssert.StartsWith(message, CheckerApplicationText); 116 | StringAssert.Contains(message, releaseVersion.Value); 117 | Assert.IsFalse(message.Contains(UnableToDetermineText), "The '...not able to determine the exact version...' message should NOT appear if releaseKey is contained in Constants.ReleaseVersions"); 118 | 119 | // Arrange 120 | releaseKey = releaseVersion.Key + 1; 121 | 122 | // Act 123 | message = Helpers.GetUpdateInformation(UserAgent, null, releaseKey).Text; 124 | 125 | // Assert 126 | StringAssert.StartsWith(message, CheckerApplicationText); 127 | StringAssert.Contains(message, releaseVersion.Value + " or greater"); 128 | StringAssert.Contains(message, UnableToDetermineText, "The '...not able to determine the exact version...' message SHOULD appear if releaseKey is not contained in Constants.ReleaseVersions"); 129 | } 130 | } 131 | } 132 | } 133 | -------------------------------------------------------------------------------- /SmallestTest/VersionWriterTests.cs: -------------------------------------------------------------------------------- 1 | namespace SmallestTest 2 | { 3 | using Microsoft.VisualStudio.TestTools.UnitTesting; 4 | 5 | [TestClass] 6 | public class VersionWriterTests 7 | { 8 | [TestMethod] 9 | public void Test10Version() 10 | { 11 | var expected = @"{ 12 | major: 1, 13 | minor: 0, 14 | profile: ""full"", 15 | servicePack: null 16 | }"; 17 | 18 | int? servicePack = null; 19 | 20 | var actual = SmallestDotNetLib.JsonVersions.WriteVersion(1, 0, "full", servicePack); 21 | 22 | Assert.AreEqual(expected, actual); 23 | } 24 | 25 | [TestMethod] 26 | public void Test11Json() 27 | { 28 | var expected = @"{ 29 | major: 1, 30 | minor: 1, 31 | profile: ""full"", 32 | servicePack: null 33 | }"; 34 | 35 | int? servicePack = null; 36 | 37 | var actual = SmallestDotNetLib.JsonVersions.WriteVersion(1, 1, "full", servicePack); 38 | 39 | Assert.AreEqual(expected, actual); 40 | } 41 | 42 | [TestMethod] 43 | public void Test20Json() 44 | { 45 | var expected = @"{ 46 | major: 2, 47 | minor: 0, 48 | profile: ""full"", 49 | servicePack: null 50 | }"; 51 | 52 | int? servicePack = null; 53 | 54 | var actual = SmallestDotNetLib.JsonVersions.WriteVersion(2, 0, "full", servicePack); 55 | 56 | Assert.AreEqual(expected, actual); 57 | } 58 | 59 | 60 | [TestMethod] 61 | public void Test35Json() 62 | { 63 | var expected = @"{ 64 | major: 3, 65 | minor: 5, 66 | profile: ""full"", 67 | servicePack: null 68 | }"; 69 | 70 | int? servicePack = null; 71 | 72 | var actual = SmallestDotNetLib.JsonVersions.WriteVersion(3, 5, "full", servicePack); 73 | 74 | Assert.AreEqual(expected, actual); 75 | } 76 | 77 | 78 | 79 | [TestMethod] 80 | public void Test35ServicePackOneJson() 81 | { 82 | var expected = @"{ 83 | major: 3, 84 | minor: 5, 85 | profile: ""full"", 86 | servicePack: 1 87 | }"; 88 | 89 | int? servicePack = 1; 90 | 91 | var actual = SmallestDotNetLib.JsonVersions.WriteVersion(3, 5, "full", servicePack); 92 | 93 | Assert.AreEqual(expected, actual); 94 | } 95 | 96 | [TestMethod] 97 | public void Test35ClientServicePackOneJson() 98 | { 99 | var expected = @"{ 100 | major: 3, 101 | minor: 5, 102 | profile: ""client"", 103 | servicePack: 1 104 | }"; 105 | 106 | int? servicePack = 1; 107 | 108 | var actual = SmallestDotNetLib.JsonVersions.WriteVersion(3, 5, "client", servicePack); 109 | 110 | Assert.AreEqual(expected, actual); 111 | } 112 | [TestMethod] 113 | public void Test40Json() 114 | { 115 | var expected = @"{ 116 | major: 4, 117 | minor: 0, 118 | profile: ""full"", 119 | servicePack: null 120 | }"; 121 | 122 | int? servicePack = null; 123 | 124 | var actual = SmallestDotNetLib.JsonVersions.WriteVersion(4, 0, "full", servicePack); 125 | 126 | Assert.AreEqual(expected, actual); 127 | } 128 | 129 | [TestMethod] 130 | public void Test40ClientProfileJson() 131 | { 132 | var expected = @"{ 133 | major: 4, 134 | minor: 0, 135 | profile: ""client"", 136 | servicePack: null 137 | }"; 138 | 139 | int? servicePack = null; 140 | 141 | var actual = SmallestDotNetLib.JsonVersions.WriteVersion(4, 0, "client", servicePack); 142 | 143 | Assert.AreEqual(expected, actual); 144 | } 145 | 146 | [TestMethod] 147 | public void Test45Json() 148 | { 149 | var expected = @"{ 150 | major: 4, 151 | minor: 5, 152 | profile: ""full"", 153 | servicePack: null 154 | }"; 155 | 156 | int? servicePack = null; 157 | 158 | var actual = SmallestDotNetLib.JsonVersions.WriteVersion(4, 5, "full", servicePack); 159 | 160 | Assert.AreEqual(expected, actual); 161 | } 162 | } 163 | } 164 | -------------------------------------------------------------------------------- /license.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2013 scott Hanselman 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. --------------------------------------------------------------------------------