master faab4bbc54db cached
67 files
1.1 MB
316.8k tokens
268 symbols
1 requests
Download .txt
Showing preview only (1,160K chars total). Download the full file or copy to clipboard to get everything.
Repository: TimothyMeadows/reCAPTCHA.AspNetCore
Branch: master
Commit: faab4bbc54db
Files: 67
Total size: 1.1 MB

Directory structure:
gitextract_6idzfx4c/

├── .gitignore
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── LICENSE
├── README.md
├── reCAPTCHA.AspNetCore/
│   ├── Attributes/
│   │   ├── RecaptchaResponseAttribute.cs
│   │   ├── ValidateRecaptchaAttribute.cs
│   │   └── ValidateRecaptchaFilter.cs
│   ├── CodeDom.cs
│   ├── IRecaptchaService.cs
│   ├── RecaptchaHelper.cs
│   ├── RecaptchaResponse.cs
│   ├── RecaptchaService.cs
│   ├── RecaptchaServiceCollection.cs
│   ├── RecaptchaSettings.cs
│   ├── Templates/
│   │   ├── RecaptchaV2Checkbox.cs
│   │   ├── RecaptchaV2Checkbox.tt
│   │   ├── RecaptchaV2CheckboxModelBinder.cs
│   │   ├── RecaptchaV2Invisible.cs
│   │   ├── RecaptchaV2Invisible.tt
│   │   ├── RecaptchaV2InvisibleModelBinder.cs
│   │   ├── RecaptchaV3HiddenInput.cs
│   │   ├── RecaptchaV3HiddenInput.tt
│   │   └── RecaptchaV3HiddenInputModelBinder.cs
│   ├── Versions/
│   │   ├── RecaptchaV2Checkbox.cs
│   │   ├── RecaptchaV2Invisible.cs
│   │   ├── RecaptchaV3HiddenInput.cs
│   │   └── RecaptchaVersion.cs
│   └── reCAPTCHA.AspNetCore.csproj
├── reCAPTCHA.AspNetCore.Example/
│   ├── Controllers/
│   │   ├── HomeController.cs
│   │   └── SomeAPIControlelr.cs
│   ├── Models/
│   │   ├── Contact4Model.cs
│   │   ├── ContactModel.cs
│   │   ├── ErrorViewModel.cs
│   │   └── OtherModel.cs
│   ├── Program.cs
│   ├── Startup.cs
│   ├── Views/
│   │   ├── Home/
│   │   │   ├── Contact.cshtml
│   │   │   ├── Contact2.cshtml
│   │   │   ├── Contact3.cshtml
│   │   │   ├── Contact4.cshtml
│   │   │   ├── Index.cshtml
│   │   │   └── Privacy.cshtml
│   │   ├── Shared/
│   │   │   ├── Error.cshtml
│   │   │   ├── _Layout.cshtml
│   │   │   └── _ValidationScriptsPartial.cshtml
│   │   ├── _ViewImports.cshtml
│   │   └── _ViewStart.cshtml
│   ├── appsettings.Development.json
│   ├── appsettings.json
│   ├── reCAPTCHA.AspNetCore.Example.csproj
│   └── wwwroot/
│       ├── css/
│       │   └── site.css
│       ├── js/
│       │   └── site.js
│       └── lib/
│           ├── bootstrap/
│           │   ├── LICENSE
│           │   └── dist/
│           │       ├── css/
│           │       │   ├── bootstrap-grid.css
│           │       │   ├── bootstrap-reboot.css
│           │       │   └── bootstrap.css
│           │       └── js/
│           │           ├── bootstrap.bundle.js
│           │           └── bootstrap.js
│           ├── jquery/
│           │   ├── LICENSE.txt
│           │   └── dist/
│           │       └── jquery.js
│           ├── jquery-validation/
│           │   ├── LICENSE.md
│           │   └── dist/
│           │       ├── additional-methods.js
│           │       └── jquery.validate.js
│           └── jquery-validation-unobtrusive/
│               ├── LICENSE.txt
│               └── jquery.validate.unobtrusive.js
└── reCAPTCHA.AspNetCore.sln

================================================
FILE CONTENTS
================================================

================================================
FILE: .gitignore
================================================
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
##
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore

# User-specific files
*.suo
*.user
*.userosscache
*.sln.docstates

# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs

# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
bld/
[Bb]in/
[Oo]bj/
[Ll]og/

# Visual Studio 2015 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/

# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*

# NUNIT
*.VisualState.xml
TestResult.xml

# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c

# .NET Core
project.lock.json
project.fragment.lock.json
artifacts/
**/Properties/launchSettings.json

*_i.c
*_p.c
*_i.h
*.ilk
*.meta
*.obj
*.pch
*.pdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc

# Chutzpah Test files
_Chutzpah*

# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
*.VC.db
*.VC.VC.opendb

# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap

# TFS 2012 Local Workspace
$tf/

# Guidance Automation Toolkit
*.gpState

# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user

# JustCode is a .NET coding add-in
.JustCode

# TeamCity is a build add-in
_TeamCity*

# DotCover is a Code Coverage Tool
*.dotCover

# Visual Studio code coverage results
*.coverage
*.coveragexml

# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*

# MightyMoose
*.mm.*
AutoTest.Net/

# Web workbench (sass)
.sass-cache/

# Installshield output folder
[Ee]xpress/

# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html

# Click-Once directory
publish/

# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# TODO: Comment the next line if you want to checkin your web deploy settings
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj

# Microsoft Azure Web App publish settings. Comment the next line if you want to
# checkin your Azure Web App publish settings, but sensitive information contained
# in these scripts will be unencrypted
PublishScripts/

# NuGet Packages
*.nupkg
# The packages folder can be ignored because of Package Restore
**/packages/*
# except build/, which is used as an MSBuild target.
!**/packages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/packages/repositories.config
# NuGet v3's project.json files produces more ignorable files
*.nuget.props
*.nuget.targets

# Microsoft Azure Build Output
csx/
*.build.csdef

# Microsoft Azure Emulator
ecf/
rcf/

# Windows Store app package directories and files
AppPackages/
BundleArtifacts/
Package.StoreAssociation.xml
_pkginfo.txt

# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!*.[Cc]ache/

# Others
ClientBin/
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.jfm
*.pfx
*.publishsettings
orleans.codegen.cs

# Since there are multiple workflows, uncomment next line to ignore bower_components
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
#bower_components/

# RIA/Silverlight projects
Generated_Code/

# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm

# SQL Server files
*.mdf
*.ldf
*.ndf

# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings

# Microsoft Fakes
FakesAssemblies/

# GhostDoc plugin setting file
*.GhostDoc.xml

# Node.js Tools for Visual Studio
.ntvs_analysis.dat
node_modules/

# Typescript v1 declaration files
typings/

# Visual Studio 6 build log
*.plg

# Visual Studio 6 workspace options file
*.opt

# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
*.vbw

# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions

# Paket dependency manager
.paket/paket.exe
paket-files/

# FAKE - F# Make
.fake/

# JetBrains Rider
.idea/
*.sln.iml

# CodeRush
.cr/

# Python Tools for Visual Studio (PTVS)
__pycache__/
*.pyc

# Cake - Uncomment if you are using it
# tools/**
# !tools/packages.config

# Telerik's JustMock configuration file
*.jmconfig

# BizTalk build output
*.btp.cs
*.btm.cs
*.odx.cs
*.xsd.cs
*.nuspec
/lib/netcoreapp2.0


================================================
FILE: CODE_OF_CONDUCT.md
================================================
# Contributor Covenant Code of Conduct

## Our Pledge

In the interest of fostering an open and welcoming environment, we as
contributors and maintainers pledge to making participation in our project and
our community a harassment-free experience for everyone, regardless of age, body
size, disability, ethnicity, sex characteristics, gender identity and expression,
level of experience, education, socio-economic status, nationality, personal
appearance, race, religion, or sexual identity and orientation.

## Our Standards

Examples of behavior that contributes to creating a positive environment
include:

* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members

Examples of unacceptable behavior by participants include:

* The use of sexualized language or imagery and unwelcome sexual attention or
 advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic
 address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a
 professional setting

## Our Responsibilities

Project maintainers are responsible for clarifying the standards of acceptable
behavior and are expected to take appropriate and fair corrective action in
response to any instances of unacceptable behavior.

Project maintainers have the right and responsibility to remove, edit, or
reject comments, commits, code, wiki edits, issues, and other contributions
that are not aligned to this Code of Conduct, or to ban temporarily or
permanently any contributor for other behaviors that they deem inappropriate,
threatening, offensive, or harmful.

## Scope

This Code of Conduct applies both within project spaces and in public spaces
when an individual is representing the project or its community. Examples of
representing a project or community include using an official project e-mail
address, posting via an official social media account, or acting as an appointed
representative at an online or offline event. Representation of a project may be
further defined and clarified by project maintainers.

## Enforcement

Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported by contacting the project team at timothy@timothymeadows.com. All
complaints will be reviewed and investigated and will result in a response that
is deemed necessary and appropriate to the circumstances. The project team is
obligated to maintain confidentiality with regard to the reporter of an incident.
Further details of specific enforcement policies may be posted separately.

Project maintainers who do not follow or enforce the Code of Conduct in good
faith may face temporary or permanent repercussions as determined by other
members of the project's leadership.

## Attribution

This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html

[homepage]: https://www.contributor-covenant.org

For answers to common questions about this code of conduct, see
https://www.contributor-covenant.org/faq


================================================
FILE: CONTRIBUTING.md
================================================
*First off, thanks for taking the time to contribute!*

# Features

The purpose of this library is to create an inclusive environment for all .NET core developers. To put this in more simple terms. This means that feature requests must satisfy an important question.

1. Does this feature help multiple developers, or does it just help my project?

If a feature only helps your project. It will be rejected. If you can justify the existence of a feature by explaining how it will help all of us. Then it will be accepted!

# Bugs

Bug fixes will be audited to the best of my ability and merged when accepted. Depending on the changes needed to fix the bug. You might be required to update README.md with either an example, or fix to existing example. If a bug is created from a feature you added. You are encourged to fix the bug yourself. If you need help please place the help wanted tag, and @TimothyMeadows in the comments.


================================================
FILE: LICENSE
================================================
MIT License

Copyright (c) 2017 Timothy "Ravun" Meadows

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.


================================================
FILE: README.md
================================================
# reCAPTCHA.AspNetCore
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) [![nuget](https://img.shields.io/nuget/v/reCAPTCHA.AspNetCore.svg)](https://www.nuget.org/packages/reCAPTCHA.AspNetCore/)

Google reCAPTCHA for .NET Core 3.x. The older .NET Core 2.x version can be found [here](https://github.com/TimothyMeadows/reCAPTCHA.AspNetCore/tree/2.x).

*Note: There have been changes to this libraries structure between versions 2, and 3. If you still wish to use version 2 it's been frozen at version 2.2.5 on nuget.*

# Install

From a command prompt
```bash
dotnet add package reCAPTCHA.AspNetCore
```

```bash
Install-Package reCAPTCHA.AspNetCore
```

You can also search for package via your nuget ui / website:

https://www.nuget.org/packages/reCAPTCHA.AspNetCore/

# Requirements
You must first have a **secret key** and a **site key** in order to use the reCAPTCHA service. This package supports v2 and v3 api keys. You can read more about reCAPTCHA v2, and v3 as well as sign up for free here: https://www.google.com/recaptcha/intro/

# Configure

Choose how you want to configure the storage of your ```RecaptchaSettings```. This contains your site key, and site secret so it's recommended to use ```secrets.json``` with Azure Key Vault (or similar setup). However you can also just add the section to your ```appconfig.json``` file.


#### appconfig.json

Add the follow entry to the file make sure to paste in your secret key and site key followed by setting the correct version to v2 or v3 depending on your key type:
```json
"RecaptchaSettings": {
    "SecretKey": "paste secret key here",
    "SiteKey": "paste site key here"
  } 
```

#### secrets.json
Right click on your project file and goto Manage Secrets.

This will open secrets.json. Add the follow entry to the file make sure to paste in your secret key and site key followed by setting the correct version to v2 or v3 depending on your key type:
```json
"RecaptchaSettings": {
    "SecretKey": "paste secret key here",
    "SiteKey": "paste site key here"
  } 
```

*Note: This will also require you to have a setup such as Azure Key Vault (or similar setup) when running in production.*

#### Content Security Policy

If you use a content security policy you can specify the values for script-src, and frame-src using the below example. Note that you should also make sure the Site option used for those who suffer from censorship matches the values you are using. The default value for Site is www.google.com.

```json
"RecaptchaSettings": {
    "SecretKey": "paste secret key here",
    "SiteKey": "paste site key here",
    "ContentSecurityPolicy": "https://www.google.com/recaptcha/"
  } 
```

This is an example for those that have to use recaptcha.net which would also have to change the site value:

```json
"RecaptchaSettings": {
    "SecretKey": "paste secret key here",
    "SiteKey": "paste site key here",
    "Site": "www.recaptcha.net",
    "ContentSecurityPolicy": "https://www.recaptcha.net/recaptcha/"
  } 
```

# Versions

These are the currently supported versions. Below is also the list of class names for T when using ```Html.Recaptcha<T>```

- [RecaptchaV2Checkbox](https://developers.google.com/recaptcha/docs/display)
- [RecaptchaV2Invisible](https://developers.google.com/recaptcha/docs/invisible)
- [RecaptchaV3HiddenInput](https://developers.google.com/recaptcha/docs/v3)

# Examples

Open `Startup.cs` and add the following code as shown below to your `ConfigureServices` method:

```csharp
// Add recaptcha and pass recaptcha configuration section
services.AddRecaptcha(Configuration.GetSection("RecaptchaSettings"));

// Or configure recaptcha via options
services.AddRecaptcha(options =>
{
    options.SecretKey = "Your secret key";
    options.SiteKey = "Your site key";
});
```

# Usage

In order to prevent having to copy and paste your site key all over your view files (a nightmare to update later). You can inject your settings from the Startup method by adding the following code to top of your view file:

```csharp
@inject IOptions<RecaptchaSettings> RecaptchaSettings
```

You can then freely include the Recaptcha script inside of forms you wish to validate later in your controller (supports multiple forms).
```csharp
@using (Html.BeginForm("SomeMethod", "SomeController")) {
  @(Html.Recaptcha<RecaptchaV2Checkbox>(RecaptchaSettings?.Value))
}
```

If you wish to trigger a JavaScript function on callback you can pass a method name to the Html helper.
```csharp
@using (Html.BeginForm("SomeMethod", "SomeController")) {
  @(Html.Recaptcha<RecaptchaV2Checkbox>(RecaptchaSettings?.Value, new RecaptchaV2Checkbox { successCallback = "methodName" }))
}
```
```html
<script>
  function methodName() {
    alert('caw caw caw!');
  }
</script>
```

You can specify the language in the optional model.

```csharp
@(Html.Recaptcha(RecaptchaSettings?.Value, new RecaptchaV2Checkbox
{
    Language = System.Globalization.CultureInfo.CurrentCulture.Name.Substring(0,2)
}))
```

You may find that you need to add a reference to Microsoft.Extensions.Options before you can use IOptions.

```csharp
@using Microsoft.Extensions.Options
@using reCAPTCHA.AspNetCore
```

You can see a tested example of usage in the [Contact.cshtml](https://github.com/TimothyMeadows/reCAPTCHA.AspNetCore/blob/master/reCAPTCHA.AspNetCore.Example/Views/Home/Contact.cshtml) view. However you will need to configure it with your key information before running yourself. You should also take note of the allowed domains security policy in the Google Recaptcha docs.

# Validation

You can validate the recaptcha attempts using the ValidateRecaptchaAttribute on your HttpPost method:

```csharp
[HttpPost]
[ValidateRecaptcha]
public async Task<IActionResult> SomeMethod(SomeModel model)
{
  return View(model);
}
```

You can also specify a minimum score you wish to accept when a success occurs:

```csharp
[HttpPost]
[ValidateRecaptcha(0.5)]
public async Task<IActionResult> SomeMethod(SomeModel model)
{
  return View(model);
}
```

You can see a tested example of usage in the [HomeController.cs](https://github.com/TimothyMeadows/reCAPTCHA.AspNetCore/blob/master/reCAPTCHA.AspNetCore.Example/Controllers/HomeController.cs) controller. However you will need to configure it with your key information before running yourself. You should also take note of the allowed domains security policy in the Google Recaptcha docs.

# Recaptcha.net

Users who suffer from censorship concerns can now bypass the libraries default of www.google.com to www.recaptcha.net, or a proxy of there choosing using the following optional setting in ```appsettings.json```.

```csharp
"RecaptchaSettings": {
    "Site": "www.recaptcha.net",
    "SecretKey": "paste secret key here",
    "SiteKey": "paste site key here"
  }
```

# Unique Issues / Solutions

- [Testing / Localhost Development](https://github.com/TimothyMeadows/reCAPTCHA.AspNetCore/issues/82)
- [IsAsync empty response](https://github.com/TimothyMeadows/reCAPTCHA.AspNetCore/issues/81)


================================================
FILE: reCAPTCHA.AspNetCore/Attributes/RecaptchaResponseAttribute.cs
================================================
using System;
using System.ComponentModel.DataAnnotations;
using System.Configuration;
using Microsoft.Extensions.DependencyInjection;

namespace reCAPTCHA.AspNetCore.Attributes
{
    /// <summary>
    /// Validates reCaptcha response code bound to a property, parameter or field.
    /// </summary>
    /// <seealso cref="ValidationAttribute" />
    /// <seealso cref="IRecaptchaService.Validate(string)"/>
    [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.Field)]
	public class RecaptchaResponseAttribute : ValidationAttribute
	{
		/// <summary>
		/// Gets a value that indicates whether the attribute requires validation context.
		/// </summary>
		public override bool RequiresValidationContext => true;

        /// <summary>
        /// Gets or sets the minimum score.
        /// </summary>
        /// <value>
        /// The minimum score.
        /// </value>
        /// <seealso cref="ValidateRecaptchaAttribute._minimumScore"/>
        public double MinimumScore { get; set; }

        /// <summary>
        /// Returns wether the captcha validation was deemed successful based on the value of a member to attribute has been applied to.
        /// </summary>
        /// <param name="value">The value to validate.</param>
        /// <param name="validationContext">The context information about the validation operation.</param>
        /// <returns>
        /// An instance of the <see cref="System.ComponentModel.DataAnnotations.ValidationResult" /> class.
        /// </returns>
        /// <exception cref="ConfigurationErrorsException">When reCaptcha has not been configured.</exception>
        protected override ValidationResult IsValid(object value, ValidationContext validationContext)
		{
			if (!(value is string responseCode)
					|| string.IsNullOrWhiteSpace(responseCode))
				return null;

			var validationservice = validationContext.GetService<IRecaptchaService>();

            if(validationservice is null)
                throw new ConfigurationErrorsException($"{typeof(IRecaptchaService).Assembly.GetName().Name} has not been configured");

			var response = validationservice.Validate(responseCode).Result;

            if (response.success 
                && (response.score == 0 || response.score >= MinimumScore))

                return ValidationResult.Success;

            else

                return new ValidationResult(FormatErrorMessage(validationContext.DisplayName));
        }
	}
}


================================================
FILE: reCAPTCHA.AspNetCore/Attributes/ValidateRecaptchaAttribute.cs
================================================
using System;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.DependencyInjection;

namespace reCAPTCHA.AspNetCore.Attributes
{

    /// <summary>
    /// Validates Recaptcha submitted by a form using: @Html.Recaptcha(RecaptchaSettings.Value)
    /// </summary>
    [AttributeUsage(AttributeTargets.Method, Inherited = false)]
    public class ValidateRecaptchaAttribute : Attribute, IFilterFactory
    {
        public bool IsReusable => true;
        private readonly double _minimumScore;
        private readonly string _errorMessage;


        /// <summary>
        /// Validates Recaptcha submitted by a form using: @Html.Recaptcha(RecaptchaSettings.Value)
        /// </summary>
        /// <param name="score">The minimum score you wish to be acceptable for a success.</param>
        /// <param name="errorMessage">Error message you want added to validation model.</param>
        public ValidateRecaptchaAttribute(double score = 0, string errorMessage = "There was an error validating the google recaptcha response. Please try again, or contact the site owner.")
        {
            _minimumScore = score;
            _errorMessage = errorMessage;
        }

        public IFilterMetadata CreateInstance(IServiceProvider services)
        {
            var recaptcha = services.GetService<IRecaptchaService>();
            return new ValidateRecaptchaFilter(recaptcha, _minimumScore, _errorMessage);
        }
    }
}


================================================
FILE: reCAPTCHA.AspNetCore/Attributes/ValidateRecaptchaFilter.cs
================================================
using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc.Filters;

namespace reCAPTCHA.AspNetCore.Attributes
{
    public class ValidateRecaptchaFilter : IAsyncActionFilter
    {
        private readonly IRecaptchaService _recaptcha;
        private readonly double _minimumScore;
        private readonly string _errorMessage;

        public ValidateRecaptchaFilter(IRecaptchaService recaptcha, double minimumScore, string errorMessage)
        {
            _recaptcha = recaptcha;
            _minimumScore = minimumScore;
            _errorMessage = errorMessage;
        }

        public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
        {
            var recaptcha = await _recaptcha.Validate(context.HttpContext.Request);
            if (!recaptcha.success || recaptcha.score != 0 && recaptcha.score < _minimumScore)
                context.ModelState.AddModelError("Recaptcha", _errorMessage);

            await next();
        }
    }
}


================================================
FILE: reCAPTCHA.AspNetCore/CodeDom.cs
================================================
using System.Collections.Generic;

namespace System.CodeDom.Compiler
{
    public class CompilerError
    {
        public string ErrorText;
        public bool IsWarning;
    }

    public class CompilerErrorCollection : List<CompilerError>
    {
        // This is a place holder class, it most likely should be included in dotnet core it's self but for some reason it is not.
    }
}

================================================
FILE: reCAPTCHA.AspNetCore/IRecaptchaService.cs
================================================
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;

namespace reCAPTCHA.AspNetCore
{
    public interface IRecaptchaService
    {
        Task<RecaptchaResponse> Validate(HttpRequest request, bool antiForgery = true);

        Task<RecaptchaResponse> Validate(string responseCode);
    }
}


================================================
FILE: reCAPTCHA.AspNetCore/RecaptchaHelper.cs
================================================
using System;
using Microsoft.AspNetCore.Html;
using Microsoft.AspNetCore.Mvc.Rendering;
using reCAPTCHA.AspNetCore.Versions;

namespace reCAPTCHA.AspNetCore
{
    public static class RecaptchaHelper
    {
        /// <summary>
        /// Helper extension to render the Google Recaptcha.
        /// </summary>
        /// <param name="helper">Html helper object.</param>
        /// <param name="settings">Recaptcha settings needed to render.</param>
        /// <param name="model">Optional recaptcha version model. If not supplied a model with defaults will be created.</param>
        /// <returns>HtmlString with Recaptcha elements.</returns>
        public static HtmlString Recaptcha<T>(this IHtmlHelper helper, RecaptchaSettings settings, T model = default(T))
        {
            if (settings == null)
                throw new ArgumentException("settings can't be null");

            var name = typeof(T)?.Name;
            object instance;
            if (model == null)
            {
                instance = name switch
                {
                    nameof(RecaptchaV2Checkbox) => new RecaptchaV2Checkbox { Settings = settings },
                    nameof(RecaptchaV2Invisible) => new RecaptchaV2Invisible { Settings = settings },
                    nameof(RecaptchaV3HiddenInput) => new RecaptchaV3HiddenInput { Settings = settings },
                    _ => throw new ArgumentException(
                        $"Unknown type '{name}' passed as recaptcha version. Please use a valid type for T when using the Recaptcha method.")
                };
            }
            else
                instance = Convert.ChangeType(model, typeof(T));

            string body;
            switch (name)
            {
                case nameof(RecaptchaV2Checkbox):
                    var v2Checkbox = (RecaptchaV2Checkbox)instance;
                    v2Checkbox.Settings ??= settings;
                    body = new Templates.RecaptchaV2Checkbox(v2Checkbox).TransformText();
                    break;
                case nameof(RecaptchaV2Invisible):
                    var v2Invisible = (RecaptchaV2Invisible)instance;
                    v2Invisible.Settings ??= settings;
                    body = new Templates.RecaptchaV2Invisible(v2Invisible).TransformText();
                    break;
                case nameof(RecaptchaV3HiddenInput):
                    var v3 = (RecaptchaV3HiddenInput)instance;
                    v3.Settings ??= settings;
                    body = new Templates.RecaptchaV3HiddenInput(v3).TransformText();
                    break;
                default:
                    body = string.Empty;
                    break;
            }

            return new HtmlString(body);
        }
    }
}


================================================
FILE: reCAPTCHA.AspNetCore/RecaptchaResponse.cs
================================================
using System;

namespace reCAPTCHA.AspNetCore
{
    public class RecaptchaResponse
    {

        public RecaptchaResponse(bool success)
        {
            this.success = success;
        }

        public bool success { get; set; }
        public double score { get; set; }
        public string action { get; set; }
        public DateTime challenge_ts { get; set; }
        public string hostname { get; set; }
    }
}


================================================
FILE: reCAPTCHA.AspNetCore/RecaptchaService.cs
================================================
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using System.Net.Http;
using System.Text.Json;
using System.Threading.Tasks;

namespace reCAPTCHA.AspNetCore
{
    public class RecaptchaService : IRecaptchaService
    {
        private readonly ILogger<RecaptchaService> _logger;
        private static readonly HttpClient Client = new HttpClient();
        public readonly RecaptchaSettings RecaptchaSettings;

        public RecaptchaService(IOptions<RecaptchaSettings> options, ILogger<RecaptchaService> logger)
        {
            _logger = logger;
            RecaptchaSettings = options.Value;
        }

        public async Task<RecaptchaResponse> Validate(HttpRequest request, bool antiForgery = true)
        {
            if (!request.Form.ContainsKey("g-recaptcha-response")) // error if no reason to do anything, this is to alert developers they are calling it without reason.
            {
                _logger.LogError("Google recaptcha response not found in form. Did you forget to include it?");
                return new RecaptchaResponse(false);
            }

            var response = request.Form["g-recaptcha-response"];
            var result = await Client.GetStringAsync($"https://{RecaptchaSettings.Site}/recaptcha/api/siteverify?secret={RecaptchaSettings.SecretKey}&response={response}");
            var captchaResponse = JsonSerializer.Deserialize<RecaptchaResponse>(result);

            if (captchaResponse.success && antiForgery)
                if (captchaResponse.hostname?.ToLower() != request.Host.Host?.ToLower() &&
                    captchaResponse.hostname != "testkey.google.com")
                {
                    _logger.LogError("Recaptcha host, and request host do not match. Forgery attempt?");
                    return new RecaptchaResponse(false);
                }

            return captchaResponse;
        }

        public async Task<RecaptchaResponse> Validate(string responseCode)
        {
            if (string.IsNullOrEmpty(responseCode))
            {
                _logger.LogError("Google recaptcha response is empty?");
                return new RecaptchaResponse(false);
            }

            var result = await Client.GetStringAsync($"https://{RecaptchaSettings.Site}/recaptcha/api/siteverify?secret={RecaptchaSettings.SecretKey}&response={responseCode}");
            var captchaResponse = JsonSerializer.Deserialize<RecaptchaResponse>(result);

            return captchaResponse;
        }
    }
}

================================================
FILE: reCAPTCHA.AspNetCore/RecaptchaServiceCollection.cs
================================================
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using System;
using Microsoft.Extensions.Options;

namespace reCAPTCHA.AspNetCore
{
    /// <summary>
    /// Extension methods for adding reCAPTCHA services to the DI container.
    /// </summary>
    public static class RecaptchaServiceCollection
    {
        /// <summary>
        /// Adds services required for using reCAPTCHA.
        /// </summary>
        /// <param name="services">The <see cref="IServiceCollection"/> to add the services to.</param>
        /// <param name="options">The action used to configure reCAPTCHA.</param>
        /// <returns>The <see cref="IServiceCollection"/> so that additional calls can be chained.</returns>
        public static IServiceCollection AddRecaptcha(this IServiceCollection services, Action<RecaptchaSettings> options)
        {
            if (services == null)
                throw new ArgumentNullException(nameof(services));

            if (options == null)
                throw new ArgumentNullException(nameof(options));

            var recaptchaSettings = new RecaptchaSettings();
            options.Invoke(recaptchaSettings);

            services.Configure(options);
            services.AddTransient<IRecaptchaService, RecaptchaService>();

            return services;
        }

        /// <summary>
        /// Adds services required for using reCAPTCHA.
        /// </summary>
        /// <param name="services">The <see cref="IServiceCollection"/> to add the services to.</param>
        /// <param name="configurationSection">The configuration section that contains reCAPTCHA settings.</param>
        /// <returns>The <see cref="IServiceCollection"/> so that additional calls can be chained.</returns>
        public static IServiceCollection AddRecaptcha(this IServiceCollection services, IConfiguration configurationSection)
        {
            if (services == null)
                throw new ArgumentNullException(nameof(services));

            if (configurationSection == null)
                throw new ArgumentNullException(nameof(configurationSection));

            services.Configure<RecaptchaSettings>(configurationSection);
            services.AddTransient<IRecaptchaService, RecaptchaService>();

            return services;
        }
    }
}

================================================
FILE: reCAPTCHA.AspNetCore/RecaptchaSettings.cs
================================================
namespace reCAPTCHA.AspNetCore
{
    public class RecaptchaSettings
    {
        /// <summary>
        /// Google Recaptcha Site this is often www.google.com, or www.recaptcha.net. You can also use a custom proxy address.
        /// </summary>
        public string Site { get; set; } = "www.google.com";
        /// <summary>
        /// Values for the content security policy directives. See: https://developers.google.com/recaptcha/docs/faq#im-using-content-security-policy-csp-on-my-website.-how-can-i-configure-it-to-work-with-recaptcha
        /// </summary>
        public string ContentSecurityPolicy { get; set; } = string.Empty;
        /// <summary>
        /// Nonce value that will be added as attribute to the inline script to allow it to comply with content security policy when using nonce
        /// </summary>
        public string Nonce { get; set; }
        /// <summary>
        /// Google Recaptcha Secret Key
        /// </summary>
        public string SecretKey { get; set; }
        /// <summary>
        /// Google Recaptcha Site Key
        /// </summary>
        public string SiteKey { get; set; }
    }
}

================================================
FILE: reCAPTCHA.AspNetCore/Templates/RecaptchaV2Checkbox.cs
================================================
// ------------------------------------------------------------------------------
// <auto-generated>
//     This code was generated by a tool.
//     Runtime Version: 16.0.0.0
//  
//     Changes to this file may cause incorrect behavior and will be lost if
//     the code is regenerated.
// </auto-generated>
// ------------------------------------------------------------------------------
namespace reCAPTCHA.AspNetCore.Templates
{
    using System;
    
    /// <summary>
    /// Class to produce the template output
    /// </summary>
    
    #line 1 "E:\Repository\TimothyMeadows\reCAPTCHA.AspNetCore\reCAPTCHA.AspNetCore\Templates\RecaptchaV2Checkbox.tt"
    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TextTemplating", "16.0.0.0")]
    public partial class RecaptchaV2Checkbox : RecaptchaV2CheckboxBase
    {
#line hidden
        /// <summary>
        /// Create the template output
        /// </summary>
        public virtual string TransformText()
        {
            this.Write("\n<div id=\"");
            
            #line 4 "E:\Repository\TimothyMeadows\reCAPTCHA.AspNetCore\reCAPTCHA.AspNetCore\Templates\RecaptchaV2Checkbox.tt"
            this.Write(this.ToStringHelper.ToStringWithCulture(Model.Uid));
            
            #line default
            #line hidden
            this.Write("\" class=\"g-recaptcha\" data-sitekey=\"");
            
            #line 4 "E:\Repository\TimothyMeadows\reCAPTCHA.AspNetCore\reCAPTCHA.AspNetCore\Templates\RecaptchaV2Checkbox.tt"
            this.Write(this.ToStringHelper.ToStringWithCulture(Model.Settings.SiteKey));
            
            #line default
            #line hidden
            this.Write("\" ");
            
            #line 4 "E:\Repository\TimothyMeadows\reCAPTCHA.AspNetCore\reCAPTCHA.AspNetCore\Templates\RecaptchaV2Checkbox.tt"
 if (!string.IsNullOrEmpty(Model.SuccessCallback)) {
            
            #line default
            #line hidden
            this.Write("data-callback=\"");
            
            #line 4 "E:\Repository\TimothyMeadows\reCAPTCHA.AspNetCore\reCAPTCHA.AspNetCore\Templates\RecaptchaV2Checkbox.tt"
            this.Write(this.ToStringHelper.ToStringWithCulture(Model.SuccessCallback));
            
            #line default
            #line hidden
            this.Write("\"");
            
            #line 4 "E:\Repository\TimothyMeadows\reCAPTCHA.AspNetCore\reCAPTCHA.AspNetCore\Templates\RecaptchaV2Checkbox.tt"
}
            
            #line default
            #line hidden
            this.Write(" ");
            
            #line 4 "E:\Repository\TimothyMeadows\reCAPTCHA.AspNetCore\reCAPTCHA.AspNetCore\Templates\RecaptchaV2Checkbox.tt"
 if (!string.IsNullOrEmpty(Model.ErrorCallback)) {
            
            #line default
            #line hidden
            this.Write("data-error-callback=\"");
            
            #line 4 "E:\Repository\TimothyMeadows\reCAPTCHA.AspNetCore\reCAPTCHA.AspNetCore\Templates\RecaptchaV2Checkbox.tt"
            this.Write(this.ToStringHelper.ToStringWithCulture(Model.ErrorCallback));
            
            #line default
            #line hidden
            this.Write("\"");
            
            #line 4 "E:\Repository\TimothyMeadows\reCAPTCHA.AspNetCore\reCAPTCHA.AspNetCore\Templates\RecaptchaV2Checkbox.tt"
}
            
            #line default
            #line hidden
            this.Write(" ");
            
            #line 4 "E:\Repository\TimothyMeadows\reCAPTCHA.AspNetCore\reCAPTCHA.AspNetCore\Templates\RecaptchaV2Checkbox.tt"
 if (!string.IsNullOrEmpty(Model.ExpiredCallback)) {
            
            #line default
            #line hidden
            this.Write("data-expired-callback=\"");
            
            #line 4 "E:\Repository\TimothyMeadows\reCAPTCHA.AspNetCore\reCAPTCHA.AspNetCore\Templates\RecaptchaV2Checkbox.tt"
            this.Write(this.ToStringHelper.ToStringWithCulture(Model.ExpiredCallback));
            
            #line default
            #line hidden
            this.Write("\"");
            
            #line 4 "E:\Repository\TimothyMeadows\reCAPTCHA.AspNetCore\reCAPTCHA.AspNetCore\Templates\RecaptchaV2Checkbox.tt"
}
            
            #line default
            #line hidden
            this.Write("></div>\n<script ");
            
            #line 5 "E:\Repository\TimothyMeadows\reCAPTCHA.AspNetCore\reCAPTCHA.AspNetCore\Templates\RecaptchaV2Checkbox.tt"
 if (!string.IsNullOrEmpty(Model.Settings.Nonce)) {
            
            #line default
            #line hidden
            this.Write("nonce=\"");
            
            #line 5 "E:\Repository\TimothyMeadows\reCAPTCHA.AspNetCore\reCAPTCHA.AspNetCore\Templates\RecaptchaV2Checkbox.tt"
            this.Write(this.ToStringHelper.ToStringWithCulture(Model.Settings.Nonce));
            
            #line default
            #line hidden
            this.Write("\"");
            
            #line 5 "E:\Repository\TimothyMeadows\reCAPTCHA.AspNetCore\reCAPTCHA.AspNetCore\Templates\RecaptchaV2Checkbox.tt"
}
            
            #line default
            #line hidden
            this.Write(">\n\tfunction _");
            
            #line 6 "E:\Repository\TimothyMeadows\reCAPTCHA.AspNetCore\reCAPTCHA.AspNetCore\Templates\RecaptchaV2Checkbox.tt"
            this.Write(this.ToStringHelper.ToStringWithCulture(Model.Uid.ToString().Replace("-", "_")));
            
            #line default
            #line hidden
            this.Write("() {\n\t\tif (typeof grecaptcha !== 'undefined')\n\t\t\tgrecaptcha.render('");
            
            #line 8 "E:\Repository\TimothyMeadows\reCAPTCHA.AspNetCore\reCAPTCHA.AspNetCore\Templates\RecaptchaV2Checkbox.tt"
            this.Write(this.ToStringHelper.ToStringWithCulture(Model.Uid));
            
            #line default
            #line hidden
            this.Write("', {\n\t\t\t\t'sitekey' : '");
            
            #line 9 "E:\Repository\TimothyMeadows\reCAPTCHA.AspNetCore\reCAPTCHA.AspNetCore\Templates\RecaptchaV2Checkbox.tt"
            this.Write(this.ToStringHelper.ToStringWithCulture(Model.Settings.SiteKey));
            
            #line default
            #line hidden
            this.Write("',\n\t\t\t\t'theme' : '");
            
            #line 10 "E:\Repository\TimothyMeadows\reCAPTCHA.AspNetCore\reCAPTCHA.AspNetCore\Templates\RecaptchaV2Checkbox.tt"
            this.Write(this.ToStringHelper.ToStringWithCulture(Model.Theme));
            
            #line default
            #line hidden
            this.Write("',\n\t\t\t\t");
            
            #line 11 "E:\Repository\TimothyMeadows\reCAPTCHA.AspNetCore\reCAPTCHA.AspNetCore\Templates\RecaptchaV2Checkbox.tt"
 if (!string.IsNullOrEmpty(Model.SuccessCallback)) { 
            
            #line default
            #line hidden
            this.Write("\t\t\t\t'callback' : '");
            
            #line 12 "E:\Repository\TimothyMeadows\reCAPTCHA.AspNetCore\reCAPTCHA.AspNetCore\Templates\RecaptchaV2Checkbox.tt"
            this.Write(this.ToStringHelper.ToStringWithCulture(Model.SuccessCallback));
            
            #line default
            #line hidden
            this.Write("',\n\t\t\t\t");
            
            #line 13 "E:\Repository\TimothyMeadows\reCAPTCHA.AspNetCore\reCAPTCHA.AspNetCore\Templates\RecaptchaV2Checkbox.tt"
 } 
            
            #line default
            #line hidden
            this.Write("\t\t\t\t");
            
            #line 14 "E:\Repository\TimothyMeadows\reCAPTCHA.AspNetCore\reCAPTCHA.AspNetCore\Templates\RecaptchaV2Checkbox.tt"
 if (!string.IsNullOrEmpty(Model.ErrorCallback)) { 
            
            #line default
            #line hidden
            this.Write("\t\t\t\t'error-callback' : '");
            
            #line 15 "E:\Repository\TimothyMeadows\reCAPTCHA.AspNetCore\reCAPTCHA.AspNetCore\Templates\RecaptchaV2Checkbox.tt"
            this.Write(this.ToStringHelper.ToStringWithCulture(Model.ErrorCallback));
            
            #line default
            #line hidden
            this.Write("',\n\t\t\t\t");
            
            #line 16 "E:\Repository\TimothyMeadows\reCAPTCHA.AspNetCore\reCAPTCHA.AspNetCore\Templates\RecaptchaV2Checkbox.tt"
 } 
            
            #line default
            #line hidden
            this.Write("\t\t\t\t");
            
            #line 17 "E:\Repository\TimothyMeadows\reCAPTCHA.AspNetCore\reCAPTCHA.AspNetCore\Templates\RecaptchaV2Checkbox.tt"
 if (!string.IsNullOrEmpty(Model.ExpiredCallback)) { 
            
            #line default
            #line hidden
            this.Write("\t\t\t\t'expired-callback' : '");
            
            #line 18 "E:\Repository\TimothyMeadows\reCAPTCHA.AspNetCore\reCAPTCHA.AspNetCore\Templates\RecaptchaV2Checkbox.tt"
            this.Write(this.ToStringHelper.ToStringWithCulture(Model.ExpiredCallback));
            
            #line default
            #line hidden
            this.Write("',\n\t\t\t\t");
            
            #line 19 "E:\Repository\TimothyMeadows\reCAPTCHA.AspNetCore\reCAPTCHA.AspNetCore\Templates\RecaptchaV2Checkbox.tt"
 } 
            
            #line default
            #line hidden
            this.Write("\t\t\t})\n\t}\n</script>\n<script ");
            
            #line 23 "E:\Repository\TimothyMeadows\reCAPTCHA.AspNetCore\reCAPTCHA.AspNetCore\Templates\RecaptchaV2Checkbox.tt"
 if (!string.IsNullOrEmpty(Model.Settings.ContentSecurityPolicy)) {
            
            #line default
            #line hidden
            this.Write("script-src=\"");
            
            #line 23 "E:\Repository\TimothyMeadows\reCAPTCHA.AspNetCore\reCAPTCHA.AspNetCore\Templates\RecaptchaV2Checkbox.tt"
            this.Write(this.ToStringHelper.ToStringWithCulture(Model.Settings.ContentSecurityPolicy));
            
            #line default
            #line hidden
            this.Write("\"");
            
            #line 23 "E:\Repository\TimothyMeadows\reCAPTCHA.AspNetCore\reCAPTCHA.AspNetCore\Templates\RecaptchaV2Checkbox.tt"
}
            
            #line default
            #line hidden
            this.Write(" ");
            
            #line 23 "E:\Repository\TimothyMeadows\reCAPTCHA.AspNetCore\reCAPTCHA.AspNetCore\Templates\RecaptchaV2Checkbox.tt"
 if (!string.IsNullOrEmpty(Model.Settings.ContentSecurityPolicy)) {
            
            #line default
            #line hidden
            this.Write("frame-src=\"");
            
            #line 23 "E:\Repository\TimothyMeadows\reCAPTCHA.AspNetCore\reCAPTCHA.AspNetCore\Templates\RecaptchaV2Checkbox.tt"
            this.Write(this.ToStringHelper.ToStringWithCulture(Model.Settings.ContentSecurityPolicy));
            
            #line default
            #line hidden
            this.Write("\"");
            
            #line 23 "E:\Repository\TimothyMeadows\reCAPTCHA.AspNetCore\reCAPTCHA.AspNetCore\Templates\RecaptchaV2Checkbox.tt"
}
            
            #line default
            #line hidden
            this.Write(" src=\"https://");
            
            #line 23 "E:\Repository\TimothyMeadows\reCAPTCHA.AspNetCore\reCAPTCHA.AspNetCore\Templates\RecaptchaV2Checkbox.tt"
            this.Write(this.ToStringHelper.ToStringWithCulture(Model.Settings.Site));
            
            #line default
            #line hidden
            this.Write("/recaptcha/api.js?onload=_");
            
            #line 23 "E:\Repository\TimothyMeadows\reCAPTCHA.AspNetCore\reCAPTCHA.AspNetCore\Templates\RecaptchaV2Checkbox.tt"
            this.Write(this.ToStringHelper.ToStringWithCulture(Model.Uid.ToString().Replace("-", "_")));
            
            #line default
            #line hidden
            this.Write("&render=explicit&hl=");
            
            #line 23 "E:\Repository\TimothyMeadows\reCAPTCHA.AspNetCore\reCAPTCHA.AspNetCore\Templates\RecaptchaV2Checkbox.tt"
            this.Write(this.ToStringHelper.ToStringWithCulture(Model.Language));
            
            #line default
            #line hidden
            this.Write("\" async defer></script>");
            return this.GenerationEnvironment.ToString();
        }
    }
    
    #line default
    #line hidden
    #region Base class
    /// <summary>
    /// Base class for this transformation
    /// </summary>
    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TextTemplating", "16.0.0.0")]
    public class RecaptchaV2CheckboxBase
    {
        #region Fields
        private global::System.Text.StringBuilder generationEnvironmentField;
        private global::System.CodeDom.Compiler.CompilerErrorCollection errorsField;
        private global::System.Collections.Generic.List<int> indentLengthsField;
        private string currentIndentField = "";
        private bool endsWithNewline;
        private global::System.Collections.Generic.IDictionary<string, object> sessionField;
        #endregion
        #region Properties
        /// <summary>
        /// The string builder that generation-time code is using to assemble generated output
        /// </summary>
        protected System.Text.StringBuilder GenerationEnvironment
        {
            get
            {
                if ((this.generationEnvironmentField == null))
                {
                    this.generationEnvironmentField = new global::System.Text.StringBuilder();
                }
                return this.generationEnvironmentField;
            }
            set
            {
                this.generationEnvironmentField = value;
            }
        }
        /// <summary>
        /// The error collection for the generation process
        /// </summary>
        public System.CodeDom.Compiler.CompilerErrorCollection Errors
        {
            get
            {
                if ((this.errorsField == null))
                {
                    this.errorsField = new global::System.CodeDom.Compiler.CompilerErrorCollection();
                }
                return this.errorsField;
            }
        }
        /// <summary>
        /// A list of the lengths of each indent that was added with PushIndent
        /// </summary>
        private System.Collections.Generic.List<int> indentLengths
        {
            get
            {
                if ((this.indentLengthsField == null))
                {
                    this.indentLengthsField = new global::System.Collections.Generic.List<int>();
                }
                return this.indentLengthsField;
            }
        }
        /// <summary>
        /// Gets the current indent we use when adding lines to the output
        /// </summary>
        public string CurrentIndent
        {
            get
            {
                return this.currentIndentField;
            }
        }
        /// <summary>
        /// Current transformation session
        /// </summary>
        public virtual global::System.Collections.Generic.IDictionary<string, object> Session
        {
            get
            {
                return this.sessionField;
            }
            set
            {
                this.sessionField = value;
            }
        }
        #endregion
        #region Transform-time helpers
        /// <summary>
        /// Write text directly into the generated output
        /// </summary>
        public void Write(string textToAppend)
        {
            if (string.IsNullOrEmpty(textToAppend))
            {
                return;
            }
            // If we're starting off, or if the previous text ended with a newline,
            // we have to append the current indent first.
            if (((this.GenerationEnvironment.Length == 0) 
                        || this.endsWithNewline))
            {
                this.GenerationEnvironment.Append(this.currentIndentField);
                this.endsWithNewline = false;
            }
            // Check if the current text ends with a newline
            if (textToAppend.EndsWith(global::System.Environment.NewLine, global::System.StringComparison.CurrentCulture))
            {
                this.endsWithNewline = true;
            }
            // This is an optimization. If the current indent is "", then we don't have to do any
            // of the more complex stuff further down.
            if ((this.currentIndentField.Length == 0))
            {
                this.GenerationEnvironment.Append(textToAppend);
                return;
            }
            // Everywhere there is a newline in the text, add an indent after it
            textToAppend = textToAppend.Replace(global::System.Environment.NewLine, (global::System.Environment.NewLine + this.currentIndentField));
            // If the text ends with a newline, then we should strip off the indent added at the very end
            // because the appropriate indent will be added when the next time Write() is called
            if (this.endsWithNewline)
            {
                this.GenerationEnvironment.Append(textToAppend, 0, (textToAppend.Length - this.currentIndentField.Length));
            }
            else
            {
                this.GenerationEnvironment.Append(textToAppend);
            }
        }
        /// <summary>
        /// Write text directly into the generated output
        /// </summary>
        public void WriteLine(string textToAppend)
        {
            this.Write(textToAppend);
            this.GenerationEnvironment.AppendLine();
            this.endsWithNewline = true;
        }
        /// <summary>
        /// Write formatted text directly into the generated output
        /// </summary>
        public void Write(string format, params object[] args)
        {
            this.Write(string.Format(global::System.Globalization.CultureInfo.CurrentCulture, format, args));
        }
        /// <summary>
        /// Write formatted text directly into the generated output
        /// </summary>
        public void WriteLine(string format, params object[] args)
        {
            this.WriteLine(string.Format(global::System.Globalization.CultureInfo.CurrentCulture, format, args));
        }
        /// <summary>
        /// Raise an error
        /// </summary>
        public void Error(string message)
        {
            System.CodeDom.Compiler.CompilerError error = new global::System.CodeDom.Compiler.CompilerError();
            error.ErrorText = message;
            this.Errors.Add(error);
        }
        /// <summary>
        /// Raise a warning
        /// </summary>
        public void Warning(string message)
        {
            System.CodeDom.Compiler.CompilerError error = new global::System.CodeDom.Compiler.CompilerError();
            error.ErrorText = message;
            error.IsWarning = true;
            this.Errors.Add(error);
        }
        /// <summary>
        /// Increase the indent
        /// </summary>
        public void PushIndent(string indent)
        {
            if ((indent == null))
            {
                throw new global::System.ArgumentNullException("indent");
            }
            this.currentIndentField = (this.currentIndentField + indent);
            this.indentLengths.Add(indent.Length);
        }
        /// <summary>
        /// Remove the last indent that was added with PushIndent
        /// </summary>
        public string PopIndent()
        {
            string returnValue = "";
            if ((this.indentLengths.Count > 0))
            {
                int indentLength = this.indentLengths[(this.indentLengths.Count - 1)];
                this.indentLengths.RemoveAt((this.indentLengths.Count - 1));
                if ((indentLength > 0))
                {
                    returnValue = this.currentIndentField.Substring((this.currentIndentField.Length - indentLength));
                    this.currentIndentField = this.currentIndentField.Remove((this.currentIndentField.Length - indentLength));
                }
            }
            return returnValue;
        }
        /// <summary>
        /// Remove any indentation
        /// </summary>
        public void ClearIndent()
        {
            this.indentLengths.Clear();
            this.currentIndentField = "";
        }
        #endregion
        #region ToString Helpers
        /// <summary>
        /// Utility class to produce culture-oriented representation of an object as a string.
        /// </summary>
        public class ToStringInstanceHelper
        {
            private System.IFormatProvider formatProviderField  = global::System.Globalization.CultureInfo.InvariantCulture;
            /// <summary>
            /// Gets or sets format provider to be used by ToStringWithCulture method.
            /// </summary>
            public System.IFormatProvider FormatProvider
            {
                get
                {
                    return this.formatProviderField ;
                }
                set
                {
                    if ((value != null))
                    {
                        this.formatProviderField  = value;
                    }
                }
            }
            /// <summary>
            /// This is called from the compile/run appdomain to convert objects within an expression block to a string
            /// </summary>
            public string ToStringWithCulture(object objectToConvert)
            {
                if ((objectToConvert == null))
                {
                    throw new global::System.ArgumentNullException("objectToConvert");
                }
                System.Type t = objectToConvert.GetType();
                System.Reflection.MethodInfo method = t.GetMethod("ToString", new System.Type[] {
                            typeof(System.IFormatProvider)});
                if ((method == null))
                {
                    return objectToConvert.ToString();
                }
                else
                {
                    return ((string)(method.Invoke(objectToConvert, new object[] {
                                this.formatProviderField })));
                }
            }
        }
        private ToStringInstanceHelper toStringHelperField = new ToStringInstanceHelper();
        /// <summary>
        /// Helper to produce culture-oriented representation of an object as a string
        /// </summary>
        public ToStringInstanceHelper ToStringHelper
        {
            get
            {
                return this.toStringHelperField;
            }
        }
        #endregion
    }
    #endregion
}


================================================
FILE: reCAPTCHA.AspNetCore/Templates/RecaptchaV2Checkbox.tt
================================================
<#@ template language="C#" #>
<#@ assembly name="System.Core" #>

<div id="<#= Model.Uid #>" class="g-recaptcha" data-sitekey="<#= Model.Settings.SiteKey #>" <# if (!string.IsNullOrEmpty(Model.SuccessCallback)) {#>data-callback="<#= Model.SuccessCallback #>"<#}#> <# if (!string.IsNullOrEmpty(Model.ErrorCallback)) {#>data-error-callback="<#= Model.ErrorCallback #>"<#}#> <# if (!string.IsNullOrEmpty(Model.ExpiredCallback)) {#>data-expired-callback="<#= Model.ExpiredCallback #>"<#}#>></div>
<script <# if (!string.IsNullOrEmpty(Model.Settings.Nonce)) {#>nonce="<#= Model.Settings.Nonce #>"<#}#>>
	function _<#= Model.Uid.ToString().Replace("-", "_") #>() {
		if (typeof grecaptcha !== 'undefined')
			grecaptcha.render('<#= Model.Uid #>', {
				'sitekey' : '<#= Model.Settings.SiteKey #>',
				'theme' : '<#= Model.Theme #>',
				<# if (!string.IsNullOrEmpty(Model.SuccessCallback)) { #>
				'callback' : '<#= Model.SuccessCallback #>',
				<# } #>
				<# if (!string.IsNullOrEmpty(Model.ErrorCallback)) { #>
				'error-callback' : '<#= Model.ErrorCallback #>',
				<# } #>
				<# if (!string.IsNullOrEmpty(Model.ExpiredCallback)) { #>
				'expired-callback' : '<#= Model.ExpiredCallback #>',
				<# } #>
			})
	}
</script>
<script <# if (!string.IsNullOrEmpty(Model.Settings.ContentSecurityPolicy)) {#>script-src="<#= Model.Settings.ContentSecurityPolicy #>"<#}#> <# if (!string.IsNullOrEmpty(Model.Settings.ContentSecurityPolicy)) {#>frame-src="<#= Model.Settings.ContentSecurityPolicy #>"<#}#> src="https://<#= Model.Settings.Site #>/recaptcha/api.js?onload=_<#= Model.Uid.ToString().Replace("-", "_") #>&render=explicit&hl=<#= Model.Language #>" async defer></script>

================================================
FILE: reCAPTCHA.AspNetCore/Templates/RecaptchaV2CheckboxModelBinder.cs
================================================
using System;
using System.Collections.Generic;
using System.Text;

namespace reCAPTCHA.AspNetCore.Templates
{
    public partial class RecaptchaV2Checkbox
    {
        public readonly Versions.RecaptchaV2Checkbox Model;

        public RecaptchaV2Checkbox(Versions.RecaptchaV2Checkbox model)
        {
            if (model.Settings == null)
                throw new ArgumentException("Settings can't be null.");

            var defaultModel = new Versions.RecaptchaV2Checkbox();
            if (model.Uid.Equals(Guid.Empty))
                model.Uid = defaultModel.Uid;

            if (string.IsNullOrEmpty(model.Language))
                model.Language = defaultModel.Language;

            if (string.IsNullOrEmpty(model.Id))
                model.Id = defaultModel.Id;

            if (string.IsNullOrEmpty(model.Theme))
                model.Theme = defaultModel.Theme;

            Model = model;
        }
    }
}


================================================
FILE: reCAPTCHA.AspNetCore/Templates/RecaptchaV2Invisible.cs
================================================
// ------------------------------------------------------------------------------
// <auto-generated>
//     This code was generated by a tool.
//     Runtime Version: 16.0.0.0
//  
//     Changes to this file may cause incorrect behavior and will be lost if
//     the code is regenerated.
// </auto-generated>
// ------------------------------------------------------------------------------
namespace reCAPTCHA.AspNetCore.Templates
{
    using System.Linq;
    using System.Text;
    using System.Collections.Generic;
    using System;
    
    /// <summary>
    /// Class to produce the template output
    /// </summary>
    
    #line 1 "E:\Repository\TimothyMeadows\reCAPTCHA.AspNetCore\reCAPTCHA.AspNetCore\Templates\RecaptchaV2Invisible.tt"
    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TextTemplating", "16.0.0.0")]
    public partial class RecaptchaV2Invisible : RecaptchaV2InvisibleBase
    {
#line hidden
        /// <summary>
        /// Create the template output
        /// </summary>
        public virtual string TransformText()
        {
            this.Write("\n<script ");
            
            #line 7 "E:\Repository\TimothyMeadows\reCAPTCHA.AspNetCore\reCAPTCHA.AspNetCore\Templates\RecaptchaV2Invisible.tt"
 if (!string.IsNullOrEmpty(Model.Settings.Nonce)) {
            
            #line default
            #line hidden
            this.Write("nonce=\"");
            
            #line 7 "E:\Repository\TimothyMeadows\reCAPTCHA.AspNetCore\reCAPTCHA.AspNetCore\Templates\RecaptchaV2Invisible.tt"
            this.Write(this.ToStringHelper.ToStringWithCulture(Model.Settings.Nonce));
            
            #line default
            #line hidden
            this.Write("\"");
            
            #line 7 "E:\Repository\TimothyMeadows\reCAPTCHA.AspNetCore\reCAPTCHA.AspNetCore\Templates\RecaptchaV2Invisible.tt"
}
            
            #line default
            #line hidden
            this.Write(">\n\tfunction _");
            
            #line 8 "E:\Repository\TimothyMeadows\reCAPTCHA.AspNetCore\reCAPTCHA.AspNetCore\Templates\RecaptchaV2Invisible.tt"
            this.Write(this.ToStringHelper.ToStringWithCulture(Model.Uid.ToString().Replace("-", "_")));
            
            #line default
            #line hidden
            this.Write("() {\n\t\tif (typeof grecaptcha !== 'undefined') {\n\t\t\tgrecaptcha.render('");
            
            #line 10 "E:\Repository\TimothyMeadows\reCAPTCHA.AspNetCore\reCAPTCHA.AspNetCore\Templates\RecaptchaV2Invisible.tt"
            this.Write(this.ToStringHelper.ToStringWithCulture(Model.Id));
            
            #line default
            #line hidden
            this.Write("', {\n\t\t\t\t'sitekey' : '");
            
            #line 11 "E:\Repository\TimothyMeadows\reCAPTCHA.AspNetCore\reCAPTCHA.AspNetCore\Templates\RecaptchaV2Invisible.tt"
            this.Write(this.ToStringHelper.ToStringWithCulture(Model.Settings.SiteKey));
            
            #line default
            #line hidden
            this.Write("',\n\t\t\t\t'callback' : _");
            
            #line 12 "E:\Repository\TimothyMeadows\reCAPTCHA.AspNetCore\reCAPTCHA.AspNetCore\Templates\RecaptchaV2Invisible.tt"
            this.Write(this.ToStringHelper.ToStringWithCulture(Model.Uid.ToString().Replace("-", "_")));
            
            #line default
            #line hidden
            this.Write("_,\n\t\t\t\t");
            
            #line 13 "E:\Repository\TimothyMeadows\reCAPTCHA.AspNetCore\reCAPTCHA.AspNetCore\Templates\RecaptchaV2Invisible.tt"
 if (!string.IsNullOrEmpty(Model.ErrorCallback)) { 
            
            #line default
            #line hidden
            this.Write("\t\t\t\t'error-callback' : '");
            
            #line 14 "E:\Repository\TimothyMeadows\reCAPTCHA.AspNetCore\reCAPTCHA.AspNetCore\Templates\RecaptchaV2Invisible.tt"
            this.Write(this.ToStringHelper.ToStringWithCulture(Model.ErrorCallback));
            
            #line default
            #line hidden
            this.Write("',\n\t\t\t\t");
            
            #line 15 "E:\Repository\TimothyMeadows\reCAPTCHA.AspNetCore\reCAPTCHA.AspNetCore\Templates\RecaptchaV2Invisible.tt"
 } 
            
            #line default
            #line hidden
            this.Write("\t\t\t\t");
            
            #line 16 "E:\Repository\TimothyMeadows\reCAPTCHA.AspNetCore\reCAPTCHA.AspNetCore\Templates\RecaptchaV2Invisible.tt"
 if (!string.IsNullOrEmpty(Model.ExpiredCallback)) { 
            
            #line default
            #line hidden
            this.Write("\t\t\t\t'expired-callback' : '");
            
            #line 17 "E:\Repository\TimothyMeadows\reCAPTCHA.AspNetCore\reCAPTCHA.AspNetCore\Templates\RecaptchaV2Invisible.tt"
            this.Write(this.ToStringHelper.ToStringWithCulture(Model.ExpiredCallback));
            
            #line default
            #line hidden
            this.Write("',\n\t\t\t\t");
            
            #line 18 "E:\Repository\TimothyMeadows\reCAPTCHA.AspNetCore\reCAPTCHA.AspNetCore\Templates\RecaptchaV2Invisible.tt"
 } 
            
            #line default
            #line hidden
            this.Write("\t\t\t});\n\n\t\t\tdocument.getElementById('");
            
            #line 21 "E:\Repository\TimothyMeadows\reCAPTCHA.AspNetCore\reCAPTCHA.AspNetCore\Templates\RecaptchaV2Invisible.tt"
            this.Write(this.ToStringHelper.ToStringWithCulture(Model.Id));
            
            #line default
            #line hidden
            this.Write("').onclick = function(e) {\n\t\t\t\te.preventDefault();\n\t\t\t\tgrecaptcha.execute();\n\t\t\t};\n\t\t}\n\t}\n\n\tfunction _");
            
            #line 28 "E:\Repository\TimothyMeadows\reCAPTCHA.AspNetCore\reCAPTCHA.AspNetCore\Templates\RecaptchaV2Invisible.tt"
            this.Write(this.ToStringHelper.ToStringWithCulture(Model.Uid.ToString().Replace("-", "_")));
            
            #line default
            #line hidden
            this.Write("_(token) {\n\t\tdocument.getElementById('");
            
            #line 29 "E:\Repository\TimothyMeadows\reCAPTCHA.AspNetCore\reCAPTCHA.AspNetCore\Templates\RecaptchaV2Invisible.tt"
            this.Write(this.ToStringHelper.ToStringWithCulture(Model.Id));
            
            #line default
            #line hidden
            this.Write("').form.submit();\n\t\t");
            
            #line 30 "E:\Repository\TimothyMeadows\reCAPTCHA.AspNetCore\reCAPTCHA.AspNetCore\Templates\RecaptchaV2Invisible.tt"
 if (!string.IsNullOrEmpty(Model.SuccessCallback)) { 
            
            #line default
            #line hidden
            this.Write("\t\t");
            
            #line 31 "E:\Repository\TimothyMeadows\reCAPTCHA.AspNetCore\reCAPTCHA.AspNetCore\Templates\RecaptchaV2Invisible.tt"
            this.Write(this.ToStringHelper.ToStringWithCulture(Model.SuccessCallback));
            
            #line default
            #line hidden
            this.Write("(token);\n\t\t");
            
            #line 32 "E:\Repository\TimothyMeadows\reCAPTCHA.AspNetCore\reCAPTCHA.AspNetCore\Templates\RecaptchaV2Invisible.tt"
 } 
            
            #line default
            #line hidden
            this.Write("\t}\n</script>\n<script ");
            
            #line 35 "E:\Repository\TimothyMeadows\reCAPTCHA.AspNetCore\reCAPTCHA.AspNetCore\Templates\RecaptchaV2Invisible.tt"
 if (!string.IsNullOrEmpty(Model.Settings.ContentSecurityPolicy)) {
            
            #line default
            #line hidden
            this.Write("script-src=\"");
            
            #line 35 "E:\Repository\TimothyMeadows\reCAPTCHA.AspNetCore\reCAPTCHA.AspNetCore\Templates\RecaptchaV2Invisible.tt"
            this.Write(this.ToStringHelper.ToStringWithCulture(Model.Settings.ContentSecurityPolicy));
            
            #line default
            #line hidden
            this.Write("\"");
            
            #line 35 "E:\Repository\TimothyMeadows\reCAPTCHA.AspNetCore\reCAPTCHA.AspNetCore\Templates\RecaptchaV2Invisible.tt"
}
            
            #line default
            #line hidden
            this.Write(" ");
            
            #line 35 "E:\Repository\TimothyMeadows\reCAPTCHA.AspNetCore\reCAPTCHA.AspNetCore\Templates\RecaptchaV2Invisible.tt"
 if (!string.IsNullOrEmpty(Model.Settings.ContentSecurityPolicy)) {
            
            #line default
            #line hidden
            this.Write("frame-src=\"");
            
            #line 35 "E:\Repository\TimothyMeadows\reCAPTCHA.AspNetCore\reCAPTCHA.AspNetCore\Templates\RecaptchaV2Invisible.tt"
            this.Write(this.ToStringHelper.ToStringWithCulture(Model.Settings.ContentSecurityPolicy));
            
            #line default
            #line hidden
            this.Write("\"");
            
            #line 35 "E:\Repository\TimothyMeadows\reCAPTCHA.AspNetCore\reCAPTCHA.AspNetCore\Templates\RecaptchaV2Invisible.tt"
}
            
            #line default
            #line hidden
            this.Write(" src=\"https://");
            
            #line 35 "E:\Repository\TimothyMeadows\reCAPTCHA.AspNetCore\reCAPTCHA.AspNetCore\Templates\RecaptchaV2Invisible.tt"
            this.Write(this.ToStringHelper.ToStringWithCulture(Model.Settings.Site));
            
            #line default
            #line hidden
            this.Write("/recaptcha/api.js?onload=_");
            
            #line 35 "E:\Repository\TimothyMeadows\reCAPTCHA.AspNetCore\reCAPTCHA.AspNetCore\Templates\RecaptchaV2Invisible.tt"
            this.Write(this.ToStringHelper.ToStringWithCulture(Model.Uid.ToString().Replace("-", "_")));
            
            #line default
            #line hidden
            this.Write("&render=explicit&hl=");
            
            #line 35 "E:\Repository\TimothyMeadows\reCAPTCHA.AspNetCore\reCAPTCHA.AspNetCore\Templates\RecaptchaV2Invisible.tt"
            this.Write(this.ToStringHelper.ToStringWithCulture(Model.Language));
            
            #line default
            #line hidden
            this.Write("\" async defer></script>");
            return this.GenerationEnvironment.ToString();
        }
    }
    
    #line default
    #line hidden
    #region Base class
    /// <summary>
    /// Base class for this transformation
    /// </summary>
    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TextTemplating", "16.0.0.0")]
    public class RecaptchaV2InvisibleBase
    {
        #region Fields
        private global::System.Text.StringBuilder generationEnvironmentField;
        private global::System.CodeDom.Compiler.CompilerErrorCollection errorsField;
        private global::System.Collections.Generic.List<int> indentLengthsField;
        private string currentIndentField = "";
        private bool endsWithNewline;
        private global::System.Collections.Generic.IDictionary<string, object> sessionField;
        #endregion
        #region Properties
        /// <summary>
        /// The string builder that generation-time code is using to assemble generated output
        /// </summary>
        protected System.Text.StringBuilder GenerationEnvironment
        {
            get
            {
                if ((this.generationEnvironmentField == null))
                {
                    this.generationEnvironmentField = new global::System.Text.StringBuilder();
                }
                return this.generationEnvironmentField;
            }
            set
            {
                this.generationEnvironmentField = value;
            }
        }
        /// <summary>
        /// The error collection for the generation process
        /// </summary>
        public System.CodeDom.Compiler.CompilerErrorCollection Errors
        {
            get
            {
                if ((this.errorsField == null))
                {
                    this.errorsField = new global::System.CodeDom.Compiler.CompilerErrorCollection();
                }
                return this.errorsField;
            }
        }
        /// <summary>
        /// A list of the lengths of each indent that was added with PushIndent
        /// </summary>
        private System.Collections.Generic.List<int> indentLengths
        {
            get
            {
                if ((this.indentLengthsField == null))
                {
                    this.indentLengthsField = new global::System.Collections.Generic.List<int>();
                }
                return this.indentLengthsField;
            }
        }
        /// <summary>
        /// Gets the current indent we use when adding lines to the output
        /// </summary>
        public string CurrentIndent
        {
            get
            {
                return this.currentIndentField;
            }
        }
        /// <summary>
        /// Current transformation session
        /// </summary>
        public virtual global::System.Collections.Generic.IDictionary<string, object> Session
        {
            get
            {
                return this.sessionField;
            }
            set
            {
                this.sessionField = value;
            }
        }
        #endregion
        #region Transform-time helpers
        /// <summary>
        /// Write text directly into the generated output
        /// </summary>
        public void Write(string textToAppend)
        {
            if (string.IsNullOrEmpty(textToAppend))
            {
                return;
            }
            // If we're starting off, or if the previous text ended with a newline,
            // we have to append the current indent first.
            if (((this.GenerationEnvironment.Length == 0) 
                        || this.endsWithNewline))
            {
                this.GenerationEnvironment.Append(this.currentIndentField);
                this.endsWithNewline = false;
            }
            // Check if the current text ends with a newline
            if (textToAppend.EndsWith(global::System.Environment.NewLine, global::System.StringComparison.CurrentCulture))
            {
                this.endsWithNewline = true;
            }
            // This is an optimization. If the current indent is "", then we don't have to do any
            // of the more complex stuff further down.
            if ((this.currentIndentField.Length == 0))
            {
                this.GenerationEnvironment.Append(textToAppend);
                return;
            }
            // Everywhere there is a newline in the text, add an indent after it
            textToAppend = textToAppend.Replace(global::System.Environment.NewLine, (global::System.Environment.NewLine + this.currentIndentField));
            // If the text ends with a newline, then we should strip off the indent added at the very end
            // because the appropriate indent will be added when the next time Write() is called
            if (this.endsWithNewline)
            {
                this.GenerationEnvironment.Append(textToAppend, 0, (textToAppend.Length - this.currentIndentField.Length));
            }
            else
            {
                this.GenerationEnvironment.Append(textToAppend);
            }
        }
        /// <summary>
        /// Write text directly into the generated output
        /// </summary>
        public void WriteLine(string textToAppend)
        {
            this.Write(textToAppend);
            this.GenerationEnvironment.AppendLine();
            this.endsWithNewline = true;
        }
        /// <summary>
        /// Write formatted text directly into the generated output
        /// </summary>
        public void Write(string format, params object[] args)
        {
            this.Write(string.Format(global::System.Globalization.CultureInfo.CurrentCulture, format, args));
        }
        /// <summary>
        /// Write formatted text directly into the generated output
        /// </summary>
        public void WriteLine(string format, params object[] args)
        {
            this.WriteLine(string.Format(global::System.Globalization.CultureInfo.CurrentCulture, format, args));
        }
        /// <summary>
        /// Raise an error
        /// </summary>
        public void Error(string message)
        {
            System.CodeDom.Compiler.CompilerError error = new global::System.CodeDom.Compiler.CompilerError();
            error.ErrorText = message;
            this.Errors.Add(error);
        }
        /// <summary>
        /// Raise a warning
        /// </summary>
        public void Warning(string message)
        {
            System.CodeDom.Compiler.CompilerError error = new global::System.CodeDom.Compiler.CompilerError();
            error.ErrorText = message;
            error.IsWarning = true;
            this.Errors.Add(error);
        }
        /// <summary>
        /// Increase the indent
        /// </summary>
        public void PushIndent(string indent)
        {
            if ((indent == null))
            {
                throw new global::System.ArgumentNullException("indent");
            }
            this.currentIndentField = (this.currentIndentField + indent);
            this.indentLengths.Add(indent.Length);
        }
        /// <summary>
        /// Remove the last indent that was added with PushIndent
        /// </summary>
        public string PopIndent()
        {
            string returnValue = "";
            if ((this.indentLengths.Count > 0))
            {
                int indentLength = this.indentLengths[(this.indentLengths.Count - 1)];
                this.indentLengths.RemoveAt((this.indentLengths.Count - 1));
                if ((indentLength > 0))
                {
                    returnValue = this.currentIndentField.Substring((this.currentIndentField.Length - indentLength));
                    this.currentIndentField = this.currentIndentField.Remove((this.currentIndentField.Length - indentLength));
                }
            }
            return returnValue;
        }
        /// <summary>
        /// Remove any indentation
        /// </summary>
        public void ClearIndent()
        {
            this.indentLengths.Clear();
            this.currentIndentField = "";
        }
        #endregion
        #region ToString Helpers
        /// <summary>
        /// Utility class to produce culture-oriented representation of an object as a string.
        /// </summary>
        public class ToStringInstanceHelper
        {
            private System.IFormatProvider formatProviderField  = global::System.Globalization.CultureInfo.InvariantCulture;
            /// <summary>
            /// Gets or sets format provider to be used by ToStringWithCulture method.
            /// </summary>
            public System.IFormatProvider FormatProvider
            {
                get
                {
                    return this.formatProviderField ;
                }
                set
                {
                    if ((value != null))
                    {
                        this.formatProviderField  = value;
                    }
                }
            }
            /// <summary>
            /// This is called from the compile/run appdomain to convert objects within an expression block to a string
            /// </summary>
            public string ToStringWithCulture(object objectToConvert)
            {
                if ((objectToConvert == null))
                {
                    throw new global::System.ArgumentNullException("objectToConvert");
                }
                System.Type t = objectToConvert.GetType();
                System.Reflection.MethodInfo method = t.GetMethod("ToString", new System.Type[] {
                            typeof(System.IFormatProvider)});
                if ((method == null))
                {
                    return objectToConvert.ToString();
                }
                else
                {
                    return ((string)(method.Invoke(objectToConvert, new object[] {
                                this.formatProviderField })));
                }
            }
        }
        private ToStringInstanceHelper toStringHelperField = new ToStringInstanceHelper();
        /// <summary>
        /// Helper to produce culture-oriented representation of an object as a string
        /// </summary>
        public ToStringInstanceHelper ToStringHelper
        {
            get
            {
                return this.toStringHelperField;
            }
        }
        #endregion
    }
    #endregion
}


================================================
FILE: reCAPTCHA.AspNetCore/Templates/RecaptchaV2Invisible.tt
================================================
<#@ template language="C#" #>
<#@ assembly name="System.Core" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Text" #>
<#@ import namespace="System.Collections.Generic" #>

<script <# if (!string.IsNullOrEmpty(Model.Settings.Nonce)) {#>nonce="<#= Model.Settings.Nonce #>"<#}#>>
	function _<#= Model.Uid.ToString().Replace("-", "_") #>() {
		if (typeof grecaptcha !== 'undefined') {
			grecaptcha.render('<#= Model.Id #>', {
				'sitekey' : '<#= Model.Settings.SiteKey #>',
				'callback' : _<#= Model.Uid.ToString().Replace("-", "_") #>_,
				<# if (!string.IsNullOrEmpty(Model.ErrorCallback)) { #>
				'error-callback' : '<#= Model.ErrorCallback #>',
				<# } #>
				<# if (!string.IsNullOrEmpty(Model.ExpiredCallback)) { #>
				'expired-callback' : '<#= Model.ExpiredCallback #>',
				<# } #>
			});

			document.getElementById('<#= Model.Id #>').onclick = function(e) {
				e.preventDefault();
				grecaptcha.execute();
			};
		}
	}

	function _<#= Model.Uid.ToString().Replace("-", "_") #>_(token) {
		document.getElementById('<#= Model.Id #>').form.submit();
		<# if (!string.IsNullOrEmpty(Model.SuccessCallback)) { #>
		<#= Model.SuccessCallback #>(token);
		<# } #>
	}
</script>
<script <# if (!string.IsNullOrEmpty(Model.Settings.ContentSecurityPolicy)) {#>script-src="<#= Model.Settings.ContentSecurityPolicy #>"<#}#> <# if (!string.IsNullOrEmpty(Model.Settings.ContentSecurityPolicy)) {#>frame-src="<#= Model.Settings.ContentSecurityPolicy #>"<#}#> src="https://<#= Model.Settings.Site #>/recaptcha/api.js?onload=_<#= Model.Uid.ToString().Replace("-", "_") #>&render=explicit&hl=<#= Model.Language #>" async defer></script>

================================================
FILE: reCAPTCHA.AspNetCore/Templates/RecaptchaV2InvisibleModelBinder.cs
================================================
using System;
using System.Collections.Generic;
using System.Text;

namespace reCAPTCHA.AspNetCore.Templates
{
    public partial class RecaptchaV2Invisible
    {
        public readonly Versions.RecaptchaV2Invisible Model;

        public RecaptchaV2Invisible(Versions.RecaptchaV2Invisible model)
        {
            if (model.Settings == null)
                throw new ArgumentException("Settings can't be null.");

            var defaultModel = new Versions.RecaptchaV2Invisible();
            if (model.Uid.Equals(Guid.Empty))
                model.Uid = defaultModel.Uid;

            if (string.IsNullOrEmpty(model.Language))
                model.Language = defaultModel.Language;

            if (string.IsNullOrEmpty(model.Id))
                model.Id = defaultModel.Id;

            Model = model;
        }
    }
}


================================================
FILE: reCAPTCHA.AspNetCore/Templates/RecaptchaV3HiddenInput.cs
================================================
// ------------------------------------------------------------------------------
// <auto-generated>
//     This code was generated by a tool.
//     Runtime Version: 16.0.0.0
//  
//     Changes to this file may cause incorrect behavior and will be lost if
//     the code is regenerated.
// </auto-generated>
// ------------------------------------------------------------------------------
namespace reCAPTCHA.AspNetCore.Templates
{
    using System.Linq;
    using System.Text;
    using System.Collections.Generic;
    using System;
    
    /// <summary>
    /// Class to produce the template output
    /// </summary>
    
    #line 1 "E:\Repository\TimothyMeadows\reCAPTCHA.AspNetCore\reCAPTCHA.AspNetCore\Templates\RecaptchaV3HiddenInput.tt"
    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TextTemplating", "16.0.0.0")]
    public partial class RecaptchaV3HiddenInput : RecaptchaV3HiddenInputBase
    {
#line hidden
        /// <summary>
        /// Create the template output
        /// </summary>
        public virtual string TransformText()
        {
            this.Write("\n<input id=\"");
            
            #line 7 "E:\Repository\TimothyMeadows\reCAPTCHA.AspNetCore\reCAPTCHA.AspNetCore\Templates\RecaptchaV3HiddenInput.tt"
            this.Write(this.ToStringHelper.ToStringWithCulture(Model.Id));
            
            #line default
            #line hidden
            this.Write("\" name=\"g-recaptcha-response\" type=\"hidden\" value=\"\" />\n<script ");
            
            #line 8 "E:\Repository\TimothyMeadows\reCAPTCHA.AspNetCore\reCAPTCHA.AspNetCore\Templates\RecaptchaV3HiddenInput.tt"
 if (!string.IsNullOrEmpty(Model.Settings.ContentSecurityPolicy)) {
            
            #line default
            #line hidden
            this.Write("script-src=\"");
            
            #line 8 "E:\Repository\TimothyMeadows\reCAPTCHA.AspNetCore\reCAPTCHA.AspNetCore\Templates\RecaptchaV3HiddenInput.tt"
            this.Write(this.ToStringHelper.ToStringWithCulture(Model.Settings.ContentSecurityPolicy));
            
            #line default
            #line hidden
            this.Write("\"");
            
            #line 8 "E:\Repository\TimothyMeadows\reCAPTCHA.AspNetCore\reCAPTCHA.AspNetCore\Templates\RecaptchaV3HiddenInput.tt"
}
            
            #line default
            #line hidden
            this.Write(" ");
            
            #line 8 "E:\Repository\TimothyMeadows\reCAPTCHA.AspNetCore\reCAPTCHA.AspNetCore\Templates\RecaptchaV3HiddenInput.tt"
 if (!string.IsNullOrEmpty(Model.Settings.ContentSecurityPolicy)) {
            
            #line default
            #line hidden
            this.Write("frame-src=\"");
            
            #line 8 "E:\Repository\TimothyMeadows\reCAPTCHA.AspNetCore\reCAPTCHA.AspNetCore\Templates\RecaptchaV3HiddenInput.tt"
            this.Write(this.ToStringHelper.ToStringWithCulture(Model.Settings.ContentSecurityPolicy));
            
            #line default
            #line hidden
            this.Write("\"");
            
            #line 8 "E:\Repository\TimothyMeadows\reCAPTCHA.AspNetCore\reCAPTCHA.AspNetCore\Templates\RecaptchaV3HiddenInput.tt"
}
            
            #line default
            #line hidden
            this.Write(" src=\"https://");
            
            #line 8 "E:\Repository\TimothyMeadows\reCAPTCHA.AspNetCore\reCAPTCHA.AspNetCore\Templates\RecaptchaV3HiddenInput.tt"
            this.Write(this.ToStringHelper.ToStringWithCulture(Model.Settings.Site));
            
            #line default
            #line hidden
            this.Write("/recaptcha/api.js?render=");
            
            #line 8 "E:\Repository\TimothyMeadows\reCAPTCHA.AspNetCore\reCAPTCHA.AspNetCore\Templates\RecaptchaV3HiddenInput.tt"
            this.Write(this.ToStringHelper.ToStringWithCulture(Model.Settings.SiteKey));
            
            #line default
            #line hidden
            this.Write("&hl=");
            
            #line 8 "E:\Repository\TimothyMeadows\reCAPTCHA.AspNetCore\reCAPTCHA.AspNetCore\Templates\RecaptchaV3HiddenInput.tt"
            this.Write(this.ToStringHelper.ToStringWithCulture(Model.Language));
            
            #line default
            #line hidden
            this.Write("\" ");
            
            #line 8 "E:\Repository\TimothyMeadows\reCAPTCHA.AspNetCore\reCAPTCHA.AspNetCore\Templates\RecaptchaV3HiddenInput.tt"
 if (Model.IsAsync) {
            
            #line default
            #line hidden
            this.Write("async defer");
            
            #line 8 "E:\Repository\TimothyMeadows\reCAPTCHA.AspNetCore\reCAPTCHA.AspNetCore\Templates\RecaptchaV3HiddenInput.tt"
}
            
            #line default
            #line hidden
            this.Write(" ></script>\n<script ");
            
            #line 9 "E:\Repository\TimothyMeadows\reCAPTCHA.AspNetCore\reCAPTCHA.AspNetCore\Templates\RecaptchaV3HiddenInput.tt"
 if (!string.IsNullOrEmpty(Model.Settings.Nonce)) {
            
            #line default
            #line hidden
            this.Write("nonce=\"");
            
            #line 9 "E:\Repository\TimothyMeadows\reCAPTCHA.AspNetCore\reCAPTCHA.AspNetCore\Templates\RecaptchaV3HiddenInput.tt"
            this.Write(this.ToStringHelper.ToStringWithCulture(Model.Settings.Nonce));
            
            #line default
            #line hidden
            this.Write("\"");
            
            #line 9 "E:\Repository\TimothyMeadows\reCAPTCHA.AspNetCore\reCAPTCHA.AspNetCore\Templates\RecaptchaV3HiddenInput.tt"
}
            
            #line default
            #line hidden
            this.Write(">\n\tfunction getReCaptcha() {\n\t\tgrecaptcha.execute('");
            
            #line 11 "E:\Repository\TimothyMeadows\reCAPTCHA.AspNetCore\reCAPTCHA.AspNetCore\Templates\RecaptchaV3HiddenInput.tt"
            this.Write(this.ToStringHelper.ToStringWithCulture(Model.Settings.SiteKey));
            
            #line default
            #line hidden
            this.Write("', { 'action': '");
            
            #line 11 "E:\Repository\TimothyMeadows\reCAPTCHA.AspNetCore\reCAPTCHA.AspNetCore\Templates\RecaptchaV3HiddenInput.tt"
            this.Write(this.ToStringHelper.ToStringWithCulture(Model.Action));
            
            #line default
            #line hidden
            this.Write("' }).then(function (token) {\n\t\t\tdocument.getElementById('");
            
            #line 12 "E:\Repository\TimothyMeadows\reCAPTCHA.AspNetCore\reCAPTCHA.AspNetCore\Templates\RecaptchaV3HiddenInput.tt"
            this.Write(this.ToStringHelper.ToStringWithCulture(Model.Id));
            
            #line default
            #line hidden
            this.Write("').value = token;\n\t\t\tsetInterval(function(){getReCaptcha();}, 100000);\n\t\t});\n\t}\n\n\tif (typeof grecaptcha !== 'undefined') {\n\t\tgrecaptcha.ready(function () {\n\t\t\tgetReCaptcha();\n\t\t});\n\t}\n</script>");
            return this.GenerationEnvironment.ToString();
        }
    }
    
    #line default
    #line hidden
    #region Base class
    /// <summary>
    /// Base class for this transformation
    /// </summary>
    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TextTemplating", "16.0.0.0")]
    public class RecaptchaV3HiddenInputBase
    {
        #region Fields
        private global::System.Text.StringBuilder generationEnvironmentField;
        private global::System.CodeDom.Compiler.CompilerErrorCollection errorsField;
        private global::System.Collections.Generic.List<int> indentLengthsField;
        private string currentIndentField = "";
        private bool endsWithNewline;
        private global::System.Collections.Generic.IDictionary<string, object> sessionField;
        #endregion
        #region Properties
        /// <summary>
        /// The string builder that generation-time code is using to assemble generated output
        /// </summary>
        protected System.Text.StringBuilder GenerationEnvironment
        {
            get
            {
                if ((this.generationEnvironmentField == null))
                {
                    this.generationEnvironmentField = new global::System.Text.StringBuilder();
                }
                return this.generationEnvironmentField;
            }
            set
            {
                this.generationEnvironmentField = value;
            }
        }
        /// <summary>
        /// The error collection for the generation process
        /// </summary>
        public System.CodeDom.Compiler.CompilerErrorCollection Errors
        {
            get
            {
                if ((this.errorsField == null))
                {
                    this.errorsField = new global::System.CodeDom.Compiler.CompilerErrorCollection();
                }
                return this.errorsField;
            }
        }
        /// <summary>
        /// A list of the lengths of each indent that was added with PushIndent
        /// </summary>
        private System.Collections.Generic.List<int> indentLengths
        {
            get
            {
                if ((this.indentLengthsField == null))
                {
                    this.indentLengthsField = new global::System.Collections.Generic.List<int>();
                }
                return this.indentLengthsField;
            }
        }
        /// <summary>
        /// Gets the current indent we use when adding lines to the output
        /// </summary>
        public string CurrentIndent
        {
            get
            {
                return this.currentIndentField;
            }
        }
        /// <summary>
        /// Current transformation session
        /// </summary>
        public virtual global::System.Collections.Generic.IDictionary<string, object> Session
        {
            get
            {
                return this.sessionField;
            }
            set
            {
                this.sessionField = value;
            }
        }
        #endregion
        #region Transform-time helpers
        /// <summary>
        /// Write text directly into the generated output
        /// </summary>
        public void Write(string textToAppend)
        {
            if (string.IsNullOrEmpty(textToAppend))
            {
                return;
            }
            // If we're starting off, or if the previous text ended with a newline,
            // we have to append the current indent first.
            if (((this.GenerationEnvironment.Length == 0) 
                        || this.endsWithNewline))
            {
                this.GenerationEnvironment.Append(this.currentIndentField);
                this.endsWithNewline = false;
            }
            // Check if the current text ends with a newline
            if (textToAppend.EndsWith(global::System.Environment.NewLine, global::System.StringComparison.CurrentCulture))
            {
                this.endsWithNewline = true;
            }
            // This is an optimization. If the current indent is "", then we don't have to do any
            // of the more complex stuff further down.
            if ((this.currentIndentField.Length == 0))
            {
                this.GenerationEnvironment.Append(textToAppend);
                return;
            }
            // Everywhere there is a newline in the text, add an indent after it
            textToAppend = textToAppend.Replace(global::System.Environment.NewLine, (global::System.Environment.NewLine + this.currentIndentField));
            // If the text ends with a newline, then we should strip off the indent added at the very end
            // because the appropriate indent will be added when the next time Write() is called
            if (this.endsWithNewline)
            {
                this.GenerationEnvironment.Append(textToAppend, 0, (textToAppend.Length - this.currentIndentField.Length));
            }
            else
            {
                this.GenerationEnvironment.Append(textToAppend);
            }
        }
        /// <summary>
        /// Write text directly into the generated output
        /// </summary>
        public void WriteLine(string textToAppend)
        {
            this.Write(textToAppend);
            this.GenerationEnvironment.AppendLine();
            this.endsWithNewline = true;
        }
        /// <summary>
        /// Write formatted text directly into the generated output
        /// </summary>
        public void Write(string format, params object[] args)
        {
            this.Write(string.Format(global::System.Globalization.CultureInfo.CurrentCulture, format, args));
        }
        /// <summary>
        /// Write formatted text directly into the generated output
        /// </summary>
        public void WriteLine(string format, params object[] args)
        {
            this.WriteLine(string.Format(global::System.Globalization.CultureInfo.CurrentCulture, format, args));
        }
        /// <summary>
        /// Raise an error
        /// </summary>
        public void Error(string message)
        {
            System.CodeDom.Compiler.CompilerError error = new global::System.CodeDom.Compiler.CompilerError();
            error.ErrorText = message;
            this.Errors.Add(error);
        }
        /// <summary>
        /// Raise a warning
        /// </summary>
        public void Warning(string message)
        {
            System.CodeDom.Compiler.CompilerError error = new global::System.CodeDom.Compiler.CompilerError();
            error.ErrorText = message;
            error.IsWarning = true;
            this.Errors.Add(error);
        }
        /// <summary>
        /// Increase the indent
        /// </summary>
        public void PushIndent(string indent)
        {
            if ((indent == null))
            {
                throw new global::System.ArgumentNullException("indent");
            }
            this.currentIndentField = (this.currentIndentField + indent);
            this.indentLengths.Add(indent.Length);
        }
        /// <summary>
        /// Remove the last indent that was added with PushIndent
        /// </summary>
        public string PopIndent()
        {
            string returnValue = "";
            if ((this.indentLengths.Count > 0))
            {
                int indentLength = this.indentLengths[(this.indentLengths.Count - 1)];
                this.indentLengths.RemoveAt((this.indentLengths.Count - 1));
                if ((indentLength > 0))
                {
                    returnValue = this.currentIndentField.Substring((this.currentIndentField.Length - indentLength));
                    this.currentIndentField = this.currentIndentField.Remove((this.currentIndentField.Length - indentLength));
                }
            }
            return returnValue;
        }
        /// <summary>
        /// Remove any indentation
        /// </summary>
        public void ClearIndent()
        {
            this.indentLengths.Clear();
            this.currentIndentField = "";
        }
        #endregion
        #region ToString Helpers
        /// <summary>
        /// Utility class to produce culture-oriented representation of an object as a string.
        /// </summary>
        public class ToStringInstanceHelper
        {
            private System.IFormatProvider formatProviderField  = global::System.Globalization.CultureInfo.InvariantCulture;
            /// <summary>
            /// Gets or sets format provider to be used by ToStringWithCulture method.
            /// </summary>
            public System.IFormatProvider FormatProvider
            {
                get
                {
                    return this.formatProviderField ;
                }
                set
                {
                    if ((value != null))
                    {
                        this.formatProviderField  = value;
                    }
                }
            }
            /// <summary>
            /// This is called from the compile/run appdomain to convert objects within an expression block to a string
            /// </summary>
            public string ToStringWithCulture(object objectToConvert)
            {
                if ((objectToConvert == null))
                {
                    throw new global::System.ArgumentNullException("objectToConvert");
                }
                System.Type t = objectToConvert.GetType();
                System.Reflection.MethodInfo method = t.GetMethod("ToString", new System.Type[] {
                            typeof(System.IFormatProvider)});
                if ((method == null))
                {
                    return objectToConvert.ToString();
                }
                else
                {
                    return ((string)(method.Invoke(objectToConvert, new object[] {
                                this.formatProviderField })));
                }
            }
        }
        private ToStringInstanceHelper toStringHelperField = new ToStringInstanceHelper();
        /// <summary>
        /// Helper to produce culture-oriented representation of an object as a string
        /// </summary>
        public ToStringInstanceHelper ToStringHelper
        {
            get
            {
                return this.toStringHelperField;
            }
        }
        #endregion
    }
    #endregion
}


================================================
FILE: reCAPTCHA.AspNetCore/Templates/RecaptchaV3HiddenInput.tt
================================================
<#@ template language="C#" #>
<#@ assembly name="System.Core" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Text" #>
<#@ import namespace="System.Collections.Generic" #>

<input id="<#= Model.Id #>" name="g-recaptcha-response" type="hidden" value="" />
<script <# if (!string.IsNullOrEmpty(Model.Settings.ContentSecurityPolicy)) {#>script-src="<#= Model.Settings.ContentSecurityPolicy #>"<#}#> <# if (!string.IsNullOrEmpty(Model.Settings.ContentSecurityPolicy)) {#>frame-src="<#= Model.Settings.ContentSecurityPolicy #>"<#}#> src="https://<#= Model.Settings.Site #>/recaptcha/api.js?render=<#= Model.Settings.SiteKey #>&hl=<#= Model.Language #>" <# if (Model.IsAsync) {#>async defer<#}#> ></script>
<script <# if (!string.IsNullOrEmpty(Model.Settings.Nonce)) {#>nonce="<#= Model.Settings.Nonce #>"<#}#>>
	function getReCaptcha() {
		grecaptcha.execute('<#= Model.Settings.SiteKey #>', { 'action': '<#= Model.Action #>' }).then(function (token) {
			document.getElementById('<#= Model.Id #>').value = token;
			setInterval(function(){getReCaptcha();}, 100000);
		});
	}

	if (typeof grecaptcha !== 'undefined') {
		grecaptcha.ready(function () {
			getReCaptcha();
		});
	}
</script>

================================================
FILE: reCAPTCHA.AspNetCore/Templates/RecaptchaV3HiddenInputModelBinder.cs
================================================
using System;
using System.Collections.Generic;
using System.Text;

namespace reCAPTCHA.AspNetCore.Templates
{
    public partial class RecaptchaV3HiddenInput
    {
        public readonly Versions.RecaptchaV3HiddenInput Model;

        public RecaptchaV3HiddenInput(Versions.RecaptchaV3HiddenInput model)
        {
            if (model.Settings == null)
                throw new ArgumentException("Settings can't be null.");

            var defaultModel = new Versions.RecaptchaV3HiddenInput();
            if (model.Uid.Equals(Guid.Empty))
                model.Uid = defaultModel.Uid;

            if (string.IsNullOrEmpty(model.Language))
                model.Language = defaultModel.Language;

            if (string.IsNullOrEmpty(model.Action))
                model.Action = defaultModel.Action;

            Model = model;
        }
    }
}


================================================
FILE: reCAPTCHA.AspNetCore/Versions/RecaptchaV2Checkbox.cs
================================================
namespace reCAPTCHA.AspNetCore.Versions
{
    public class RecaptchaV2Checkbox : RecaptchaVersion
    {
        public string Id { get; set; } = "recaptcha";
        public string Theme { get; set; } = "light";
        public string SuccessCallback { get; set; }
        public string ErrorCallback { get; set; }
        public string ExpiredCallback { get; set; }
    }
}


================================================
FILE: reCAPTCHA.AspNetCore/Versions/RecaptchaV2Invisible.cs
================================================
using System;
using System.Collections.Generic;
using System.Text;

namespace reCAPTCHA.AspNetCore.Versions
{
    public class RecaptchaV2Invisible : RecaptchaVersion
    {
        public string Id { get; set; } = "recaptcha";
        public string SuccessCallback { get; set; }
        public string ErrorCallback { get; set; }
        public string ExpiredCallback { get; set; }
    }
}


================================================
FILE: reCAPTCHA.AspNetCore/Versions/RecaptchaV3HiddenInput.cs
================================================
using System;
using System.Collections.Generic;
using System.Text;

namespace reCAPTCHA.AspNetCore.Versions
{
    public class RecaptchaV3HiddenInput : RecaptchaVersion
    {
        public string Id { get; set; } = "g-recaptcha-response";
        public string Action { get; set; } = "homepage";
        public bool IsAsync { get; set; } = true;
    }
}


================================================
FILE: reCAPTCHA.AspNetCore/Versions/RecaptchaVersion.cs
================================================
using System;
using System.Collections.Generic;
using System.Text;

namespace reCAPTCHA.AspNetCore.Versions
{
    /// <summary>
    /// This is the base model for Google Recaptcha version models. You should only add new properties here if their global across all recaptcha versions.
    /// </summary>
    public class RecaptchaVersion
    {
        public Guid Uid { get; set; } = Guid.NewGuid();
        public string Language { get; set; } = "en";
        public RecaptchaSettings Settings { get; set; }
    }
}


================================================
FILE: reCAPTCHA.AspNetCore/reCAPTCHA.AspNetCore.csproj
================================================
<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework>netcoreapp3.1</TargetFramework>
    <GeneratePackageOnBuild>true</GeneratePackageOnBuild>
    <Version>3.0.12</Version>
    <Authors>Timothy D Meadows II</Authors>
    <PackageLicenseUrl></PackageLicenseUrl>
    <PackageProjectUrl>https://github.com/TimothyMeadows/reCAPTCHA.AspNetCore/</PackageProjectUrl>
    <RepositoryUrl>https://github.com/TimothyMeadows/reCAPTCHA.AspNetCore/</RepositoryUrl>
    <RepositoryType>Github</RepositoryType>
    <Description>Google reCAPTCHA ASP.NET Core 3</Description>
    <PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance>
    <PackageLicenseFile>LICENSE</PackageLicenseFile>
  </PropertyGroup>

  <ItemGroup>
    <FrameworkReference Include="Microsoft.AspNetCore.App" />
  </ItemGroup>

  <ItemGroup>
    <Service Include="{508349b6-6b84-4df5-91f0-309beebad82d}" />
  </ItemGroup>

  <ItemGroup>
    <Compile Update="Templates\RecaptchaV2Checkbox.cs">
      <DesignTime>True</DesignTime>
      <AutoGen>True</AutoGen>
      <DependentUpon>RecaptchaV2Checkbox.tt</DependentUpon>
    </Compile>
    <Compile Update="Templates\RecaptchaV2Invisible.cs">
      <DesignTime>True</DesignTime>
      <AutoGen>True</AutoGen>
      <DependentUpon>RecaptchaV2Invisible.tt</DependentUpon>
    </Compile>
    <Compile Update="Templates\RecaptchaV3HiddenInput.cs">
      <DesignTime>True</DesignTime>
      <AutoGen>True</AutoGen>
      <DependentUpon>RecaptchaV3HiddenInput.tt</DependentUpon>
    </Compile>
  </ItemGroup>

  <ItemGroup>
    <None Update="Templates\RecaptchaV2Checkbox.tt">
      <Generator>TextTemplatingFilePreprocessor</Generator>
      <LastGenOutput>RecaptchaV2Checkbox.cs</LastGenOutput>
    </None>
    <None Update="Templates\RecaptchaV2Invisible.tt">
      <Generator>TextTemplatingFilePreprocessor</Generator>
      <LastGenOutput>RecaptchaV2Invisible.cs</LastGenOutput>
    </None>
    <None Update="Templates\RecaptchaV3HiddenInput.tt">
      <Generator>TextTemplatingFilePreprocessor</Generator>
      <LastGenOutput>RecaptchaV3HiddenInput.cs</LastGenOutput>
    </None>
    <None Include="..\LICENSE">
      <Pack>True</Pack>
      <PackagePath></PackagePath>
    </None>
  </ItemGroup>

  <ItemGroup>
    <PackageReference Include="System.Configuration.ConfigurationManager" Version="5.0.0" />
  </ItemGroup>
</Project>

================================================
FILE: reCAPTCHA.AspNetCore.Example/Controllers/HomeController.cs
================================================
using System.Diagnostics;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using reCAPTCHA.AspNetCore.Attributes;
using reCAPTCHA.AspNetCore.Example.Models;

namespace reCAPTCHA.AspNetCore.Example.Controllers
{
    public class HomeController : Controller
    {
        private readonly IRecaptchaService _recaptcha;
        private readonly double _minimumScore;
        private readonly string _errorMessage;

        public HomeController(IRecaptchaService recaptcha)
        {
            _recaptcha = recaptcha;
            _minimumScore = 0.5;
            _errorMessage = "There was an error validating the google recaptcha response. Please try again, or contact the site owner.";
        }

        public IActionResult Index()
        {
            return View();
        }

        public IActionResult Contact()
        {
            ViewData["Message"] = "Your contact page.";

            return View(new ContactModel());
        }

        public IActionResult Contact2()
        {
            ViewData["Message"] = "Your contact page.";

            return View(new ContactModel());
        }

        public IActionResult Contact3()
        {
            ViewData["Message"] = "Your contact page.";

            return View(new ContactModel());
        }

        public IActionResult Contact4()
        {
            ViewData["Message"] = "Your contact page.";

            return View(new ContactModel());
        }

        [HttpPost]
        [ValidateRecaptcha(0.5)]
        public IActionResult Contact(ContactModel model)
        {
            ViewData["Message"] = "Your contact page.";

            return View(!ModelState.IsValid ? model : new ContactModel());
        }

        [HttpPost]
        public async Task<IActionResult> Contact2(ContactModel model)
        {
            ViewData["Message"] = "Your contact page.";

            var recaptcha = await _recaptcha.Validate(Request);
            if (!recaptcha.success || recaptcha.score != 0 && recaptcha.score < _minimumScore)
                ModelState.AddModelError("Recaptcha", _errorMessage);

            return View(!ModelState.IsValid ? model : new ContactModel());
        }

        [HttpPost]
        public async Task<IActionResult> Contact3(ContactModel model)
        {
            ViewData["Message"] = "Your contact page.";

            return View(!ModelState.IsValid ? model : new ContactModel());
        }

        [HttpPost]
        [ValidateRecaptcha(0.5)]
        public IActionResult Contact4(ContactModel model)
        {
            ViewData["Message"] = "Your contact page.";

            return View(!ModelState.IsValid ? model : new ContactModel());
        }

        public IActionResult Privacy()
        {
            return View();
        }

        [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
        public IActionResult Error()
        {
            return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
        }
    }
}


================================================
FILE: reCAPTCHA.AspNetCore.Example/Controllers/SomeAPIControlelr.cs
================================================
using Microsoft.AspNetCore.Mvc;
using reCAPTCHA.AspNetCore.Attributes;
using reCAPTCHA.AspNetCore.Example.Models;
using System.ComponentModel.DataAnnotations;

namespace reCAPTCHA.AspNetCore.Example.Controllers
{
    [ApiController, Route("SomeApi")]
    public class SomeApiController : Controller
    {
        [HttpGet]
        public ActionResult SomeAction(string someValue, [Required, RecaptchaResponse] string reCaptchaResponseCode)
        {
            return Ok($"I have done something with {someValue} after reCaptcha was validated");
        }

        [HttpPost]
        public ActionResult SomeAction(OtherModel model)
        {
            return Ok($"I have done something after reCaptcha was validated");
        }
    }
}


================================================
FILE: reCAPTCHA.AspNetCore.Example/Models/Contact4Model.cs
================================================
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace reCAPTCHA.AspNetCore.Example.Models
{
    public class Contact4Model
    {
        public ContactModel Form1 { get; set; }
        public ContactModel Form2 { get; set; }
    }
}


================================================
FILE: reCAPTCHA.AspNetCore.Example/Models/ContactModel.cs
================================================
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace reCAPTCHA.AspNetCore.Example.Models
{
    public class ContactModel
    {
        public string Message { get; set; }
    }
}


================================================
FILE: reCAPTCHA.AspNetCore.Example/Models/ErrorViewModel.cs
================================================
using System;

namespace reCAPTCHA.AspNetCore.Example.Models
{
    public class ErrorViewModel
    {
        public string RequestId { get; set; }

        public bool ShowRequestId => !string.IsNullOrEmpty(RequestId);
    }
}


================================================
FILE: reCAPTCHA.AspNetCore.Example/Models/OtherModel.cs
================================================
using reCAPTCHA.AspNetCore.Attributes;

namespace reCAPTCHA.AspNetCore.Example.Models
{
    public class OtherModel
    {
        [RecaptchaResponse(MinimumScore = 0.5)]
        public string ReCaptchaResponseCode { get; set; }
    }
}


================================================
FILE: reCAPTCHA.AspNetCore.Example/Program.cs
================================================
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;

namespace reCAPTCHA.AspNetCore.Example
{
    public class Program
    {
        public static void Main(string[] args)
        {
            CreateHostBuilder(args).Build().Run();
        }

        public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .ConfigureWebHostDefaults(webBuilder =>
                {
                    webBuilder.UseStartup<Startup>();
                });
    }
}


================================================
FILE: reCAPTCHA.AspNetCore.Example/Startup.cs
================================================
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

namespace reCAPTCHA.AspNetCore.Example
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddControllersWithViews();

            //services.AddRecaptcha(Configuration.GetSection("RecaptchaSettings"));

            services.AddRecaptcha(options =>
            {
                options.SecretKey = "6LeIxAcTAAAAAGG-vFI1TnRWxMZNFuojJ4WifJWe";
                options.SiteKey = "6LeIxAcTAAAAAJcZVRqyHh71UMIEGNQ_MXjiZKhI";
            });
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler("/Home/Error");
                // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
                app.UseHsts();
            }
            app.UseHttpsRedirection();
            app.UseStaticFiles();

            app.UseRouting();

            app.UseAuthorization();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllerRoute(
                    name: "default",
                    pattern: "{controller=Home}/{action=Index}/{id?}");
            });
        }
    }
}

================================================
FILE: reCAPTCHA.AspNetCore.Example/Views/Home/Contact.cshtml
================================================
@using reCAPTCHA.AspNetCore
@using reCAPTCHA.AspNetCore.Versions;
@using Microsoft.Extensions.Options

@model ContactModel
@inject IOptions<RecaptchaSettings> RecaptchaSettings;

@{
    ViewData["Title"] = "Contact";
}
<!--
    This is the default example for using the library.
-->
<h2>@ViewData["Title"]</h2>
<h3>@ViewData["Message"]</h3>

<address>
    One Microsoft Way<br />
    Redmond, WA 98052-6399<br />
    <abbr title="Phone">P:</abbr>
    425.555.0100
</address>

<address>
    <strong>Support:</strong> <a href="mailto:Support@example.com">Support@example.com</a><br />
    <strong>Marketing:</strong> <a href="mailto:Marketing@example.com">Marketing@example.com</a>
</address>

@using (Html.BeginForm("Contact", "Home", FormMethod.Post))
{
    @Html.ValidationSummary(true)
<fieldset>
    <div class="form-group">
        @Html.LabelFor(model => model.Message)
        <br />
        @Html.TextAreaFor(model => model.Message, new { @class = "form-control", rows = "3", style = "width: 300px;" })
    </div>
    <div class="form-group">
        @(Html.Recaptcha<RecaptchaV2Checkbox>(RecaptchaSettings.Value))
    </div>
    <button id="recaptcha" type="submit" class="btn btn-primary">Submit</button>
</fieldset>
}

================================================
FILE: reCAPTCHA.AspNetCore.Example/Views/Home/Contact2.cshtml
================================================
@using reCAPTCHA.AspNetCore
@using reCAPTCHA.AspNetCore.Versions;
@using Microsoft.Extensions.Options

@model ContactModel
@inject IOptions<RecaptchaSettings> RecaptchaSettings;

@{
    ViewData["Title"] = "Contact";
}
<!--
    This example shows how to process recpatcha manually on the backend (see Contact2 in controller)    
-->
<h2>@ViewData["Title"]</h2>
<h3>@ViewData["Message"]</h3>

<address>
    One Microsoft Way<br />
    Redmond, WA 98052-6399<br />
    <abbr title="Phone">P:</abbr>
    425.555.0100
</address>

<address>
    <strong>Support:</strong> <a href="mailto:Support@example.com">Support@example.com</a><br />
    <strong>Marketing:</strong> <a href="mailto:Marketing@example.com">Marketing@example.com</a>
</address>

@using (Html.BeginForm("Contact2", "Home", FormMethod.Post))
{
    @Html.ValidationSummary(true)
<fieldset>
    <div class="form-group">
        @Html.LabelFor(model => model.Message)
        <br />
        @Html.TextAreaFor(model => model.Message, new { @class = "form-control", rows = "3", style = "width: 300px;" })
    </div>
    <div class="form-group">
        @(Html.Recaptcha<RecaptchaV2Checkbox>(RecaptchaSettings.Value))
    </div>
    <button id="recaptcha" type="submit" class="btn btn-primary">Submit</button>
</fieldset>
}

================================================
FILE: reCAPTCHA.AspNetCore.Example/Views/Home/Contact3.cshtml
================================================
@using reCAPTCHA.AspNetCore
@using reCAPTCHA.AspNetCore.Versions;
@using Microsoft.Extensions.Options

@model ContactModel
@inject IOptions<RecaptchaSettings> RecaptchaSettings;

@{
    ViewData["Title"] = "Contact";
}
<!--
    This example shows how to use a hidden button to delay recatpcha processing in a form.
    You can modify OnPost to validate form input using whatever library you wish
-->
<h2>@ViewData["Title"]</h2>
<h3>@ViewData["Message"]</h3>

<address>
    One Microsoft Way<br />
    Redmond, WA 98052-6399<br />
    <abbr title="Phone">P:</abbr>
    425.555.0100
</address>

<address>
    <strong>Support:</strong> <a href="mailto:Support@example.com">Support@example.com</a><br />
    <strong>Marketing:</strong> <a href="mailto:Marketing@example.com">Marketing@example.com</a>
</address>

@using (Html.BeginForm("Contact", "Home", FormMethod.Post))
{
    @Html.ValidationSummary(true)
<fieldset>
    <div class="form-group">
        @Html.LabelFor(model => model.Message)
        <br />
        @Html.TextAreaFor(model => model.Message, new { @class = "form-control", rows = "3", style = "width: 300px;" })
    </div>
    <div class="form-group">
        @(Html.Recaptcha<RecaptchaV2Invisible>(RecaptchaSettings.Value))
    </div>
    <button id="submit" type="submit" class="btn btn-primary" onclick="OnPost()">Submit</button>
    <button id="recaptcha" type="button" class="btn btn-primary" style="visibility: hidden;">Recaptcha</button>
</fieldset>
}

<script>
    function OnPost() {
        alert('Using OnPost');
        document.getElementById('recaptcha').click();
    }
</script>

================================================
FILE: reCAPTCHA.AspNetCore.Example/Views/Home/Contact4.cshtml
================================================
@using reCAPTCHA.AspNetCore
@using reCAPTCHA.AspNetCore.Versions;
@using Microsoft.Extensions.Options

@model ContactModel
@inject IOptions<RecaptchaSettings> RecaptchaSettings;

@{
    ViewData["Title"] = "Contact";
}
<!--
    This is an example of using more than 1 form, with recaptcha on the page at once.
-->
<h2>@ViewData["Title"]</h2>
<h3>@ViewData["Message"]</h3>

<address>
    One Microsoft Way<br />
    Redmond, WA 98052-6399<br />
    <abbr title="Phone">P:</abbr>
    425.555.0100
</address>

<address>
    <strong>Support:</strong> <a href="mailto:Support@example.com">Support@example.com</a><br />
    <strong>Marketing:</strong> <a href="mailto:Marketing@example.com">Marketing@example.com</a>
</address>

<div>
    Form 1
    <hr />
</div>
@using (Html.BeginForm("Contact4", "Home", FormMethod.Post))
{
    @Html.ValidationSummary(true)
    <fieldset>
        <div class="form-group">
            @Html.LabelFor(model => model.Message)
            <br />
            @Html.TextAreaFor(model => model.Message, new { @class = "form-control", rows = "3", style = "width: 300px;" })
        </div>
        <div class="form-group">
            @(Html.Recaptcha<RecaptchaV3HiddenInput>(RecaptchaSettings.Value))
        </div>
        <button id="recaptcha" type="submit" class="btn btn-primary">Submit</button>
    </fieldset>
}

<div>
    Form 2
    <hr />
</div>
@using (Html.BeginForm("Contact4", "Home", FormMethod.Post))
{
    @Html.ValidationSummary(true)
    <fieldset>
        <div class="form-group">
            @Html.LabelFor(model => model.Message)
            <br />
            @Html.TextAreaFor(model => model.Message, new { @class = "form-control", rows = "3", style = "width: 300px;" })
        </div>
        <div class="form-group">
            @(Html.Recaptcha<RecaptchaV3HiddenInput>(RecaptchaSettings.Value, new RecaptchaV3HiddenInput
            {
                Id = "recaptcha2"
            }))
        </div>
        <button id="recaptcha2" type="submit" class="btn btn-primary">Submit</button>
    </fieldset>
}

================================================
FILE: reCAPTCHA.AspNetCore.Example/Views/Home/Index.cshtml
================================================
@{
    ViewData["Title"] = "Home Page";
}

<div class="text-center">
    <h1 class="display-4">Welcome</h1>
    <p>Learn about <a href="https://docs.microsoft.com/aspnet/core">building Web apps with ASP.NET Core</a>.</p>
</div>


================================================
FILE: reCAPTCHA.AspNetCore.Example/Views/Home/Privacy.cshtml
================================================
@{
    ViewData["Title"] = "Privacy Policy";
}
<h1>@ViewData["Title"]</h1>

<p>Use this page to detail your site's privacy policy.</p>


================================================
FILE: reCAPTCHA.AspNetCore.Example/Views/Shared/Error.cshtml
================================================
@model ErrorViewModel
@{
    ViewData["Title"] = "Error";
}

<h1 class="text-danger">Error.</h1>
<h2 class="text-danger">An error occurred while processing your request.</h2>

@if (Model.ShowRequestId)
{
    <p>
        <strong>Request ID:</strong> <code>@Model.RequestId</code>
    </p>
}

<h3>Development Mode</h3>
<p>
    Swapping to <strong>Development</strong> environment will display more detailed information about the error that occurred.
</p>
<p>
    <strong>The Development environment shouldn't be enabled for deployed applications.</strong>
    It can result in displaying sensitive information from exceptions to end users.
    For local debugging, enable the <strong>Development</strong> environment by setting the <strong>ASPNETCORE_ENVIRONMENT</strong> environment variable to <strong>Development</strong>
    and restarting the app.
</p>


================================================
FILE: reCAPTCHA.AspNetCore.Example/Views/Shared/_Layout.cshtml
================================================
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>@ViewData["Title"] - reCAPTCHA.AspNetCore.Example</title>
    <link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.min.css" />
    <link rel="stylesheet" href="~/css/site.css" />
</head>
<body>
    <header>
        <nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-bottom box-shadow mb-3">
            <div class="container">
                <a class="navbar-brand" asp-area="" asp-controller="Home" asp-action="Index">reCAPTCHA.AspNetCore.Example</a>
                <button class="navbar-toggler" type="button" data-toggle="collapse" data-target=".navbar-collapse" aria-controls="navbarSupportedContent"
                        aria-expanded="false" aria-label="Toggle navigation">
                    <span class="navbar-toggler-icon"></span>
                </button>
                <div class="navbar-collapse collapse d-sm-inline-flex flex-sm-row-reverse">
                    <ul class="navbar-nav flex-grow-1">
                        <li class="nav-item">
                            <a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Index">Home</a>
                        </li>
                        <li class="nav-item">
                            <a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Contact">Contact</a>
                        </li>
                        <li class="nav-item">
                            <a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Contact2">Contact 2</a>
                        </li>
                        <li class="nav-item">
                            <a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Contact3">Contact 3</a>
                        </li>
                        <li class="nav-item">
                            <a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Privacy">Privacy</a>
                        </li>
                    </ul>
                </div>
            </div>
        </nav>
    </header>
    <div class="container">
        <main role="main" class="pb-3">
            @RenderBody()
        </main>
    </div>

    <footer class="border-top footer text-muted">
        <div class="container">
            &copy; 2020 - reCAPTCHA.AspNetCore.Example - <a asp-area="" asp-controller="Home" asp-action="Privacy">Privacy</a>
        </div>
    </footer>
    <script src="~/lib/jquery/dist/jquery.min.js"></script>
    <script src="~/lib/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
    <script src="~/js/site.js" asp-append-version="true"></script>
    @RenderSection("Scripts", required: false)
</body>
</html>

================================================
FILE: reCAPTCHA.AspNetCore.Example/Views/Shared/_ValidationScriptsPartial.cshtml
================================================
<script src="~/lib/jquery-validation/dist/jquery.validate.min.js"></script>
<script src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js"></script>


================================================
FILE: reCAPTCHA.AspNetCore.Example/Views/_ViewImports.cshtml
================================================
@using reCAPTCHA.AspNetCore.Example
@using reCAPTCHA.AspNetCore.Example.Models
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers


================================================
FILE: reCAPTCHA.AspNetCore.Example/Views/_ViewStart.cshtml
================================================
@{
    Layout = "_Layout";
}


================================================
FILE: reCAPTCHA.AspNetCore.Example/appsettings.Development.json
================================================
{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  }
}


================================================
FILE: reCAPTCHA.AspNetCore.Example/appsettings.json
================================================
{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "AllowedHosts": "*",
  "RecaptchaSettings": {
    "SecretKey": "6LeIxAcTAAAAAGG-vFI1TnRWxMZNFuojJ4WifJWe",
    "SiteKey": "6LeIxAcTAAAAAJcZVRqyHh71UMIEGNQ_MXjiZKhI"
  }
}


================================================
FILE: reCAPTCHA.AspNetCore.Example/reCAPTCHA.AspNetCore.Example.csproj
================================================
<Project Sdk="Microsoft.NET.Sdk.Web">

  <PropertyGroup>
    <TargetFramework>netcoreapp3.1</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <ProjectReference Include="..\reCAPTCHA.AspNetCore\reCAPTCHA.AspNetCore.csproj" />
  </ItemGroup>
</Project>

================================================
FILE: reCAPTCHA.AspNetCore.Example/wwwroot/css/site.css
================================================
/* Please see documentation at https://docs.microsoft.com/aspnet/core/client-side/bundling-and-minification
for details on configuring this project to bundle and minify static web assets. */

a.navbar-brand {
  white-space: normal;
  text-align: center;
  word-break: break-all;
}

/* Provide sufficient contrast against white background */
a {
  color: #0366d6;
}

.btn-primary {
  color: #fff;
  background-color: #1b6ec2;
  border-color: #1861ac;
}

.nav-pills .nav-link.active, .nav-pills .show > .nav-link {
  color: #fff;
  background-color: #1b6ec2;
  border-color: #1861ac;
}

/* Sticky footer styles
-------------------------------------------------- */
html {
  font-size: 14px;
}
@media (min-width: 768px) {
  html {
    font-size: 16px;
  }
}

.border-top {
  border-top: 1px solid #e5e5e5;
}
.border-bottom {
  border-bottom: 1px solid #e5e5e5;
}

.box-shadow {
  box-shadow: 0 .25rem .75rem rgba(0, 0, 0, .05);
}

button.accept-policy {
  font-size: 1rem;
  line-height: inherit;
}

/* Sticky footer styles
-------------------------------------------------- */
html {
  position: relative;
  min-height: 100%;
}

body {
  /* Margin bottom by footer height */
  margin-bottom: 60px;
}
.footer {
  position: absolute;
  bottom: 0;
  width: 100%;
  white-space: nowrap;
  line-height: 60px; /* Vertically center the text there */
}


================================================
FILE: reCAPTCHA.AspNetCore.Example/wwwroot/js/site.js
================================================
// Please see documentation at https://docs.microsoft.com/aspnet/core/client-side/bundling-and-minification
// for details on configuring this project to bundle and minify static web assets.

// Write your JavaScript code.


================================================
FILE: reCAPTCHA.AspNetCore.Example/wwwroot/lib/bootstrap/LICENSE
================================================
The MIT License (MIT)

Copyright (c) 2011-2018 Twitter, Inc.
Copyright (c) 2011-2018 The Bootstrap Authors

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.


================================================
FILE: reCAPTCHA.AspNetCore.Example/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.css
================================================
/*!
 * Bootstrap Grid v4.3.1 (https://getbootstrap.com/)
 * Copyright 2011-2019 The Bootstrap Authors
 * Copyright 2011-2019 Twitter, Inc.
 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
 */
html {
  box-sizing: border-box;
  -ms-overflow-style: scrollbar;
}

*,
*::before,
*::after {
  box-sizing: inherit;
}

.container {
  width: 100%;
  padding-right: 15px;
  padding-left: 15px;
  margin-right: auto;
  margin-left: auto;
}

@media (min-width: 576px) {
  .container {
    max-width: 540px;
  }
}

@media (min-width: 768px) {
  .container {
    max-width: 720px;
  }
}

@media (min-width: 992px) {
  .container {
    max-width: 960px;
  }
}

@media (min-width: 1200px) {
  .container {
    max-width: 1140px;
  }
}

.container-fluid {
  width: 100%;
  padding-right: 15px;
  padding-left: 15px;
  margin-right: auto;
  margin-left: auto;
}

.row {
  display: -ms-flexbox;
  display: flex;
  -ms-flex-wrap: wrap;
  flex-wrap: wrap;
  margin-right: -15px;
  margin-left: -15px;
}

.no-gutters {
  margin-right: 0;
  margin-left: 0;
}

.no-gutters > .col,
.no-gutters > [class*="col-"] {
  padding-right: 0;
  padding-left: 0;
}

.col-1, .col-2, .col-3, .col-4, .col-5, .col-6, .col-7, .col-8, .col-9, .col-10, .col-11, .col-12, .col,
.col-auto, .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12, .col-sm,
.col-sm-auto, .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12, .col-md,
.col-md-auto, .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12, .col-lg,
.col-lg-auto, .col-xl-1, .col-xl-2, .col-xl-3, .col-xl-4, .col-xl-5, .col-xl-6, .col-xl-7, .col-xl-8, .col-xl-9, .col-xl-10, .col-xl-11, .col-xl-12, .col-xl,
.col-xl-auto {
  position: relative;
  width: 100%;
  padding-right: 15px;
  padding-left: 15px;
}

.col {
  -ms-flex-preferred-size: 0;
  flex-basis: 0;
  -ms-flex-positive: 1;
  flex-grow: 1;
  max-width: 100%;
}

.col-auto {
  -ms-flex: 0 0 auto;
  flex: 0 0 auto;
  width: auto;
  max-width: 100%;
}

.col-1 {
  -ms-flex: 0 0 8.333333%;
  flex: 0 0 8.333333%;
  max-width: 8.333333%;
}

.col-2 {
  -ms-flex: 0 0 16.666667%;
  flex: 0 0 16.666667%;
  max-width: 16.666667%;
}

.col-3 {
  -ms-flex: 0 0 25%;
  flex: 0 0 25%;
  max-width: 25%;
}

.col-4 {
  -ms-flex: 0 0 33.333333%;
  flex: 0 0 33.333333%;
  max-width: 33.333333%;
}

.col-5 {
  -ms-flex: 0 0 41.666667%;
  flex: 0 0 41.666667%;
  max-width: 41.666667%;
}

.col-6 {
  -ms-flex: 0 0 50%;
  flex: 0 0 50%;
  max-width: 50%;
}

.col-7 {
  -ms-flex: 0 0 58.333333%;
  flex: 0 0 58.333333%;
  max-width: 58.333333%;
}

.col-8 {
  -ms-flex: 0 0 66.666667%;
  flex: 0 0 66.666667%;
  max-width: 66.666667%;
}

.col-9 {
  -ms-flex: 0 0 75%;
  flex: 0 0 75%;
  max-width: 75%;
}

.col-10 {
  -ms-flex: 0 0 83.333333%;
  flex: 0 0 83.333333%;
  max-width: 83.333333%;
}

.col-11 {
  -ms-flex: 0 0 91.666667%;
  flex: 0 0 91.666667%;
  max-width: 91.666667%;
}

.col-12 {
  -ms-flex: 0 0 100%;
  flex: 0 0 100%;
  max-width: 100%;
}

.order-first {
  -ms-flex-order: -1;
  order: -1;
}

.order-last {
  -ms-flex-order: 13;
  order: 13;
}

.order-0 {
  -ms-flex-order: 0;
  order: 0;
}

.order-1 {
  -ms-flex-order: 1;
  order: 1;
}

.order-2 {
  -ms-flex-order: 2;
  order: 2;
}

.order-3 {
  -ms-flex-order: 3;
  order: 3;
}

.order-4 {
  -ms-flex-order: 4;
  order: 4;
}

.order-5 {
  -ms-flex-order: 5;
  order: 5;
}

.order-6 {
  -ms-flex-order: 6;
  order: 6;
}

.order-7 {
  -ms-flex-order: 7;
  order: 7;
}

.order-8 {
  -ms-flex-order: 8;
  order: 8;
}

.order-9 {
  -ms-flex-order: 9;
  order: 9;
}

.order-10 {
  -ms-flex-order: 10;
  order: 10;
}

.order-11 {
  -ms-flex-order: 11;
  order: 11;
}

.order-12 {
  -ms-flex-order: 12;
  order: 12;
}

.offset-1 {
  margin-left: 8.333333%;
}

.offset-2 {
  margin-left: 16.666667%;
}

.offset-3 {
  margin-left: 25%;
}

.offset-4 {
  margin-left: 33.333333%;
}

.offset-5 {
  margin-left: 41.666667%;
}

.offset-6 {
  margin-left: 50%;
}

.offset-7 {
  margin-left: 58.333333%;
}

.offset-8 {
  margin-left: 66.666667%;
}

.offset-9 {
  margin-left: 75%;
}

.offset-10 {
  margin-left: 83.333333%;
}

.offset-11 {
  margin-left: 91.666667%;
}

@media (min-width: 576px) {
  .col-sm {
    -ms-flex-preferred-size: 0;
    flex-basis: 0;
    -ms-flex-positive: 1;
    flex-grow: 1;
    max-width: 100%;
  }
  .col-sm-auto {
    -ms-flex: 0 0 auto;
    flex: 0 0 auto;
    width: auto;
    max-width: 100%;
  }
  .col-sm-1 {
    -ms-flex: 0 0 8.333333%;
    flex: 0 0 8.333333%;
    max-width: 8.333333%;
  }
  .col-sm-2 {
    -ms-flex: 0 0 16.666667%;
    flex: 0 0 16.666667%;
    max-width: 16.666667%;
  }
  .col-sm-3 {
    -ms-flex: 0 0 25%;
    flex: 0 0 25%;
    max-width: 25%;
  }
  .col-sm-4 {
    -ms-flex: 0 0 33.333333%;
    flex: 0 0 33.333333%;
    max-width: 33.333333%;
  }
  .col-sm-5 {
    -ms-flex: 0 0 41.666667%;
    flex: 0 0 41.666667%;
    max-width: 41.666667%;
  }
  .col-sm-6 {
    -ms-flex: 0 0 50%;
    flex: 0 0 50%;
    max-width: 50%;
  }
  .col-sm-7 {
    -ms-flex: 0 0 58.333333%;
    flex: 0 0 58.333333%;
    max-width: 58.333333%;
  }
  .col-sm-8 {
    -ms-flex: 0 0 66.666667%;
    flex: 0 0 66.666667%;
    max-width: 66.666667%;
  }
  .col-sm-9 {
    -ms-flex: 0 0 75%;
    flex: 0 0 75%;
    max-width: 75%;
  }
  .col-sm-10 {
    -ms-flex: 0 0 83.333333%;
    flex: 0 0 83.333333%;
    max-width: 83.333333%;
  }
  .col-sm-11 {
    -ms-flex: 0 0 91.666667%;
    flex: 0 0 91.666667%;
    max-width: 91.666667%;
  }
  .col-sm-12 {
    -ms-flex: 0 0 100%;
    flex: 0 0 100%;
    max-width: 100%;
  }
  .order-sm-first {
    -ms-flex-order: -1;
    order: -1;
  }
  .order-sm-last {
    -ms-flex-order: 13;
    order: 13;
  }
  .order-sm-0 {
    -ms-flex-order: 0;
    order: 0;
  }
  .order-sm-1 {
    -ms-flex-order: 1;
    order: 1;
  }
  .order-sm-2 {
    -ms-flex-order: 2;
    order: 2;
  }
  .order-sm-3 {
    -ms-flex-order: 3;
    order: 3;
  }
  .order-sm-4 {
    -ms-flex-order: 4;
    order: 4;
  }
  .order-sm-5 {
    -ms-flex-order: 5;
    order: 5;
  }
  .order-sm-6 {
    -ms-flex-order: 6;
    order: 6;
  }
  .order-sm-7 {
    -ms-flex-order: 7;
    order: 7;
  }
  .order-sm-8 {
    -ms-flex-order: 8;
    order: 8;
  }
  .order-sm-9 {
    -ms-flex-order: 9;
    order: 9;
  }
  .order-sm-10 {
    -ms-flex-order: 10;
    order: 10;
  }
  .order-sm-11 {
    -ms-flex-order: 11;
    order: 11;
  }
  .order-sm-12 {
    -ms-flex-order: 12;
    order: 12;
  }
  .offset-sm-0 {
    margin-left: 0;
  }
  .offset-sm-1 {
    margin-left: 8.333333%;
  }
  .offset-sm-2 {
    margin-left: 16.666667%;
  }
  .offset-sm-3 {
    margin-left: 25%;
  }
  .offset-sm-4 {
    margin-left: 33.333333%;
  }
  .offset-sm-5 {
    margin-left: 41.666667%;
  }
  .offset-sm-6 {
    margin-left: 50%;
  }
  .offset-sm-7 {
    margin-left: 58.333333%;
  }
  .offset-sm-8 {
    margin-left: 66.666667%;
  }
  .offset-sm-9 {
    margin-left: 75%;
  }
  .offset-sm-10 {
    margin-left: 83.333333%;
  }
  .offset-sm-11 {
    margin-left: 91.666667%;
  }
}

@media (min-width: 768px) {
  .col-md {
    -ms-flex-preferred-size: 0;
    flex-basis: 0;
    -ms-flex-positive: 1;
    flex-grow: 1;
    max-width: 100%;
  }
  .col-md-auto {
    -ms-flex: 0 0 auto;
    flex: 0 0 auto;
    width: auto;
    max-width: 100%;
  }
  .col-md-1 {
    -ms-flex: 0 0 8.333333%;
    flex: 0 0 8.333333%;
    max-width: 8.333333%;
  }
  .col-md-2 {
    -ms-flex: 0 0 16.666667%;
    flex: 0 0 16.666667%;
    max-width: 16.666667%;
  }
  .col-md-3 {
    -ms-flex: 0 0 25%;
    flex: 0 0 25%;
    max-width: 25%;
  }
  .col-md-4 {
    -ms-flex: 0 0 33.333333%;
    flex: 0 0 33.333333%;
    max-width: 33.333333%;
  }
  .col-md-5 {
    -ms-flex: 0 0 41.666667%;
    flex: 0 0 41.666667%;
    max-width: 41.666667%;
  }
  .col-md-6 {
    -ms-flex: 0 0 50%;
    flex: 0 0 50%;
    max-width: 50%;
  }
  .col-md-7 {
    -ms-flex: 0 0 58.333333%;
    flex: 0 0 58.333333%;
    max-width: 58.333333%;
  }
  .col-md-8 {
    -ms-flex: 0 0 66.666667%;
    flex: 0 0 66.666667%;
    max-width: 66.666667%;
  }
  .col-md-9 {
    -ms-flex: 0 0 75%;
    flex: 0 0 75%;
    max-width: 75%;
  }
  .col-md-10 {
    -ms-flex: 0 0 83.333333%;
    flex: 0 0 83.333333%;
    max-width: 83.333333%;
  }
  .col-md-11 {
    -ms-flex: 0 0 91.666667%;
    flex: 0 0 91.666667%;
    max-width: 91.666667%;
  }
  .col-md-12 {
    -ms-flex: 0 0 100%;
    flex: 0 0 100%;
    max-width: 100%;
  }
  .order-md-first {
    -ms-flex-order: -1;
    order: -1;
  }
  .order-md-last {
    -ms-flex-order: 13;
    order: 13;
  }
  .order-md-0 {
    -ms-flex-order: 0;
    order: 0;
  }
  .order-md-1 {
    -ms-flex-order: 1;
    order: 1;
  }
  .order-md-2 {
    -ms-flex-order: 2;
    order: 2;
  }
  .order-md-3 {
    -ms-flex-order: 3;
    order: 3;
  }
  .order-md-4 {
    -ms-flex-order: 4;
    order: 4;
  }
  .order-md-5 {
    -ms-flex-order: 5;
    order: 5;
  }
  .order-md-6 {
    -ms-flex-order: 6;
    order: 6;
  }
  .order-md-7 {
    -ms-flex-order: 7;
    order: 7;
  }
  .order-md-8 {
    -ms-flex-order: 8;
    order: 8;
  }
  .order-md-9 {
    -ms-flex-order: 9;
    order: 9;
  }
  .order-md-10 {
    -ms-flex-order: 10;
    order: 10;
  }
  .order-md-11 {
    -ms-flex-order: 11;
    order: 11;
  }
  .order-md-12 {
    -ms-flex-order: 12;
    order: 12;
  }
  .offset-md-0 {
    margin-left: 0;
  }
  .offset-md-1 {
    margin-left: 8.333333%;
  }
  .offset-md-2 {
    margin-left: 16.666667%;
  }
  .offset-md-3 {
    margin-left: 25%;
  }
  .offset-md-4 {
    margin-left: 33.333333%;
  }
  .offset-md-5 {
    margin-left: 41.666667%;
  }
  .offset-md-6 {
    margin-left: 50%;
  }
  .offset-md-7 {
    margin-left: 58.333333%;
  }
  .offset-md-8 {
    margin-left: 66.666667%;
  }
  .offset-md-9 {
    margin-left: 75%;
  }
  .offset-md-10 {
    margin-left: 83.333333%;
  }
  .offset-md-11 {
    margin-left: 91.666667%;
  }
}

@media (min-width: 992px) {
  .col-lg {
    -ms-flex-preferred-size: 0;
    flex-basis: 0;
    -ms-flex-positive: 1;
    flex-grow: 1;
    max-width: 100%;
  }
  .col-lg-auto {
    -ms-flex: 0 0 auto;
    flex: 0 0 auto;
    width: auto;
    max-width: 100%;
  }
  .col-lg-1 {
    -ms-flex: 0 0 8.333333%;
    flex: 0 0 8.333333%;
    max-width: 8.333333%;
  }
  .col-lg-2 {
    -ms-flex: 0 0 16.666667%;
    flex: 0 0 16.666667%;
    max-width: 16.666667%;
  }
  .col-lg-3 {
    -ms-flex: 0 0 25%;
    flex: 0 0 25%;
    max-width: 25%;
  }
  .col-lg-4 {
    -ms-flex: 0 0 33.333333%;
    flex: 0 0 33.333333%;
    max-width: 33.333333%;
  }
  .col-lg-5 {
    -ms-flex: 0 0 41.666667%;
    flex: 0 0 41.666667%;
    max-width: 41.666667%;
  }
  .col-lg-6 {
    -ms-flex: 0 0 50%;
    flex: 0 0 50%;
    max-width: 50%;
  }
  .col-lg-7 {
    -ms-flex: 0 0 58.333333%;
    flex: 0 0 58.333333%;
    max-width: 58.333333%;
  }
  .col-lg-8 {
    -ms-flex: 0 0 66.666667%;
    flex: 0 0 66.666667%;
    max-width: 66.666667%;
  }
  .col-lg-9 {
    -ms-flex: 0 0 75%;
    flex: 0 0 75%;
    max-width: 75%;
  }
  .col-lg-10 {
    -ms-flex: 0 0 83.333333%;
    flex: 0 0 83.333333%;
    max-width: 83.333333%;
  }
  .col-lg-11 {
    -ms-flex: 0 0 91.666667%;
    flex: 0 0 91.666667%;
    max-width: 91.666667%;
  }
  .col-lg-12 {
    -ms-flex: 0 0 100%;
    flex: 0 0 100%;
    max-width: 100%;
  }
  .order-lg-first {
    -ms-flex-order: -1;
    order: -1;
  }
  .order-lg-last {
    -ms-flex-order: 13;
    order: 13;
  }
  .order-lg-0 {
    -ms-flex-order: 0;
    order: 0;
  }
  .order-lg-1 {
    -ms-flex-order: 1;
    order: 1;
  }
  .order-lg-2 {
    -ms-flex-order: 2;
    order: 2;
  }
  .order-lg-3 {
    -ms-flex-order: 3;
    order: 3;
  }
  .order-lg-4 {
    -ms-flex-order: 4;
    order: 4;
  }
  .order-lg-5 {
    -ms-flex-order: 5;
    order: 5;
  }
  .order-lg-6 {
    -ms-flex-order: 6;
    order: 6;
  }
  .order-lg-7 {
    -ms-flex-order: 7;
    order: 7;
  }
  .order-lg-8 {
    -ms-flex-order: 8;
    order: 8;
  }
  .order-lg-9 {
    -ms-flex-order: 9;
    order: 9;
  }
  .order-lg-10 {
    -ms-flex-order: 10;
    order: 10;
  }
  .order-lg-11 {
    -ms-flex-order: 11;
    order: 11;
  }
  .order-lg-12 {
    -ms-flex-order: 12;
    order: 12;
  }
  .offset-lg-0 {
    margin-left: 0;
  }
  .offset-lg-1 {
    margin-left: 8.333333%;
  }
  .offset-lg-2 {
    margin-left: 16.666667%;
  }
  .offset-lg-3 {
    margin-left: 25%;
  }
  .offset-lg-4 {
    margin-left: 33.333333%;
  }
  .offset-lg-5 {
    margin-left: 41.666667%;
  }
  .offset-lg-6 {
    margin-left: 50%;
  }
  .offset-lg-7 {
    margin-left: 58.333333%;
  }
  .offset-lg-8 {
    margin-left: 66.666667%;
  }
  .offset-lg-9 {
    margin-left: 75%;
  }
  .offset-lg-10 {
    margin-left: 83.333333%;
  }
  .offset-lg-11 {
    margin-left: 91.666667%;
  }
}

@media (min-width: 1200px) {
  .col-xl {
    -ms-flex-preferred-size: 0;
    flex-basis: 0;
    -ms-flex-positive: 1;
    flex-grow: 1;
    max-width: 100%;
  }
  .col-xl-auto {
    -ms-flex: 0 0 auto;
    flex: 0 0 auto;
    width: auto;
    max-width: 100%;
  }
  .col-xl-1 {
    -ms-flex: 0 0 8.333333%;
    flex: 0 0 8.333333%;
    max-width: 8.333333%;
  }
  .col-xl-2 {
    -ms-flex: 0 0 16.666667%;
    flex: 0 0 16.666667%;
    max-width: 16.666667%;
  }
  .col-xl-3 {
    -ms-flex: 0 0 25%;
    flex: 0 0 25%;
    max-width: 25%;
  }
  .col-xl-4 {
    -ms-flex: 0 0 33.333333%;
    flex: 0 0 33.333333%;
    max-width: 33.333333%;
  }
  .col-xl-5 {
    -ms-flex: 0 0 41.666667%;
    flex: 0 0 41.666667%;
    max-width: 41.666667%;
  }
  .col-xl-6 {
    -ms-flex: 0 0 50%;
    flex: 0 0 50%;
    max-width: 50%;
  }
  .col-xl-7 {
    -ms-flex: 0 0 58.333333%;
    flex: 0 0 58.333333%;
    max-width: 58.333333%;
  }
  .col-xl-8 {
    -ms-flex: 0 0 66.666667%;
    flex: 0 0 66.666667%;
    max-width: 66.666667%;
  }
  .col-xl-9 {
    -ms-flex: 0 0 75%;
    flex: 0 0 75%;
    max-width: 75%;
  }
  .col-xl-10 {
    -ms-flex: 0 0 83.333333%;
    flex: 0 0 83.333333%;
    max-width: 83.333333%;
  }
  .col-xl-11 {
    -ms-flex: 0 0 91.666667%;
    flex: 0 0 91.666667%;
    max-width: 91.666667%;
  }
  .col-xl-12 {
    -ms-flex: 0 0 100%;
    flex: 0 0 100%;
    max-width: 100%;
  }
  .order-xl-first {
    -ms-flex-order: -1;
    order: -1;
  }
  .order-xl-last {
    -ms-flex-order: 13;
    order: 13;
  }
  .order-xl-0 {
    -ms-flex-order: 0;
    order: 0;
  }
  .order-xl-1 {
    -ms-flex-order: 1;
    order: 1;
  }
  .order-xl-2 {
    -ms-flex-order: 2;
    order: 2;
  }
  .order-xl-3 {
    -ms-flex-order: 3;
    order: 3;
  }
  .order-xl-4 {
    -ms-flex-order: 4;
    order: 4;
  }
  .order-xl-5 {
    -ms-flex-order: 5;
    order: 5;
  }
  .order-xl-6 {
    -ms-flex-order: 6;
    order: 6;
  }
  .order-xl-7 {
    -ms-flex-order: 7;
    order: 7;
  }
  .order-xl-8 {
    -ms-flex-order: 8;
    order: 8;
  }
  .order-xl-9 {
    -ms-flex-order: 9;
    order: 9;
  }
  .order-xl-10 {
    -ms-flex-order: 10;
    order: 10;
  }
  .order-xl-11 {
    -ms-flex-order: 11;
    order: 11;
  }
  .order-xl-12 {
    -ms-flex-order: 12;
    order: 12;
  }
  .offset-xl-0 {
    margin-left: 0;
  }
  .offset-xl-1 {
    margin-left: 8.333333%;
  }
  .offset-xl-2 {
    margin-left: 16.666667%;
  }
  .offset-xl-3 {
    margin-left: 25%;
  }
  .offset-xl-4 {
    margin-left: 33.333333%;
  }
  .offset-xl-5 {
    margin-left: 41.666667%;
  }
  .offset-xl-6 {
    margin-left: 50%;
  }
  .offset-xl-7 {
    margin-left: 58.333333%;
  }
  .offset-xl-8 {
    margin-left: 66.666667%;
  }
  .offset-xl-9 {
    margin-left: 75%;
  }
  .offset-xl-10 {
    margin-left: 83.333333%;
  }
  .offset-xl-11 {
    margin-left: 91.666667%;
  }
}

.d-none {
  display: none !important;
}

.d-inline {
  display: inline !important;
}

.d-inline-block {
  display: inline-block !important;
}

.d-block {
  display: block !important;
}

.d-table {
  display: table !important;
}

.d-table-row {
  display: table-row !important;
}

.d-table-cell {
  display: table-cell !important;
}

.d-flex {
  display: -ms-flexbox !important;
  display: flex !important;
}

.d-inline-flex {
  display: -ms-inline-flexbox !important;
  display: inline-flex !important;
}

@media (min-width: 576px) {
  .d-sm-none {
    display: none !important;
  }
  .d-sm-inline {
    display: inline !important;
  }
  .d-sm-inline-block {
    display: inline-block !important;
  }
  .d-sm-block {
    display: block !important;
  }
  .d-sm-table {
    display: table !important;
  }
  .d-sm-table-row {
    display: table-row !important;
  }
  .d-sm-table-cell {
    display: table-cell !important;
  }
  .d-sm-flex {
    display: -ms-flexbox !important;
    display: flex !important;
  }
  .d-sm-inline-flex {
    display: -ms-inline-flexbox !important;
    display: inline-flex !important;
  }
}

@media (min-width: 768px) {
  .d-md-none {
    display: none !important;
  }
  .d-md-inline {
    display: inline !important;
  }
  .d-md-inline-block {
    display: inline-block !important;
  }
  .d-md-block {
    display: block !important;
  }
  .d-md-table {
    display: table !important;
  }
  .d-md-table-row {
    display: table-row !important;
  }
  .d-md-table-cell {
    display: table-cell !important;
  }
  .d-md-flex {
    display: -ms-flexbox !important;
    display: flex !important;
  }
  .d-md-inline-flex {
    display: -ms-inline-flexbox !important;
    display: inline-flex !important;
  }
}

@media (min-width: 992px) {
  .d-lg-none {
    display: none !important;
  }
  .d-lg-inline {
    display: inline !important;
  }
  .d-lg-inline-block {
    display: inline-block !important;
  }
  .d-lg-block {
    display: block !important;
  }
  .d-lg-table {
    display: table !important;
  }
  .d-lg-table-row {
    display: table-row !important;
  }
  .d-lg-table-cell {
    display: table-cell !important;
  }
  .d-lg-flex {
    display: -ms-flexbox !important;
    display: flex !important;
  }
  .d-lg-inline-flex {
    display: -ms-inline-flexbox !important;
    display: inline-flex !important;
  }
}

@media (min-width: 1200px) {
  .d-xl-none {
    display: none !important;
  }
  .d-xl-inline {
    display: inline !important;
  }
  .d-xl-inline-block {
    display: inline-block !important;
  }
  .d-xl-block {
    display: block !important;
  }
  .d-xl-table {
    display: table !important;
  }
  .d-xl-table-row {
    display: table-row !important;
  }
  .d-xl-table-cell {
    display: table-cell !important;
  }
  .d-xl-flex {
    display: -ms-flexbox !important;
    display: flex !important;
  }
  .d-xl-inline-flex {
    display: -ms-inline-flexbox !important;
    display: inline-flex !important;
  }
}

@media print {
  .d-print-none {
    display: none !important;
  }
  .d-print-inline {
    display: inline !important;
  }
  .d-print-inline-block {
    display: inline-block !important;
  }
  .d-print-block {
    display: block !important;
  }
  .d-print-table {
    display: table !important;
  }
  .d-print-table-row {
    display: table-row !important;
  }
  .d-print-table-cell {
    display: table-cell !important;
  }
  .d-print-flex {
    display: -ms-flexbox !important;
    display: flex !important;
  }
  .d-print-inline-flex {
    display: -ms-inline-flexbox !important;
    display: inline-flex !important;
  }
}

.flex-row {
  -ms-flex-direction: row !important;
  flex-direction: row !important;
}

.flex-column {
  -ms-flex-direction: column !important;
  flex-direction: column !important;
}

.flex-row-reverse {
  -ms-flex-direction: row-reverse !important;
  flex-direction: row-reverse !important;
}

.flex-column-reverse {
  -ms-flex-direction: column-reverse !important;
  flex-direction: column-reverse !important;
}

.flex-wrap {
  -ms-flex-wrap: wrap !important;
  flex-wrap: wrap !important;
}

.flex-nowrap {
  -ms-flex-wrap: nowrap !important;
  flex-wrap: nowrap !important;
}

.flex-wrap-reverse {
  -ms-flex-wrap: wrap-reverse !important;
  flex-wrap: wrap-reverse !important;
}

.flex-fill {
  -ms-flex: 1 1 auto !important;
  flex: 1 1 auto !important;
}

.flex-grow-0 {
  -ms-flex-positive: 0 !important;
  flex-grow: 0 !important;
}

.flex-grow-1 {
  -ms-flex-positive: 1 !important;
  flex-grow: 1 !important;
}

.flex-shrink-0 {
  -ms-flex-negative: 0 !important;
  flex-shrink: 0 !important;
}

.flex-shrink-1 {
  -ms-flex-negative: 1 !important;
  flex-shrink: 1 !important;
}

.justify-content-start {
  -ms-flex-pack: start !important;
  justify-content: flex-start !important;
}

.justify-content-end {
  -ms-flex-pack: end !important;
  justify-content: flex-end !important;
}

.justify-content-center {
  -ms-flex-pack: center !important;
  justify-content: center !important;
}

.justify-content-between {
  -ms-flex-pack: justify !important;
  justify-content: space-between !important;
}

.justify-content-around {
  -ms-flex-pack: distribute !important;
  justify-content: space-around !important;
}

.align-items-start {
  -ms-flex-align: start !important;
  align-items: flex-start !important;
}

.align-items-end {
  -ms-flex-align: end !important;
  align-items: flex-end !important;
}

.align-items-center {
  -ms-flex-align: center !important;
  align-items: center !important;
}

.align-items-baseline {
  -ms-flex-align: baseline !important;
  align-items: baseline !important;
}

.align-items-stretch {
  -ms-flex-align: stretch !important;
  align-items: stretch !important;
}

.align-content-start {
  -ms-flex-line-pack: start !important;
  align-content: flex-start !important;
}

.align-content-end {
  -ms-flex-line-pack: end !important;
  align-content: flex-end !important;
}

.align-content-center {
  -ms-flex-line-pack: center !important;
  align-content: center !important;
}

.align-content-between {
  -ms-flex-line-pack: justify !important;
  align-content: space-between !important;
}

.align-content-around {
  -ms-flex-line-pack: distribute !important;
  align-content: space-around !important;
}

.align-content-stretch {
  -ms-flex-line-pack: stretch !important;
  align-content: stretch !important;
}

.align-self-auto {
  -ms-flex-item-align: auto !important;
  align-self: auto !important;
}

.align-self-start {
  -ms-flex-item-align: start !important;
  align-self: flex-start !important;
}

.align-self-end {
  -ms-flex-item-align: end !important;
  align-self: flex-end !important;
}

.align-self-center {
  -ms-flex-item-align: center !important;
  align-self: center !important;
}

.align-self-baseline {
  -ms-flex-item-align: baseline !important;
  align-self: baseline !important;
}

.align-self-stretch {
  -ms-flex-item-align: stretch !important;
  align-self: stretch !important;
}

@media (min-width: 576px) {
  .flex-sm-row {
    -ms-flex-direction: row !important;
    flex-direction: row !important;
  }
  .flex-sm-column {
    -ms-flex-direction: column !important;
    flex-direction: column !important;
  }
  .flex-sm-row-reverse {
    -ms-flex-direction: row-reverse !important;
    flex-direction: row-reverse !important;
  }
  .flex-sm-column-reverse {
    -ms-flex-direction: column-reverse !important;
    flex-direction: column-reverse !important;
  }
  .flex-sm-wrap {
    -ms-flex-wrap: wrap !important;
    flex-wrap: wrap !important;
  }
  .flex-sm-nowrap {
    -ms-flex-wrap: nowrap !important;
    flex-wrap: nowrap !important;
  }
  .flex-sm-wrap-reverse {
    -ms-flex-wrap: wrap-reverse !important;
    flex-wrap: wrap-reverse !important;
  }
  .flex-sm-fill {
    -ms-flex: 1 1 auto !important;
    flex: 1 1 auto !important;
  }
  .flex-sm-grow-0 {
    -ms-flex-positive: 0 !important;
    flex-grow: 0 !important;
  }
  .flex-sm-grow-1 {
    -ms-flex-positive: 1 !important;
    flex-grow: 1 !important;
  }
  .flex-sm-shrink-0 {
    -ms-flex-negative: 0 !important;
    flex-shrink: 0 !important;
  }
  .flex-sm-shrink-1 {
    -ms-flex-negative: 1 !important;
    flex-shrink: 1 !important;
  }
  .justify-content-sm-start {
    -ms-flex-pack: start !important;
    justify-content: flex-start !important;
  }
  .justify-content-sm-end {
    -ms-flex-pack: end !important;
    justify-content: flex-end !important;
  }
  .justify-content-sm-center {
    -ms-flex-pack: center !important;
    justify-content: center !important;
  }
  .justify-content-sm-between {
    -ms-flex-pack: justify !important;
    justify-content: space-between !important;
  }
  .justify-content-sm-around {
    -ms-flex-pack: distribute !important;
    justify-content: space-around !important;
  }
  .align-items-sm-start {
    -ms-flex-align: start !important;
    align-items: flex-start !important;
  }
  .align-items-sm-end {
    -ms-flex-align: end !important;
    align-items: flex-end !important;
  }
  .align-items-sm-center {
    -ms-flex-align: center !important;
    align-items: center !important;
  }
  .align-items-sm-baseline {
    -ms-flex-align: baseline !important;
    align-items: baseline !important;
  }
  .align-items-sm-stretch {
    -ms-flex-align: stretch !important;
    align-items: stretch !important;
  }
  .align-content-sm-start {
    -ms-flex-line-pack: start !important;
    align-content: flex-start !important;
  }
  .align-content-sm-end {
    -ms-flex-line-pack: end !important;
    align-content: flex-end !important;
  }
  .align-content-sm-center {
    -ms-flex-line-pack: center !important;
    align-content: center !important;
  }
  .align-content-sm-between {
    -ms-flex-line-pack: justify !important;
    align-content: space-between !important;
  }
  .align-content-sm-around {
    -ms-flex-line-pack: distribute !important;
    align-content: space-around !important;
  }
  .align-content-sm-stretch {
    -ms-flex-line-pack: stretch !important;
    align-content: stretch !important;
  }
  .align-self-sm-auto {
    -ms-flex-item-align: auto !important;
    align-self: auto !important;
  }
  .align-self-sm-start {
    -ms-flex-item-align: start !important;
    align-self: flex-start !important;
  }
  .align-self-sm-end {
    -ms-flex-item-align: end !important;
    align-self: flex-end !important;
  }
  .align-self-sm-center {
    -ms-flex-item-align: center !important;
    align-self: center !important;
  }
  .align-self-sm-baseline {
    -ms-flex-item-align: baseline !important;
    align-self: baseline !important;
  }
  .align-self-sm-stretch {
    -ms-flex-item-align: stretch !important;
    align-self: stretch !important;
  }
}

@media (min-width: 768px) {
  .flex-md-row {
    -ms-flex-direction: row !important;
    flex-direction: row !important;
  }
  .flex-md-column {
    -ms-flex-direction: column !important;
    flex-direction: column !important;
  }
  .flex-md-row-reverse {
    -ms-flex-direction: row-reverse !important;
    flex-direction: row-reverse !important;
  }
  .flex-md-column-reverse {
    -ms-flex-direction: column-reverse !important;
    flex-direction: column-reverse !important;
  }
  .flex-md-wrap {
    -ms-flex-wrap: wrap !important;
    flex-wrap: wrap !important;
  }
  .flex-md-nowrap {
    -ms-flex-wrap: nowrap !important;
    flex-wrap: nowrap !important;
  }
  .flex-md-wrap-reverse {
    -ms-flex-wrap: wrap-reverse !important;
    flex-wrap: wrap-reverse !important;
  }
  .flex-md-fill {
    -ms-flex: 1 1 auto !important;
    flex: 1 1 auto !important;
  }
  .flex-md-grow-0 {
    -ms-flex-positive: 0 !important;
    flex-grow: 0 !important;
  }
  .flex-md-grow-1 {
    -ms-flex-positive: 1 !important;
    flex-grow: 1 !important;
  }
  .flex-md-shrink-0 {
    -ms-flex-negative: 0 !important;
    flex-shrink: 0 !important;
  }
  .flex-md-shrink-1 {
    -ms-flex-negative: 1 !important;
    flex-shrink: 1 !important;
  }
  .justify-content-md-start {
    -ms-flex-pack: start !important;
    justify-content: flex-start !important;
  }
  .justify-content-md-end {
    -ms-flex-pack: end !important;
    justify-content: flex-end !important;
  }
  .justify-content-md-center {
    -ms-flex-pack: center !important;
    justify-content: center !important;
  }
  .justify-content-md-between {
    -ms-flex-pack: justify !important;
    justify-content: space-between !important;
  }
  .justify-content-md-around {
    -ms-flex-pack: distribute !important;
    justify-content: space-around !important;
  }
  .align-items-md-start {
    -ms-flex-align: start !important;
    align-items: flex-start !important;
  }
  .align-items-md-end {
    -ms-flex-align: end !important;
    align-items: flex-end !important;
  }
  .align-items-md-center {
    -ms-flex-align: center !important;
    align-items: center !important;
  }
  .align-items-md-baseline {
    -ms-flex-align: baseline !important;
    align-items: baseline !important;
  }
  .align-items-md-stretch {
    -ms-flex-align: stretch !important;
    align-items: stretch !important;
  }
  .align-content-md-start {
    -ms-flex-line-pack: start !important;
    align-content: flex-start !important;
  }
  .align-content-md-end {
    -ms-flex-line-pack: end !important;
    align-content: flex-end !important;
  }
  .align-content-md-center {
    -ms-flex-line-pack: center !important;
    align-content: center !important;
  }
  .align-content-md-between {
    -ms-flex-line-pack: justify !important;
    align-content: space-between !important;
  }
  .align-content-md-around {
    -ms-flex-line-pack: distribute !important;
    align-content: space-around !important;
  }
  .align-content-md-stretch {
    -ms-flex-line-pack: stretch !important;
    align-content: stretch !important;
  }
  .align-self-md-auto {
    -ms-flex-item-align: auto !important;
    align-self: auto !important;
  }
  .align-self-md-start {
    -ms-flex-item-align: start !important;
    align-self: flex-start !important;
  }
  .align-self-md-end {
    -ms-flex-item-align: end !important;
    align-self: flex-end !important;
  }
  .align-self-md-center {
    -ms-flex-item-align: center !important;
    align-self: center !important;
  }
  .align-self-md-baseline {
    -ms-flex-item-align: baseline !important;
    align-self: baseline !important;
  }
  .align-self-md-stretch {
    -ms-flex-item-align: stretch !important;
    align-self: stretch !important;
  }
}

@media (min-width: 992px) {
  .flex-lg-row {
    -ms-flex-direction: row !important;
    flex-direction: row !important;
  }
  .flex-lg-column {
    -ms-flex-direction: column !important;
    flex-direction: column !important;
  }
  .flex-lg-row-reverse {
    -ms-flex-direction: row-reverse !important;
    flex-direction: row-reverse !important;
  }
  .flex-lg-column-reverse {
    -ms-flex-direction: column-reverse !important;
    flex-direction: column-reverse !important;
  }
  .flex-lg-wrap {
    -ms-flex-wrap: wrap !important;
    flex-wrap: wrap !important;
  }
  .flex-lg-nowrap {
    -ms-flex-wrap: nowrap !important;
    flex-wrap: nowrap !important;
  }
  .flex-lg-wrap-reverse {
    -ms-flex-wrap: wrap-reverse !important;
    flex-wrap: wrap-reverse !important;
  }
  .flex-lg-fill {
    -ms-flex: 1 1 auto !important;
    flex: 1 1 auto !important;
  }
  .flex-lg-grow-0 {
    -ms-flex-positive: 0 !important;
    flex-grow: 0 !important;
  }
  .flex-lg-grow-1 {
    -ms-flex-positive: 1 !important;
    flex-grow: 1 !important;
  }
  .flex-lg-shrink-0 {
    -ms-flex-negative: 0 !important;
    flex-shrink: 0 !important;
  }
  .flex-lg-shrink-1 {
    -ms-flex-negative: 1 !important;
    flex-shrink: 1 !important;
  }
  .justify-content-lg-start {
    -ms-flex-pack: start !important;
    justify-content: flex-start !important;
  }
  .justify-content-lg-end {
    -ms-flex-pack: end !important;
    justify-content: flex-end !important;
  }
  .justify-content-lg-center {
    -ms-flex-pack: center !important;
    justify-content: center !important;
  }
  .justify-content-lg-between {
    -ms-flex-pack: justify !important;
    justify-content: space-between !important;
  }
  .justify-content-lg-around {
    -ms-flex-pack: distribute !important;
    justify-content: space-around !important;
  }
  .align-items-lg-start {
    -ms-flex-align: start !important;
    align-items: flex-start !important;
  }
  .align-items-lg-end {
    -ms-flex-align: end !important;
    align-items: flex-end !important;
  }
  .align-items-lg-center {
    -ms-flex-align: center !important;
    align-items: center !important;
  }
  .align-items-lg-baseline {
    -ms-flex-align: baseline !important;
    align-items: baseline !important;
  }
  .align-items-lg-stretch {
    -ms-flex-align: stretch !important;
    align-items: stretch !important;
  }
  .align-content-lg-start {
    -ms-flex-line-pack: start !important;
    align-content: flex-start !important;
  }
  .align-content-lg-end {
    -ms-flex-line-pack: end !important;
    align-content: flex-end !important;
  }
  .align-content-lg-center {
    -ms-flex-line-pack: center !important;
    align-content: center !important;
  }
  .align-content-lg-between {
    -ms-flex-line-pack: justify !important;
    align-content: space-between !important;
  }
  .align-content-lg-around {
    -ms-flex-line-pack: distribute !important;
    align-content: space-around !important;
  }
  .align-content-lg-stretch {
    -ms-flex-line-pack: stretch !important;
    align-content: stretch !important;
  }
  .align-self-lg-auto {
    -ms-flex-item-align: auto !important;
    align-self: auto !important;
  }
  .align-self-lg-start {
    -ms-flex-item-align: start !important;
    align-self: flex-start !important;
  }
  .align-self-lg-end {
    -ms-flex-item-align: end !important;
    align-self: flex-end !important;
  }
  .align-self-lg-center {
    -ms-flex-item-align: center !important;
    align-self: center !important;
  }
  .align-self-lg-baseline {
    -ms-flex-item-align: baseline !important;
    align-self: baseline !important;
  }
  .align-self-lg-stretch {
    -ms-flex-item-align: stretch !important;
    align-self: stretch !important;
  }
}

@media (min-width: 1200px) {
  .flex-xl-row {
    -ms-flex-direction: row !important;
    flex-direction: row !important;
  }
  .flex-xl-column {
    -ms-flex-direction: column !important;
    flex-direction: column !important;
  }
  .flex-xl-row-reverse {
    -ms-flex-direction: row-reverse !important;
    flex-direction: row-reverse !important;
  }
  .flex-xl-column-reverse {
    -ms-flex-direction: column-reverse !important;
    flex-direction: column-reverse !important;
  }
  .flex-xl-wrap {
    -ms-flex-wrap: wrap !important;
    flex-wrap: wrap !important;
  }
  .flex-xl-nowrap {
    -ms-flex-wrap: nowrap !important;
    flex-wrap: nowrap !important;
  }
  .flex-xl-wrap-reverse {
    -ms-flex-wrap: wrap-reverse !important;
    flex-wrap: wrap-reverse !important;
  }
  .flex-xl-fill {
    -ms-flex: 1 1 auto !important;
    flex: 1 1 auto !important;
  }
  .flex-xl-grow-0 {
    -ms-flex-positive: 0 !important;
    flex-grow: 0 !important;
  }
  .flex-xl-grow-1 {
    -ms-flex-positive: 1 !important;
    flex-grow: 1 !important;
  }
  .flex-xl-shrink-0 {
    -ms-flex-negative: 0 !important;
    flex-shrink: 0 !important;
  }
  .flex-xl-shrink-1 {
    -ms-flex-negative: 1 !important;
    flex-shrink: 1 !important;
  }
  .justify-content-xl-start {
    -ms-flex-pack: start !important;
    justify-content: flex-start !important;
  }
  .justify-content-xl-end {
    -ms-flex-pack: end !important;
    justify-content: flex-end !important;
  }
  .justify-content-xl-center {
    -ms-flex-pack: center !important;
    justify-content: center !important;
  }
  .justify-content-xl-between {
    -ms-flex-pack: justify !important;
    justify-content: space-between !important;
  }
  .justify-content-xl-around {
    -ms-flex-pack: distribute !important;
    justify-content: space-around !important;
  }
  .align-items-xl-start {
    -ms-flex-align: start !important;
    align-items: flex-start !important;
  }
  .align-items-xl-end {
    -ms-flex-align: end !important;
    align-items: flex-end !important;
  }
  .align-items-xl-center {
    -ms-flex-align: center !important;
    align-items: center !important;
  }
  .align-items-xl-baseline {
    -ms-flex-align: baseline !important;
    align-items: baseline !important;
  }
  .align-items-xl-stretch {
    -ms-flex-align: stretch !important;
    align-items: stretch !important;
  }
  .align-content-xl-start {
    -ms-flex-line-pack: start !important;
    align-content: flex-start !important;
  }
  .align-content-xl-end {
    -ms-flex-line-pack: end !important;
    align-content: flex-end !important;
  }
  .align-content-xl-center {
    -ms-flex-line-pack: center !important;
    align-content: center !important;
  }
  .align-content-xl-between {
    -ms-flex-line-pack: justify !important;
    align-content: space-between !important;
  }
  .align-content-xl-around {
    -ms-flex-line-pack: distribute !important;
    align-content: space-around !important;
  }
  .align-content-xl-stretch {
    -ms-flex-line-pack: stretch !important;
    align-content: stretch !important;
  }
  .align-self-xl-auto {
    -ms-flex-item-align: auto !important;
    align-self: auto !important;
  }
  .align-self-xl-start {
    -ms-flex-item-align: start !important;
    align-self: flex-start !important;
  }
  .align-self-xl-end {
    -ms-flex-item-align: end !important;
    align-self: flex-end !important;
  }
  .align-self-xl-center {
    -ms-flex-item-align: center !important;
    align-self: center !important;
  }
  .align-self-xl-baseline {
    -ms-flex-item-align: baseline !important;
    align-self: baseline !important;
  }
  .align-self-xl-stretch {
    -ms-flex-item-align: stretch !important;
    align-self: stretch !important;
  }
}

.m-0 {
  margin: 0 !important;
}

.mt-0,
.my-0 {
  margin-top: 0 !important;
}

.mr-0,
.mx-0 {
  margin-right: 0 !important;
}

.mb-0,
.my-0 {
  margin-bottom: 0 !important;
}

.ml-0,
.mx-0 {
  margin-left: 0 !important;
}

.m-1 {
  margin: 0.25rem !important;
}

.mt-1,
.my-1 {
  margin-top: 0.25rem !important;
}

.mr-1,
.mx-1 {
  margin-right: 0.25rem !important;
}

.mb-1,
.my-1 {
  margin-bottom: 0.25rem !important;
}

.ml-1,
.mx-1 {
  margin-left: 0.25rem !important;
}

.m-2 {
  margin: 0.5rem !important;
}

.mt-2,
.my-2 {
  margin-top: 0.5rem !important;
}

.mr-2,
.mx-2 {
  margin-right: 0.5rem !important;
}

.mb-2,
.my-2 {
  margin-bottom: 0.5rem !important;
}

.ml-2,
.mx-2 {
  margin-left: 0.5rem !important;
}

.m-3 {
  margin: 1rem !important;
}

.mt-3,
.my-3 {
  margin-top: 1rem !important;
}

.mr-3,
.mx-3 {
  margin-right: 1rem !important;
}

.mb-3,
.my-3 {
  margin-bottom: 1rem !important;
}

.ml-3,
.mx-3 {
  margin-left: 1rem !important;
}

.m-4 {
  margin: 1.5rem !important;
}

.mt-4,
.my-4 {
  margin-top: 1.5rem !important;
}

.mr-4,
.mx-4 {
  margin-right: 1.5rem !important;
}

.mb-4,
.my-4 {
  margin-bottom: 1.5rem !important;
}

.ml-4,
.mx-4 {
  margin-left: 1.5rem !important;
}

.m-5 {
  margin: 3rem !important;
}

.mt-5,
.my-5 {
  margin-top: 3rem !important;
}

.mr-5,
.mx-5 {
  margin-right: 3rem !important;
}

.mb-5,
.my-5 {
  margin-bottom: 3rem !important;
}

.ml-5,
.mx-5 {
  margin-left: 3rem !important;
}

.p-0 {
  padding: 0 !important;
}

.pt-0,
.py-0 {
  padding-top: 0 !important;
}

.pr-0,
.px-0 {
  padding-right: 0 !important;
}

.pb-0,
.py-0 {
  padding-bottom: 0 !important;
}

.pl-0,
.px-0 {
  padding-left: 0 !important;
}

.p-1 {
  padding: 0.25rem !important;
}

.pt-1,
.py-1 {
  padding-top: 0.25rem !important;
}

.pr-1,
.px-1 {
  padding-right: 0.25rem !important;
}

.pb-1,
.py-1 {
  padding-bottom: 0.25rem !important;
}

.pl-1,
.px-1 {
  padding-left: 0.25rem !important;
}

.p-2 {
  padding: 0.5rem !important;
}

.pt-2,
.py-2 {
  padding-top: 0.5rem !important;
}

.pr-2,
.px-2 {
  padding-right: 0.5rem !important;
}

.pb-2,
.py-2 {
  padding-bottom: 0.5rem !important;
}

.pl-2,
.px-2 {
  padding-left: 0.5rem !important;
}

.p-3 {
  padding: 1rem !important;
}

.pt-3,
.py-3 {
  padding-top: 1rem !important;
}

.pr-3,
.px-3 {
  padding-right: 1rem !important;
}

.pb-3,
.py-3 {
  padding-bottom: 1rem !important;
}

.pl-3,
.px-3 {
  padding-left: 1rem !important;
}

.p-4 {
  padding: 1.5rem !important;
}

.pt-4,
.py-4 {
  padding-top: 1.5rem !important;
}

.pr-4,
.px-4 {
  padding-right: 1.5rem !important;
}

.pb-4,
.py-4 {
  padding-bottom: 1.5rem !important;
}

.pl-4,
.px-4 {
  padding-left: 1.5rem !important;
}

.p-5 {
  padding: 3rem !important;
}

.pt-5,
.py-5 {
  padding-top: 3rem !important;
}

.pr-5,
.px-5 {
  padding-right: 3rem !important;
}

.pb-5,
.py-5 {
  padding-bottom: 3rem !important;
}

.pl-5,
.px-5 {
  padding-left: 3rem !important;
}

.m-n1 {
  margin: -0.25rem !important;
}

.mt-n1,
.my-n1 {
  margin-top: -0.25rem !important;
}

.mr-n1,
.mx-n1 {
  margin-right: -0.25rem !important;
}

.mb-n1,
.my-n1 {
  margin-bottom: -0.25rem !important;
}

.ml-n1,
.mx-n1 {
  margin-left: -0.25rem !important;
}

.m-n2 {
  margin: -0.5rem !important;
}

.mt-n2,
.my-n2 {
  margin-top: -0.5rem !important;
}

.mr-n2,
.mx-n2 {
  margin-right: -0.5rem !important;
}

.mb-n2,
.my-n2 {
  margin-bottom: -0.5rem !important;
}

.ml-n2,
.mx-n2 {
  margin-left: -0.5rem !important;
}

.m-n3 {
  margin: -1rem !important;
}

.mt-n3,
.my-n3 {
  margin-top: -1rem !important;
}

.mr-n3,
.mx-n3 {
  margin-right: -1rem !important;
}

.mb-n3,
.my-n3 {
  margin-bottom: -1rem !important;
}

.ml-n3,
.mx-n3 {
  margin-left: -1rem !important;
}

.m-n4 {
  margin: -1.5rem !important;
}

.mt-n4,
.my-n4 {
  margin-top: -1.5rem !important;
}

.mr-n4,
.mx-n4 {
  margin-right: -1.5rem !important;
}

.mb-n4,
.my-n4 {
  margin-bottom: -1.5rem !important;
}

.ml-n4,
.mx-n4 {
  margin-left: -1.5rem !important;
}

.m-n5 {
  margin: -3rem !important;
}

.mt-n5,
.my-n5 {
  margin-top: -3rem !important;
}

.mr-n5,
.mx-n5 {
  margin-right: -3rem !important;
}

.mb-n5,
.my-n5 {
  margin-bottom: -3rem !important;
}

.ml-n5,
.mx-n5 {
  margin-left: -3rem !important;
}

.m-auto {
  margin: auto !important;
}

.mt-auto,
.my-auto {
  margin-top: auto !important;
}

.mr-auto,
.mx-auto {
  margin-right: auto !important;
}

.mb-auto,
.my-auto {
  margin-bottom: auto !important;
}

.ml-auto,
.mx-auto {
  margin-left: auto !important;
}

@media (min-width: 576px) {
  .m-sm-0 {
    margin: 0 !important;
  }
  .mt-sm-0,
  .my-sm-0 {
    margin-top: 0 !important;
  }
  .mr-sm-0,
  .mx-sm-0 {
    margin-right: 0 !important;
  }
  .mb-sm-0,
  .my-sm-0 {
    margin-bottom: 0 !important;
  }
  .ml-sm-0,
  .mx-sm-0 {
    margin-left: 0 !important;
  }
  .m-sm-1 {
    margin: 0.25rem !important;
  }
  .mt-sm-1,
  .my-sm-1 {
    margin-top: 0.25rem !important;
  }
  .mr-sm-1,
  .mx-sm-1 {
    margin-right: 0.25rem !important;
  }
  .mb-sm-1,
  .my-sm-1 {
    margin-bottom: 0.25rem !important;
  }
  .ml-sm-1,
  .mx-sm-1 {
    margin-left: 0.25rem !important;
  }
  .m-sm-2 {
    margin: 0.5rem !important;
  }
  .mt-sm-2,
  .my-sm-2 {
    margin-top: 0.5rem !important;
  }
  .mr-sm-2,
  .mx-sm-2 {
    margin-right: 0.5rem !important;
  }
  .mb-sm-2,
  .my-sm-2 {
    margin-bottom: 0.5rem !important;
  }
  .ml-sm-2,
  .mx-sm-2 {
    margin-left: 0.5rem !important;
  }
  .m-sm-3 {
    margin: 1rem !important;
  }
  .mt-sm-3,
  .my-sm-3 {
    margin-top: 1rem !important;
  }
  .mr-sm-3,
  .mx-sm-3 {
    margin-right: 1rem !important;
  }
  .mb-sm-3,
  .my-sm-3 {
    margin-bottom: 1rem !important;
  }
  .ml-sm-3,
  .mx-sm-3 {
    margin-left: 1rem !important;
  }
  .m-sm-4 {
    margin: 1.5rem !important;
  }
  .mt-sm-4,
  .my-sm-4 {
    margin-top: 1.5rem !important;
  }
  .mr-sm-4,
  .mx-sm-4 {
    margin-right: 1.5rem !important;
  }
  .mb-sm-4,
  .my-sm-4 {
    margin-bottom: 1.5rem !important;
  }
  .ml-sm-4,
  .mx-sm-4 {
    margin-left: 1.5rem !important;
  }
  .m-sm-5 {
    margin: 3rem !important;
  }
  .mt-sm-5,
  .my-sm-5 {
    margin-top: 3rem !important;
  }
  .mr-sm-5,
  .mx-sm-5 {
    margin-right: 3rem !important;
  }
  .mb-sm-5,
  .my-sm-5 {
    margin-bottom: 3rem !important;
  }
  .ml-sm-5,
  .mx-sm-5 {
    margin-left: 3rem !important;
  }
  .p-sm-0 {
    padding: 0 !important;
  }
  .pt-sm-0,
  .py-sm-0 {
    padding-top: 0 !important;
  }
  .pr-sm-0,
  .px-sm-0 {
    padding-right: 0 !important;
  }
  .pb-sm-0,
  .py-sm-0 {
    padding-bottom: 0 !important;
  }
  .pl-sm-0,
  .px-sm-0 {
    padding-left: 0 !important;
  }
  .p-sm-1 {
    padding: 0.25rem !important;
  }
  .pt-sm-1,
  .py-sm-1 {
    padding-top: 0.25rem !important;
  }
  .pr-sm-1,
  .px-sm-1 {
    padding-right: 0.25rem !important;
  }
  .pb-sm-1,
  .py-sm-1 {
    padding-bottom: 0.25rem !important;
  }
  .pl-sm-1,
  .px-sm-1 {
    padding-left: 0.25rem !important;
  }
  .p-sm-2 {
    padding: 0.5rem !important;
  }
  .pt-sm-2,
  .py-sm-2 {
    padding-top: 0.5rem !important;
  }
  .pr-sm-2,
  .px-sm-2 {
    padding-right: 0.5rem !important;
  }
  .pb-sm-2,
  .py-sm-2 {
    padding-bottom: 0.5rem !important;
  }
  .pl-sm-2,
  .px-sm-2 {
    padding-left: 0.5rem !important;
  }
  .p-sm-3 {
    padding: 1rem !important;
  }
  .pt-sm-3,
  .py-sm-3 {
    padding-top: 1rem !important;
  }
  .pr-sm-3,
  .px-sm-3 {
    padding-right: 1rem !important;
  }
  .pb-sm-3,
  .py-sm-3 {
    padding-bottom: 1rem !important;
  }
  .pl-sm-3,
  .px-sm-3 {
    padding-left: 1rem !important;
  }
  .p-sm-4 {
    padding: 1.5rem !important;
  }
  .pt-sm-4,
  .py-sm-4 {
    padding-top: 1.5rem !important;
  }
  .pr-sm-4,
  .px-sm-4 {
    padding-right: 1.5rem !important;
  }
  .pb-sm-4,
  .py-sm-4 {
    padding-bottom: 1.5rem !important;
  }
  .pl-sm-4,
  .px-sm-4 {
    padding-left: 1.5rem !important;
  }
  .p-sm-5 {
    padding: 3rem !important;
  }
  .pt-sm-5,
  .py-sm-5 {
    padding-top: 3rem !important;
  }
  .pr-sm-5,
  .px-sm-5 {
    padding-right: 3rem !important;
  }
  .pb-sm-5,
  .py-sm-5 {
    padding-bottom: 3rem !important;
  }
  .pl-sm-5,
  .px-sm-5 {
    padding-left: 3rem !important;
  }
  .m-sm-n1 {
    margin: -0.25rem !important;
  }
  .mt-sm-n1,
  .my-sm-n1 {
    margin-top: -0.25rem !important;
  }
  .mr-sm-n1,
  .mx-sm-n1 {
    margin-right: -0.25rem !important;
  }
  .mb-sm-n1,
  .my-sm-n1 {
    margin-bottom: -0.25rem !important;
  }
  .ml-sm-n1,
  .mx-sm-n1 {
    margin-left: -0.25rem !important;
  }
  .m-sm-n2 {
    margin: -0.5rem !important;
  }
  .mt-sm-n2,
  .my-sm-n2 {
    margin-top: -0.5rem !important;
  }
  .mr-sm-n2,
  .mx-sm-n2 {
    margin-right: -0.5rem !important;
  }
  .mb-sm-n2,
  .my-sm-n2 {
    margin-bottom: -0.5rem !important;
  }
  .ml-sm-n2,
  .mx-sm-n2 {
    margin-left: -0.5rem !important;
  }
  .m-sm-n3 {
    margin: -1rem !important;
  }
  .mt-sm-n3,
  .my-sm-n3 {
    margin-top: -1rem !important;
  }
  .mr-sm-n3,
  .mx-sm-n3 {
    margin-right: -1rem !important;
  }
  .mb-sm-n3,
  .my-sm-n3 {
    margin-bottom: -1rem !important;
  }
  .ml-sm-n3,
  .mx-sm-n3 {
    margin-left: -1rem !important;
  }
  .m-sm-n4 {
    margin: -1.5rem !important;
  }
  .mt-sm-n4,
  .my-sm-n4 {
    margin-top: -1.5rem !important;
  }
  .mr-sm-n4,
  .mx-sm-n4 {
    margin-right: -1.5rem !important;
  }
  .mb-sm-n4,
  .my-sm-n4 {
    margin-bottom: -1.5rem !important;
  }
  .ml-sm-n4,
  .mx-sm-n4 {
    margin-left: -1.5rem !important;
  }
  .m-sm-n5 {
    margin: -3rem !important;
  }
  .mt-sm-n5,
  .my-sm-n5 {
    margin-top: -3rem !important;
  }
  .mr-sm-n5,
  .mx-sm-n5 {
    margin-right: -3rem !important;
  }
  .mb-sm-n5,
  .my-sm-n5 {
    margin-bottom: -3rem !important;
  }
  .ml-sm-n5,
  .mx-sm-n5 {
    margin-left: -3rem !important;
  }
  .m-sm-auto {
    margin: auto !important;
  }
  .mt-sm-auto,
  .my-sm-auto {
    margin-top: auto !important;
  }
  .mr-sm-auto,
  .mx-sm-auto {
    margin-right: auto !important;
  }
  .mb-sm-auto,
  .my-sm-auto {
    margin-bottom: auto !important;
  }
  .ml-sm-auto,
  .mx-sm-auto {
    margin-left: auto !important;
  }
}

@media (min-width: 768px) {
  .m-md-0 {
    margin: 0 !important;
  }
  .mt-md-0,
  .my-md-0 {
    margin-top: 0 !important;
  }
  .mr-md-0,
  .mx-md-0 {
    margin-right: 0 !important;
  }
  .mb-md-0,
  .my-md-0 {
    margin-bottom: 0 !important;
  }
  .ml-md-0,
  .mx-md-0 {
    margin-left: 0 !important;
  }
  .m-md-1 {
    margin: 0.25rem !important;
  }
  .mt-md-1,
  .my-md-1 {
    margin-top: 0.25rem !important;
  }
  .mr-md-1,
  .mx-md-1 {
    margin-right: 0.25rem !important;
  }
  .mb-md-1,
  .my-md-1 {
    margin-bottom: 0.25rem !important;
  }
  .ml-md-1,
  .mx-md-1 {
    margin-left: 0.25rem !important;
  }
  .m-md-2 {
    margin: 0.5rem !important;
  }
  .mt-md-2,
  .my-md-2 {
    margin-top: 0.5rem !important;
  }
  .mr-md-2,
  .mx-md-2 {
    margin-right: 0.5rem !important;
  }
  .mb-md-2,
  .my-md-2 {
    margin-bottom: 0.5rem !important;
  }
  .ml-md-2,
  .mx-md-2 {
    margin-left: 0.5rem !important;
  }
  .m-md-3 {
    margin: 1rem !important;
  }
  .mt-md-3,
  .my-md-3 {
    margin-top: 1rem !important;
  }
  .mr-md-3,
  .mx-md-3 {
    margin-right: 1rem !important;
  }
  .mb-md-3,
  .my-md-3 {
    margin-bottom: 1rem !important;
  }
  .ml-md-3,
  .mx-md-3 {
    margin-left: 1rem !important;
  }
  .m-md-4 {
    margin: 1.5rem !important;
  }
  .mt-md-4,
  .my-md-4 {
    margin-top: 1.5rem !important;
  }
  .mr-md-4,
  .mx-md-4 {
    margin-right: 1.5rem !important;
  }
  .mb-md-4,
  .my-md-4 {
    margin-bottom: 1.5rem !important;
  }
  .ml-md-4,
  .mx-md-4 {
    margin-left: 1.5rem !important;
  }
  .m-md-5 {
    margin: 3rem !important;
  }
  .mt-md-5,
  .my-md-5 {
    margin-top: 3rem !important;
  }
  .mr-md-5,
  .mx-md-5 {
    margin-right: 3rem !important;
  }
  .mb-md-5,
  .my-md-5 {
    margin-bottom: 3rem !important;
  }
  .ml-md-5,
  .mx-md-5 {
    margin-left: 3rem !important;
  }
  .p-md-0 {
    padding: 0 !important;
  }
  .pt-md-0,
  .py-md-0 {
    padding-top: 0 !important;
  }
  .pr-md-0,
  .px-md-0 {
    padding-right: 0 !important;
  }
  .pb-md-0,
  .py-md-0 {
    padding-bottom: 0 !important;
  }
  .pl-md-0,
  .px-md-0 {
    padding-left: 0 !important;
  }
  .p-md-1 {
    padding: 0.25rem !important;
  }
  .pt-md-1,
  .py-md-1 {
    padding-top: 0.25rem !important;
  }
  .pr-md-1,
  .px-md-1 {
    padding-right: 0.25rem !important;
  }
  .pb-md-1,
  .py-md-1 {
    padding-bottom: 0.25rem !important;
  }
  .pl-md-1,
  .px-md-1 {
    padding-left: 0.25rem !important;
  }
  .p-md-2 {
    padding: 0.5rem !important;
  }
  .pt-md-2,
  .py-md-2 {
    padding-top: 0.5rem !important;
  }
  .pr-md-2,
  .px-md-2 {
    padding-right: 0.5rem !important;
  }
  .pb-md-2,
  .py-md-2 {
    padding-bottom: 0.5rem !important;
  }
  .pl-md-2,
  .px-md-2 {
    padding-left: 0.5rem !important;
  }
  .p-md-3 {
    padding: 1rem !important;
  }
  .pt-md-3,
  .py-md-3 {
    padding-top: 1rem !important;
  }
  .pr-md-3,
  .px-md-3 {
    padding-right: 1rem !important;
  }
  .pb-md-3,
  .py-md-3 {
    padding-bottom: 1rem !important;
  }
  .pl-md-3,
  .px-md-3 {
    padding-left: 1rem !important;
  }
  .p-md-4 {
    padding: 1.5rem !important;
  }
  .pt-md-4,
  .py-md-4 {
    padding-top: 1.5rem !important;
  }
  .pr-md-4,
  .px-md-4 {
    padding-right: 1.5rem !important;
  }
  .pb-md-4,
  .py-md-4 {
    padding-bottom: 1.5rem !important;
  }
  .pl-md-4,
  .px-md-4 {
    padding-left: 1.5rem !important;
  }
  .p-md-5 {
    padding: 3rem !important;
  }
  .pt-md-5,
  .py-md-5 {
    padding-top: 3rem !important;
  }
  .pr-md-5,
  .px-md-5 {
    padding-right: 3rem !important;
  }
  .pb-md-5,
  .py-md-5 {
    padding-bottom: 3rem !important;
  }
  .pl-md-5,
  .px-md-5 {
    padding-left: 3rem !important;
  }
  .m-md-n1 {
    margin: -0.25rem !important;
  }
  .mt-md-n1,
  .my-md-n1 {
    margin-top: -0.25rem !important;
  }
  .mr-md-n1,
  .mx-md-n1 {
    margin-right: -0.25rem !important;
  }
  .mb-md-n1,
  .my-md-n1 {
    margin-bottom: -0.25rem !important;
  }
  .ml-md-n1,
  .mx-md-n1 {
    margin-left: -0.25rem !important;
  }
  .m-md-n2 {
    margin: -0.5rem !important;
  }
  .mt-md-n2,
  .my-md-n2 {
    margin-top: -0.5rem !important;
  }
  .mr-md-n2,
  .mx-md-n2 {
    margin-right: -0.5rem !important;
  }
  .mb-md-n2,
  .my-md-n2 {
    margin-bottom: -0.5rem !important;
  }
  .ml-md-n2,
  .mx-md-n2 {
    margin-left: -0.5rem !important;
  }
  .m-md-n3 {
    margin: -1rem !important;
  }
  .mt-md-n3,
  .my-md-n3 {
    margin-top: -1rem !important;
  }
  .mr-md-n3,
  .mx-md-n3 {
    margin-right: -1rem !important;
  }
  .mb-md-n3,
  .my-md-n3 {
    margin-bottom: -1rem !important;
  }
  .ml-md-n3,
  .mx-md-n3 {
    margin-left: -1rem !important;
  }
  .m-md-n4 {
    margin: -1.5rem !important;
  }
  .mt-md-n4,
  .my-md-n4 {
    margin-top: -1.5rem !important;
  }
  .mr-md-n4,
  .mx-md-n4 {
    margin-right: -1.5rem !important;
  }
  .mb-md-n4,
  .my-md-n4 {
    margin-bottom: -1.5rem !important;
  }
  .ml-md-n4,
  .mx-md-n4 {
    margin-left: -1.5rem !important;
  }
  .m-md-n5 {
    margin: -3rem !important;
  }
  .mt-md-n5,
  .my-md-n5 {
    margin-top: -3rem !important;
  }
  .mr-md-n5,
  .mx-md-n5 {
    margin-right: -3rem !important;
  }
  .mb-md-n5,
  .my-md-n5 {
    margin-bottom: -3rem !important;
  }
  .ml-md-n5,
  .mx-md-n5 {
    margin-left: -3rem !important;
  }
  .m-md-auto {
    margin: auto !important;
  }
  .mt-md-auto,
  .my-md-auto {
    margin-top: auto !important;
  }
  .mr-md-auto,
  .mx-md-auto {
    margin-right: auto !important;
  }
  .mb-md-auto,
  .my-md-auto {
    margin-bottom: auto !important;
  }
  .ml-md-auto,
  .mx-md-auto {
    margin-left: auto !important;
  }
}

@media (min-width: 992px) {
  .m-lg-0 {
    margin: 0 !important;
  }
  .mt-lg-0,
  .my-lg-0 {
    margin-top: 0 !important;
  }
  .mr-lg-0,
  .mx-lg-0 {
    margin-right: 0 !important;
  }
  .mb-lg-0,
  .my-lg-0 {
    margin-bottom: 0 !important;
  }
  .ml-lg-0,
  .mx-lg-0 {
    margin-left: 0 !important;
  }
  .m-lg-1 {
    margin: 0.25rem !important;
  }
  .mt-lg-1,
  .my-lg-1 {
    margin-top: 0.25rem !important;
  }
  .mr-lg-1,
  .mx-lg-1 {
    margin-right: 0.25rem !important;
  }
  .mb-lg-1,
  .my-lg-1 {
    margin-bottom: 0.25rem !important;
  }
  .ml-lg-1,
  .mx-lg-1 {
    margin-left: 0.25rem !important;
  }
  .m-lg-2 {
    margin: 0.5rem !important;
  }
  .mt-lg-2,
  .my-lg-2 {
    margin-top: 0.5rem !important;
  }
  .mr-lg-2,
  .mx-lg-2 {
    margin-right: 0.5rem !important;
  }
  .mb-lg-2,
  .my-lg-2 {
    margin-bottom: 0.5rem !important;
  }
  .ml-lg-2,
  .mx-lg-2 {
    margin-left: 0.5rem !important;
  }
  .m-lg-3 {
    margin: 1rem !important;
  }
  .mt-lg-3,
  .my-lg-3 {
    margin-top: 1rem !important;
  }
  .mr-lg-3,
  .mx-lg-3 {
    margin-right: 1rem !important;
  }
  .mb-lg-3,
  .my-lg-3 {
    margin-bottom: 1rem !important;
  }
  .ml-lg-3,
  .mx-lg-3 {
    margin-left: 1rem !important;
  }
  .m-lg-4 {
    margin: 1.5rem !important;
  }
  .mt-lg-4,
  .my-lg-4 {
    margin-top: 1.5rem !important;
  }
  .mr-lg-4,
  .mx-lg-4 {
    margin-right: 1.5rem !important;
  }
  .mb-lg-4,
  .my-lg-4 {
    margin-bottom: 1.5rem !important;
  }
  .ml-lg-4,
  .mx-lg-4 {
    margin-left: 1.5rem !important;
  }
  .m-lg-5 {
    margin: 3rem !important;
  }
  .mt-lg-5,
  .my-lg-5 {
    margin-top: 3rem !important;
  }
  .mr-lg-5,
  .mx-lg-5 {
    margin-right: 3rem !important;
  }
  .mb-lg-5,
  .my-lg-5 {
    margin-bottom: 3rem !important;
  }
  .ml-lg-5,
  .mx-lg-5 {
    margin-left: 3rem !important;
  }
  .p-lg-0 {
    padding: 0 !important;
  }
  .pt-lg-0,
  .py-lg-0 {
    padding-top: 0 !important;
  }
  .pr-lg-0,
  .px-lg-0 {
    padding-right: 0 !important;
  }
  .pb-lg-0,
  .py-lg-0 {
    padding-bottom: 0 !important;
  }
  .pl-lg-0,
  .px-lg-0 {
    padding-left: 0 !important;
  }
  .p-lg-1 {
    padding: 0.25rem !important;
  }
  .pt-lg-1,
  .py-lg-1 {
    padding-top: 0.25rem !important;
  }
  .pr-lg-1,
  .px-lg-1 {
    padding-right: 0.25rem !important;
  }
  .pb-lg-1,
  .py-lg-1 {
    padding-bottom: 0.25rem !important;
  }
  .pl-lg-1,
  .px-lg-1 {
    padding-left: 0.25rem !important;
  }
  .p-lg-2 {
    padding: 0.5rem !important;
  }
  .pt-lg-2,
  .py-lg-2 {
    padding-top: 0.5rem !important;
  }
  .pr-lg-2,
  .px-lg-2 {
    padding-right: 0.5rem !important;
  }
  .pb-lg-2,
  .py-lg-2 {
    padding-bottom: 0.5rem !important;
  }
  .pl-lg-2,
  .px-lg-2 {
    padding-left: 0.5rem !important;
  }
  .p-lg-3 {
    padding: 1rem !important;
  }
  .pt-lg-3,
  .py-lg-3 {
    padding-top: 1rem !important;
  }
  .pr-lg-3,
  .px-lg-3 {
    padding-right: 1rem !important;
  }
  .pb-lg-3,
  .py-lg-3 {
    padding-bottom: 1rem !important;
  }
  .pl-lg-3,
  .px-lg-3 {
    padding-left: 1rem !important;
  }
  .p-lg-4 {
    padding: 1.5rem !important;
  }
  .pt-lg-4,
  .py-lg-4 {
    padding-top: 1.5rem !important;
  }
  .pr-lg-4,
  .px-lg-4 {
    padding-right: 1.5rem !important;
  }
  .pb-lg-4,
  .py-lg-4 {
    padding-bottom: 1.5rem !important;
  }
  .pl-lg-4,
  .px-lg-4 {
    padding-left: 1.5rem !important;
  }
  .p-lg-5 {
    padding: 3rem !important;
  }
  .pt-lg-5,
  .py-lg-5 {
    padding-top: 3rem !important;
  }
  .pr-lg-5,
  .px-lg-5 {
    padding-right: 3rem !important;
  }
  .pb-lg-5,
  .py-lg-5 {
    padding-bottom: 3rem !important;
  }
  .pl-lg-5,
  .px-lg-5 {
    padding-left: 3rem !important;
  }
  .m-lg-n1 {
    margin: -0.25rem !important;
  }
  .mt-lg-n1,
  .my-lg-n1 {
    margin-top: -0.25rem !important;
  }
  .mr-lg-n1,
  .mx-lg-n1 {
    margin-right: -0.25rem !important;
  }
  .mb-lg-n1,
  .my-lg-n1 {
    margin-bottom: -0.25rem !important;
  }
  .ml-lg-n1,
  .mx-lg-n1 {
    margin-left: -0.25rem !important;
  }
  .m-lg-n2 {
    margin: -0.5rem !important;
  }
  .mt-lg-n2,
  .my-lg-n2 {
    margin-top: -0.5rem !important;
  }
  .mr-lg-n2,
  .mx-lg-n2 {
    margin-right: -0.5rem !important;
  }
  .mb-lg-n2,
  .my-lg-n2 {
    margin-bottom: -0.5rem !important;
  }
  .ml-lg-n2,
  .mx-lg-n2 {
    margin-left: -0.5rem !important;
  }
  .m-lg-n3 {
    margin: -1rem !important;
  }
  .mt-lg-n3,
  .my-lg-n3 {
    margin-top: -1rem !important;
  }
  .mr-lg-n3,
  .mx-lg-n3 {
    margin-right: -1rem !important;
  }
  .mb-lg-n3,
  .my-lg-n3 {
    margin-bottom: -1rem !important;
  }
  .ml-lg-n3,
  .mx-lg-n3 {
    margin-left: -1rem !important;
  }
  .m-lg-n4 {
    margin: -1.5rem !important;
  }
  .mt-lg-n4,
  .my-lg-n4 {
    margin-top: -1.5rem !important;
  }
  .mr-lg-n4,
  .mx-lg-n4 {
    margin-right: -1.5rem !important;
  }
  .mb-lg-n4,
  .my-lg-n4 {
    margin-bottom: -1.5rem !important;
  }
  .ml-lg-n4,
  .mx-lg-n4 {
    margin-left: -1.5rem !important;
  }
  .m-lg-n5 {
    margin: -3rem !important;
  }
  .mt-lg-n5,
  .my-lg-n5 {
    margin-top: -3rem !important;
  }
  .mr-lg-n5,
  .mx-lg-n5 {
    margin-right: -3rem !important;
  }
  .mb-lg-n5,
  .my-lg-n5 {
    margin-bottom: -3rem !important;
  }
  .ml-lg-n5,
  .mx-lg-n5 {
    margin-left: -3rem !important;
  }
  .m-lg-auto {
    margin: auto !important;
  }
  .mt-lg-auto,
  .my-lg-auto {
    margin-top: auto !important;
  }
  .mr-lg-auto,
  .mx-lg-auto {
    margin-right: auto !important;
  }
  .mb-lg-auto,
  .my-lg-auto {
    margin-bottom: auto !important;
  }
  .ml-lg-auto,
  .mx-lg-auto {
    margin-left: auto !important;
  }
}

@media (min-width: 1200px) {
  .m-xl-0 {
    margin: 0 !important;
  }
  .mt-xl-0,
  .my-xl-0 {
    margin-top: 0 !important;
  }
  .mr-xl-0,
  .mx-xl-0 {
    margin-right: 0 !important;
  }
  .mb-xl-0,
  .my-xl-0 {
    margin-bottom: 0 !important;
  }
  .ml-xl-0,
  .mx-xl-0 {
    margin-left: 0 !important;
  }
  .m-xl-1 {
    margin: 0.25rem !important;
  }
  .mt-xl-1,
  .my-xl-1 {
    margin-top: 0.25rem !important;
  }
  .mr-xl-1,
  .mx-xl-1 {
    margin-right: 0.25rem !important;
  }
  .mb-xl-1,
  .my-xl-1 {
    margin-bottom: 0.25rem !important;
  }
  .ml-xl-1,
  .mx-xl-1 {
    margin-left: 0.25rem !important;
  }
  .m-xl-2 {
    margin: 0.5rem !important;
  }
  .mt-xl-2,
  .my-xl-2 {
    margin-top: 0.5rem !important;
  }
  .mr-xl-2,
  .mx-xl-2 {
    margin-right: 0.5rem !important;
  }
  .mb-xl-2,
  .my-xl-2 {
    margin-bottom: 0.5rem !important;
  }
  .ml-xl-2,
  .mx-xl-2 {
    margin-left: 0.5rem !important;
  }
  .m-xl-3 {
    margin: 1rem !important;
  }
  .mt-xl-3,
  .my-xl-3 {
    margin-top: 1rem !important;
  }
  .mr-xl-3,
  .mx-xl-3 {
    margin-right: 1rem !important;
  }
  .mb-xl-3,
  .my-xl-3 {
    margin-bottom: 1rem !important;
  }
  .ml-xl-3,
  .mx-xl-3 {
    margin-left: 1rem !important;
  }
  .m-xl-4 {
    margin: 1.5rem !important;
  }
  .mt-xl-4,
  .my-xl-4 {
    margin-top: 1.5rem !important;
  }
  .mr-xl-4,
  .mx-xl-4 {
    margin-right: 1.5rem !important;
  }
  .mb-xl-4,
  .my-xl-4 {
    margin-bottom: 1.5rem !important;
  }
  .ml-xl-4,
  .mx-xl-4 {
    margin-left: 1.5rem !important;
  }
  .m-xl-5 {
    margin: 3rem !important;
  }
  .mt-xl-5,
  .my-xl-5 {
    margin-top: 3rem !important;
  }
  .mr-xl-5,
  .mx-xl-5 {
    margin-right: 3rem !important;
  }
  .mb-xl-5,
  .my-xl-5 {
    margin-bottom: 3rem !important;
  }
  .ml-xl-5,
  .mx-xl-5 {
    margin-left: 3rem !important;
  }
  .p-xl-0 {
    padding: 0 !important;
  }
  .pt-xl-0,
  .py-xl-0 {
    padding-top: 0 !important;
  }
  .pr-xl-0,
  .px-xl-0 {
    padding-right: 0 !important;
  }
  .pb-xl-0,
  .py-xl-0 {
    padding-bottom: 0 !important;
  }
  .pl-xl-0,
  .px-xl-0 {
    padding-left: 0 !important;
  }
  .p-xl-1 {
    padding: 0.25rem !important;
  }
  .pt-xl-1,
  .py-xl-1 {
    padding-top: 0.25rem !important;
  }
  .pr-xl-1,
  .px-xl-1 {
    padding-right: 0.25rem !important;
  }
  .pb-xl-1,
  .py-xl-1 {
    padding-bottom: 0.25rem !important;
  }
  .pl-xl-1,
  .px-xl-1 {
    padding-left: 0.25rem !important;
  }
  .p-xl-2 {
    padding: 0.5rem !important;
  }
  .pt-xl-2,
  .py-xl-2 {
    padding-top: 0.5rem !important;
  }
  .pr-xl-2,
  .px-xl-2 {
    padding-right: 0.5rem !important;
  }
  .pb-xl-2,
  .py-xl-2 {
    padding-bottom: 0.5rem !important;
  }
  .pl-xl-2,
  .px-xl-2 {
    padding-left: 0.5rem !important;
  }
  .p-xl-3 {
    padding: 1rem !important;
  }
  .pt-xl-3,
  .py-xl-3 {
    padding-top: 1rem !important;
  }
  .pr-xl-3,
  .px-xl-3 {
    padding-right: 1rem !important;
  }
  .pb-xl-3,
  .py-xl-3 {
    padding-bottom: 1rem !important;
  }
  .pl-xl-3,
  .px-xl-3 {
    padding-left: 1rem !important;
  }
  .p-xl-4 {
    padding: 1.5rem !important;
  }
  .pt-xl-4,
  .py-xl-4 {
    padding-top: 1.5rem !important;
  }
  .pr-xl-4,
  .px-xl-4 {
    padding-right: 1.5rem !important;
  }
  .pb-xl-4,
  .py-xl-4 {
    padding-bottom: 1.5rem !important;
  }
  .pl-xl-4,
  .px-xl-4 {
    padding-left: 1.5rem !important;
  }
  .p-xl-5 {
    padding: 3rem !important;
  }
  .pt-xl-5,
  .py-xl-5 {
    padding-top: 3rem !important;
  }
  .pr-xl-5,
  .px-xl-5 {
    padding-right: 3rem !important;
  }
  .pb-xl-5,
  .py-xl-5 {
    padding-bottom: 3rem !important;
  }
  .pl-xl-5,
  .px-xl-5 {
    padding-left: 3rem !important;
  }
  .m-xl-n1 {
    margin: -0.25rem !important;
  }
  .mt-xl-n1,
  .my-xl-n1 {
    margin-top: -0.25rem !important;
  }
  .mr-xl-n1,
  .mx-xl-n1 {
    margin-right: -0.25rem !important;
  }
  .mb-xl-n1,
  .my-xl-n1 {
    margin-bottom: -0.25rem !important;
  }
  .ml-xl-n1,
  .mx-xl-n1 {
    margin-left: -0.25rem !important;
  }
  .m-xl-n2 {
    margin: -0.5rem !important;
  }
  .mt-xl-n2,
  .my-xl-n2 {
    margin-top: -0.5rem !important;
  }
  .mr-xl-n2,
  .mx-xl-n2 {
    margin-right: -0.5rem !important;
  }
  .mb-xl-n2,
  .my-xl-n2 {
    margin-bottom: -0.5rem !important;
  }
  .ml-xl-n2,
  .mx-xl-n2 {
    margin-left: -0.5rem !important;
  }
  .m-xl-n3 {
    margin: -1rem !important;
  }
  .mt-xl-n3,
  .my-xl-n3 {
    margin-top: -1rem !important;
  }
  .mr-xl-n3,
  .mx-xl-n3 {
    margin-right: -1rem !important;
  }
  .mb-xl-n3,
  .my-xl-n3 {
    margin-bottom: -1rem !important;
  }
  .ml-xl-n3,
  .mx-xl-n3 {
    margin-left: -1rem !important;
  }
  .m-xl-n4 {
    margin: -1.5rem !important;
  }
  .mt-xl-n4,
  .my-xl-n4 {
    margin-top: -1.5rem !important;
  }
  .mr-xl-n4,
  .mx-xl-n4 {
    margin-right: -1.5rem !important;
  }
  .mb-xl-n4,
  .my-xl-n4 {
    margin-bottom: -1.5rem !important;
  }
  .ml-xl-n4,
  .mx-xl-n4 {
    margin-left: -1.5rem !important;
  }
  .m-xl-n5 {
    margin: -3rem !important;
  }
  .mt-xl-n5,
  .my-xl-n5 {
    margin-top: -3rem !important;
  }
  .mr-xl-n5,
  .mx-xl-n5 {
    margin-right: -3rem !important;
  }
  .mb-xl-n5,
  .my-xl-n5 {
    margin-bottom: -3rem !important;
  }
  .ml-xl-n5,
  .mx-xl-n5 {
    margin-left: -3rem !important;
  }
  .m-xl-auto {
    margin: auto !important;
  }
  .mt-xl-auto,
  .my-xl-auto {
    margin-top: auto !important;
  }
  .mr-xl-auto,
  .mx-xl-auto {
    margin-right: auto !important;
  }
  .mb-xl-auto,
  .my-xl-auto {
    margin-bottom: auto !important;
  }
  .ml-xl-auto,
  .mx-xl-auto {
    margin-left: auto !important;
  }
}
/*# sourceMappingURL=bootstrap-grid.css.map */

================================================
FILE: reCAPTCHA.AspNetCore.Example/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.css
================================================
/*!
 * Bootstrap Reboot v4.3.1 (https://getbootstrap.com/)
 * Copyright 2011-2019 The Bootstrap Authors
 * Copyright 2011-2019 Twitter, Inc.
 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
 * Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md)
 */
*,
*::before,
*::after {
  box-sizing: border-box;
}

html {
  font-family: sans-serif;
  line-height: 1.15;
  -webkit-text-size-adjust: 100%;
  -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
}

article, aside, figcaption, figure, footer, header, hgroup, main, nav, section {
  display: block;
}

body {
  margin: 0;
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
  font-size: 1rem;
  font-weight: 400;
  line-height: 1.5;
  color: #212529;
  text-align: left;
  background-color: #fff;
}

[tabindex="-1"]:focus {
  outline: 0 !important;
}

hr {
  box-sizing: content-box;
  height: 0;
  overflow: visible;
}

h1, h2, h3,
Download .txt
gitextract_6idzfx4c/

├── .gitignore
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── LICENSE
├── README.md
├── reCAPTCHA.AspNetCore/
│   ├── Attributes/
│   │   ├── RecaptchaResponseAttribute.cs
│   │   ├── ValidateRecaptchaAttribute.cs
│   │   └── ValidateRecaptchaFilter.cs
│   ├── CodeDom.cs
│   ├── IRecaptchaService.cs
│   ├── RecaptchaHelper.cs
│   ├── RecaptchaResponse.cs
│   ├── RecaptchaService.cs
│   ├── RecaptchaServiceCollection.cs
│   ├── RecaptchaSettings.cs
│   ├── Templates/
│   │   ├── RecaptchaV2Checkbox.cs
│   │   ├── RecaptchaV2Checkbox.tt
│   │   ├── RecaptchaV2CheckboxModelBinder.cs
│   │   ├── RecaptchaV2Invisible.cs
│   │   ├── RecaptchaV2Invisible.tt
│   │   ├── RecaptchaV2InvisibleModelBinder.cs
│   │   ├── RecaptchaV3HiddenInput.cs
│   │   ├── RecaptchaV3HiddenInput.tt
│   │   └── RecaptchaV3HiddenInputModelBinder.cs
│   ├── Versions/
│   │   ├── RecaptchaV2Checkbox.cs
│   │   ├── RecaptchaV2Invisible.cs
│   │   ├── RecaptchaV3HiddenInput.cs
│   │   └── RecaptchaVersion.cs
│   └── reCAPTCHA.AspNetCore.csproj
├── reCAPTCHA.AspNetCore.Example/
│   ├── Controllers/
│   │   ├── HomeController.cs
│   │   └── SomeAPIControlelr.cs
│   ├── Models/
│   │   ├── Contact4Model.cs
│   │   ├── ContactModel.cs
│   │   ├── ErrorViewModel.cs
│   │   └── OtherModel.cs
│   ├── Program.cs
│   ├── Startup.cs
│   ├── Views/
│   │   ├── Home/
│   │   │   ├── Contact.cshtml
│   │   │   ├── Contact2.cshtml
│   │   │   ├── Contact3.cshtml
│   │   │   ├── Contact4.cshtml
│   │   │   ├── Index.cshtml
│   │   │   └── Privacy.cshtml
│   │   ├── Shared/
│   │   │   ├── Error.cshtml
│   │   │   ├── _Layout.cshtml
│   │   │   └── _ValidationScriptsPartial.cshtml
│   │   ├── _ViewImports.cshtml
│   │   └── _ViewStart.cshtml
│   ├── appsettings.Development.json
│   ├── appsettings.json
│   ├── reCAPTCHA.AspNetCore.Example.csproj
│   └── wwwroot/
│       ├── css/
│       │   └── site.css
│       ├── js/
│       │   └── site.js
│       └── lib/
│           ├── bootstrap/
│           │   ├── LICENSE
│           │   └── dist/
│           │       ├── css/
│           │       │   ├── bootstrap-grid.css
│           │       │   ├── bootstrap-reboot.css
│           │       │   └── bootstrap.css
│           │       └── js/
│           │           ├── bootstrap.bundle.js
│           │           └── bootstrap.js
│           ├── jquery/
│           │   ├── LICENSE.txt
│           │   └── dist/
│           │       └── jquery.js
│           ├── jquery-validation/
│           │   ├── LICENSE.md
│           │   └── dist/
│           │       ├── additional-methods.js
│           │       └── jquery.validate.js
│           └── jquery-validation-unobtrusive/
│               ├── LICENSE.txt
│               └── jquery.validate.unobtrusive.js
└── reCAPTCHA.AspNetCore.sln
Download .txt
SYMBOL INDEX (268 symbols across 32 files)

FILE: reCAPTCHA.AspNetCore.Example/Controllers/HomeController.cs
  class HomeController (line 9) | public class HomeController : Controller
    method HomeController (line 15) | public HomeController(IRecaptchaService recaptcha)
    method Index (line 22) | public IActionResult Index()
    method Contact (line 27) | public IActionResult Contact()
    method Contact2 (line 34) | public IActionResult Contact2()
    method Contact3 (line 41) | public IActionResult Contact3()
    method Contact4 (line 48) | public IActionResult Contact4()
    method Contact (line 55) | [HttpPost]
    method Contact2 (line 64) | [HttpPost]
    method Contact3 (line 76) | [HttpPost]
    method Contact4 (line 84) | [HttpPost]
    method Privacy (line 93) | public IActionResult Privacy()
    method Error (line 98) | [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, No...

FILE: reCAPTCHA.AspNetCore.Example/Controllers/SomeAPIControlelr.cs
  class SomeApiController (line 8) | [ApiController, Route("SomeApi")]
    method SomeAction (line 11) | [HttpGet]
    method SomeAction (line 17) | [HttpPost]

FILE: reCAPTCHA.AspNetCore.Example/Models/Contact4Model.cs
  class Contact4Model (line 8) | public class Contact4Model

FILE: reCAPTCHA.AspNetCore.Example/Models/ContactModel.cs
  class ContactModel (line 8) | public class ContactModel

FILE: reCAPTCHA.AspNetCore.Example/Models/ErrorViewModel.cs
  class ErrorViewModel (line 5) | public class ErrorViewModel

FILE: reCAPTCHA.AspNetCore.Example/Models/OtherModel.cs
  class OtherModel (line 5) | public class OtherModel

FILE: reCAPTCHA.AspNetCore.Example/Program.cs
  class Program (line 12) | public class Program
    method Main (line 14) | public static void Main(string[] args)
    method CreateHostBuilder (line 19) | public static IHostBuilder CreateHostBuilder(string[] args) =>

FILE: reCAPTCHA.AspNetCore.Example/Startup.cs
  class Startup (line 9) | public class Startup
    method Startup (line 11) | public Startup(IConfiguration configuration)
    method ConfigureServices (line 19) | public void ConfigureServices(IServiceCollection services)
    method Configure (line 33) | public void Configure(IApplicationBuilder app, IWebHostEnvironment env)

FILE: reCAPTCHA.AspNetCore.Example/wwwroot/lib/bootstrap/dist/js/bootstrap.bundle.js
  function _defineProperties (line 14) | function _defineProperties(target, props) {
  function _createClass (line 24) | function _createClass(Constructor, protoProps, staticProps) {
  function _defineProperty (line 30) | function _defineProperty(obj, key, value) {
  function _objectSpread (line 45) | function _objectSpread(target) {
  function _inheritsLoose (line 64) | function _inheritsLoose(subClass, superClass) {
  function toType (line 86) | function toType(obj) {
  function getSpecialTransitionEndEvent (line 90) | function getSpecialTransitionEndEvent() {
  function transitionEndEmulator (line 104) | function transitionEndEmulator(duration) {
  function setTransitionEndSupport (line 119) | function setTransitionEndSupport() {
  function Alert (line 260) | function Alert(element) {
  function Button (line 428) | function Button(element) {
  function Carousel (line 635) | function Carousel(element, config) {
  function Collapse (line 1195) | function Collapse(element, config) {
  function microtaskDebounce (line 1539) | function microtaskDebounce(fn) {
  function taskDebounce (line 1553) | function taskDebounce(fn) {
  function isFunction (line 1586) | function isFunction(functionToCheck) {
  function getStyleComputedProperty (line 1598) | function getStyleComputedProperty(element, property) {
  function getParentNode (line 1615) | function getParentNode(element) {
  function getScrollParent (line 1629) | function getScrollParent(element) {
  function isIE (line 1667) | function isIE(version) {
  function getOffsetParent (line 1684) | function getOffsetParent(element) {
  function isOffsetContainer (line 1713) | function isOffsetContainer(element) {
  function getRoot (line 1729) | function getRoot(node) {
  function findCommonOffsetParent (line 1745) | function findCommonOffsetParent(element1, element2) {
  function getScroll (line 1789) | function getScroll(element) {
  function includeScroll (line 1813) | function includeScroll(rect, element) {
  function getBordersSize (line 1836) | function getBordersSize(styles, axis) {
  function getSize (line 1843) | function getSize(axis, body, html, computedStyle) {
  function getWindowSizes (line 1847) | function getWindowSizes(document) {
  function defineProperties (line 1865) | function defineProperties(target, props) {
  function getClientRect (line 1922) | function getClientRect(offsets) {
  function getBoundingClientRect (line 1936) | function getBoundingClientRect(element) {
  function getOffsetRectRelativeToArbitraryNode (line 1985) | function getOffsetRectRelativeToArbitraryNode(children, parent) {
  function getViewportOffsetRectRelativeToArtbitraryNode (line 2037) | function getViewportOffsetRectRelativeToArtbitraryNode(element) {
  function isFixed (line 2066) | function isFixed(element) {
  function getFixedPositionOffsetParent (line 2089) | function getFixedPositionOffsetParent(element) {
  function getBoundaries (line 2112) | function getBoundaries(popper, reference, padding, boundariesElement) {
  function getArea (line 2166) | function getArea(_ref) {
  function computeAutoPlacement (line 2182) | function computeAutoPlacement(placement, refRect, popper, reference, bou...
  function getReferenceOffsets (line 2243) | function getReferenceOffsets(state, popper, reference) {
  function getOuterSizes (line 2257) | function getOuterSizes(element) {
  function getOppositePlacement (line 2276) | function getOppositePlacement(placement) {
  function getPopperOffsets (line 2293) | function getPopperOffsets(popper, referenceOffsets, placement) {
  function find (line 2331) | function find(arr, check) {
  function findIndex (line 2350) | function findIndex(arr, prop, value) {
  function runModifiers (line 2375) | function runModifiers(modifiers, data, ends) {
  function update (line 2405) | function update() {
  function isModifierEnabled (line 2457) | function isModifierEnabled(modifiers, modifierName) {
  function getSupportedPropertyName (line 2472) | function getSupportedPropertyName(property) {
  function destroy (line 2491) | function destroy() {
  function getWindow (line 2521) | function getWindow(element) {
  function attachToScrollParents (line 2526) | function attachToScrollParents(scrollParent, event, callback, scrollPare...
  function setupEventListeners (line 2543) | function setupEventListeners(reference, options, state, updateBound) {
  function enableEventListeners (line 2563) | function enableEventListeners() {
  function removeEventListeners (line 2575) | function removeEventListeners(reference, state) {
  function disableEventListeners (line 2599) | function disableEventListeners() {
  function isNumeric (line 2613) | function isNumeric(n) {
  function setStyles (line 2625) | function setStyles(element, styles) {
  function setAttributes (line 2644) | function setAttributes(element, attributes) {
  function applyStyle (line 2664) | function applyStyle(data) {
  function applyStyleOnLoad (line 2693) | function applyStyleOnLoad(reference, popper, options, modifierOptions, s...
  function getRoundedOffsets (line 2730) | function getRoundedOffsets(data, shouldRound) {
  function computeStyle (line 2769) | function computeStyle(data, options) {
  function isModifierRequired (line 2870) | function isModifierRequired(modifiers, requestingName, requestedName) {
  function arrow (line 2895) | function arrow(data, options) {
  function getOppositeVariation (line 2977) | function getOppositeVariation(variation) {
  function clockwise (line 3032) | function clockwise(placement) {
  function flip (line 3053) | function flip(data, options) {
  function keepTogether (line 3143) | function keepTogether(data) {
  function toValue (line 3177) | function toValue(str, measurement, popperOffsets, referenceOffsets) {
  function parseOffset (line 3229) | function parseOffset(offset, popperOffsets, referenceOffsets, basePlacem...
  function offset (line 3305) | function offset(data, _ref) {
  function preventOverflow (line 3346) | function preventOverflow(data, options) {
  function shift (line 3417) | function shift(data) {
  function hide (line 3450) | function hide(data) {
  function inner (line 3488) | function inner(data) {
  function Popper (line 3939) | function Popper(reference, popper) {
  function Dropdown (line 4169) | function Dropdown(element, config) {
  function Modal (line 4674) | function Modal(element, config) {
  function allowedAttribute (line 5247) | function allowedAttribute(attr, allowedAttributeList) {
  function sanitizeHtml (line 5271) | function sanitizeHtml(unsafeHtml, whiteList, sanitizeFn) {
  function Tooltip (line 5408) | function Tooltip(element, config) {
  function Popover (line 6086) | function Popover() {
  function ScrollSpy (line 6273) | function ScrollSpy(element, config) {
  function Tab (line 6568) | function Tab(element) {
  function Toast (line 6805) | function Toast(element, config) {

FILE: reCAPTCHA.AspNetCore.Example/wwwroot/lib/bootstrap/dist/js/bootstrap.js
  function _defineProperties (line 15) | function _defineProperties(target, props) {
  function _createClass (line 25) | function _createClass(Constructor, protoProps, staticProps) {
  function _defineProperty (line 31) | function _defineProperty(obj, key, value) {
  function _objectSpread (line 46) | function _objectSpread(target) {
  function _inheritsLoose (line 65) | function _inheritsLoose(subClass, superClass) {
  function toType (line 87) | function toType(obj) {
  function getSpecialTransitionEndEvent (line 91) | function getSpecialTransitionEndEvent() {
  function transitionEndEmulator (line 105) | function transitionEndEmulator(duration) {
  function setTransitionEndSupport (line 120) | function setTransitionEndSupport() {
  function Alert (line 261) | function Alert(element) {
  function Button (line 429) | function Button(element) {
  function Carousel (line 636) | function Carousel(element, config) {
  function Collapse (line 1196) | function Collapse(element, config) {
  function Dropdown (line 1591) | function Dropdown(element, config) {
  function Modal (line 2096) | function Modal(element, config) {
  function allowedAttribute (line 2669) | function allowedAttribute(attr, allowedAttributeList) {
  function sanitizeHtml (line 2693) | function sanitizeHtml(unsafeHtml, whiteList, sanitizeFn) {
  function Tooltip (line 2830) | function Tooltip(element, config) {
  function Popover (line 3508) | function Popover() {
  function ScrollSpy (line 3695) | function ScrollSpy(element, config) {
  function Tab (line 3990) | function Tab(element) {
  function Toast (line 4227) | function Toast(element, config) {

FILE: reCAPTCHA.AspNetCore.Example/wwwroot/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.js
  function setValidationValues (line 25) | function setValidationValues(options, ruleName, value) {
  function splitAndTrim (line 32) | function splitAndTrim(value) {
  function escapeAttributeValue (line 36) | function escapeAttributeValue(value) {
  function getModelPrefix (line 41) | function getModelPrefix(fieldName) {
  function appendModelPrefix (line 45) | function appendModelPrefix(value, prefix) {
  function onError (line 52) | function onError(error, inputElement) {  // 'this' is the form element
  function onErrors (line 69) | function onErrors(event, validator) {  // 'this' is the form element
  function onSuccess (line 83) | function onSuccess(error) {  // 'this' is the form element
  function onReset (line 99) | function onReset(event) {  // 'this' is the form element
  function validationInfo (line 124) | function validationInfo(form) {

FILE: reCAPTCHA.AspNetCore.Example/wwwroot/lib/jquery-validation/dist/additional-methods.js
  function stripHtml (line 21) | function stripHtml( value ) {
  function isOdd (line 212) | function isOdd( n ) {

FILE: reCAPTCHA.AspNetCore.Example/wwwroot/lib/jquery-validation/dist/jquery.validate.js
  function handle (line 70) | function handle() {
  function delegate (line 411) | function delegate( event ) {

FILE: reCAPTCHA.AspNetCore.Example/wwwroot/lib/jquery/dist/jquery.js
  function DOMEval (line 107) | function DOMEval( code, node, doc ) {
  function toType (line 137) | function toType( obj ) {
  function isArrayLike (line 507) | function isArrayLike( obj ) {
  function Sizzle (line 759) | function Sizzle( selector, context, results, seed ) {
  function createCache (line 907) | function createCache() {
  function markFunction (line 927) | function markFunction( fn ) {
  function assert (line 936) | function assert( fn ) {
  function addHandle (line 960) | function addHandle( attrs, handler ) {
  function siblingCheck (line 975) | function siblingCheck( a, b ) {
  function createInputPseudo (line 1001) | function createInputPseudo( type ) {
  function createButtonPseudo (line 1012) | function createButtonPseudo( type ) {
  function createDisabledPseudo (line 1023) | function createDisabledPseudo( disabled ) {
  function createPositionalPseudo (line 1079) | function createPositionalPseudo( fn ) {
  function testContext (line 1102) | function testContext( context ) {
  function setFilters (line 2313) | function setFilters() {}
  function toSelector (line 2387) | function toSelector( tokens ) {
  function addCombinator (line 2397) | function addCombinator( matcher, combinator, base ) {
  function elementMatcher (line 2464) | function elementMatcher( matchers ) {
  function multipleContexts (line 2478) | function multipleContexts( selector, contexts, results ) {
  function condense (line 2487) | function condense( unmatched, map, filter, context, xml ) {
  function setMatcher (line 2508) | function setMatcher( preFilter, selector, matcher, postFilter, postFinde...
  function matcherFromTokens (line 2608) | function matcherFromTokens( tokens ) {
  function matcherFromGroupMatchers (line 2671) | function matcherFromGroupMatchers( elementMatchers, setMatchers ) {
  function nodeName (line 3029) | function nodeName( elem, name ) {
  function winnow (line 3039) | function winnow( elements, qualifier, not ) {
  function sibling (line 3334) | function sibling( cur, dir ) {
  function createOptions (line 3427) | function createOptions( options ) {
  function Identity (line 3652) | function Identity( v ) {
  function Thrower (line 3655) | function Thrower( ex ) {
  function adoptValue (line 3659) | function adoptValue( value, resolve, reject, noValue ) {
  function resolve (line 3752) | function resolve( depth, deferred, handler, special ) {
  function completed (line 4117) | function completed() {
  function fcamelCase (line 4212) | function fcamelCase( _all, letter ) {
  function camelCase (line 4219) | function camelCase( string ) {
  function Data (line 4236) | function Data() {
  function getData (line 4405) | function getData( data ) {
  function dataAttr (line 4430) | function dataAttr( elem, key, data ) {
  function adjustCSS (line 4742) | function adjustCSS( elem, prop, valueParts, tween ) {
  function getDefaultDisplay (line 4810) | function getDefaultDisplay( elem ) {
  function showHide (line 4833) | function showHide( elements, show ) {
  function getAll (line 4965) | function getAll( context, tag ) {
  function setGlobalEval (line 4990) | function setGlobalEval( elems, refElements ) {
  function buildFragment (line 5006) | function buildFragment( elems, context, scripts, selection, ignored ) {
  function returnTrue (line 5098) | function returnTrue() {
  function returnFalse (line 5102) | function returnFalse() {
  function expectSync (line 5112) | function expectSync( elem, type ) {
  function safeActiveElement (line 5119) | function safeActiveElement() {
  function on (line 5125) | function on( elem, types, selector, data, fn, one ) {
  function leverageNative (line 5613) | function leverageNative( el, type, expectSync ) {
  function manipulationTarget (line 5962) | function manipulationTarget( elem, content ) {
  function disableScript (line 5973) | function disableScript( elem ) {
  function restoreScript (line 5977) | function restoreScript( elem ) {
  function cloneCopyEvent (line 5987) | function cloneCopyEvent( src, dest ) {
  function fixInput (line 6020) | function fixInput( src, dest ) {
  function domManip (line 6033) | function domManip( collection, args, callback, ignored ) {
  function remove (line 6125) | function remove( elem, selector, keepData ) {
  function computeStyleTests (line 6439) | function computeStyleTests() {
  function roundPixelMeasures (line 6483) | function roundPixelMeasures( measure ) {
  function curCSS (line 6576) | function curCSS( elem, name, computed ) {
  function addGetHookIf (line 6629) | function addGetHookIf( conditionFn, hookFn ) {
  function vendorPropName (line 6654) | function vendorPropName( name ) {
  function finalPropName (line 6669) | function finalPropName( name ) {
  function setPositiveNumber (line 6695) | function setPositiveNumber( _elem, value, subtract ) {
  function boxModelAdjustment (line 6707) | function boxModelAdjustment( elem, dimension, box, isBorderBox, styles, ...
  function getWidthOrHeight (line 6775) | function getWidthOrHeight( elem, dimension, extra ) {
  function Tween (line 7151) | function Tween( elem, options, prop, end, easing ) {
  function schedule (line 7274) | function schedule() {
  function createFxNow (line 7287) | function createFxNow() {
  function genFx (line 7295) | function genFx( type, includeWidth ) {
  function createTween (line 7315) | function createTween( value, prop, animation ) {
  function defaultPrefilter (line 7329) | function defaultPrefilter( elem, props, opts ) {
  function propFilter (line 7501) | function propFilter( props, specialEasing ) {
  function Animation (line 7538) | function Animation( elem, properties, options ) {
  function stripAndCollapse (line 8254) | function stripAndCollapse( value ) {
  function getClass (line 8260) | function getClass( elem ) {
  function classesToArray (line 8264) | function classesToArray( value ) {
  function buildParams (line 8894) | function buildParams( prefix, obj, traditional, add ) {
  function addToPrefiltersOrTransports (line 9047) | function addToPrefiltersOrTransports( structure ) {
  function inspectPrefiltersOrTransports (line 9081) | function inspectPrefiltersOrTransports( structure, options, originalOpti...
  function ajaxExtend (line 9110) | function ajaxExtend( target, src ) {
  function ajaxHandleResponses (line 9130) | function ajaxHandleResponses( s, jqXHR, responses ) {
  function ajaxConvert (line 9188) | function ajaxConvert( s, response, jqXHR, isSuccess ) {
  function done (line 9704) | function done( status, nativeStatusText, responses, headers ) {

FILE: reCAPTCHA.AspNetCore/Attributes/RecaptchaResponseAttribute.cs
  class RecaptchaResponseAttribute (line 13) | [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Property |...
    method IsValid (line 39) | protected override ValidationResult IsValid(object value, ValidationCo...

FILE: reCAPTCHA.AspNetCore/Attributes/ValidateRecaptchaAttribute.cs
  class ValidateRecaptchaAttribute (line 11) | [AttributeUsage(AttributeTargets.Method, Inherited = false)]
    method ValidateRecaptchaAttribute (line 24) | public ValidateRecaptchaAttribute(double score = 0, string errorMessag...
    method CreateInstance (line 30) | public IFilterMetadata CreateInstance(IServiceProvider services)

FILE: reCAPTCHA.AspNetCore/Attributes/ValidateRecaptchaFilter.cs
  class ValidateRecaptchaFilter (line 7) | public class ValidateRecaptchaFilter : IAsyncActionFilter
    method ValidateRecaptchaFilter (line 13) | public ValidateRecaptchaFilter(IRecaptchaService recaptcha, double min...
    method OnActionExecutionAsync (line 20) | public async Task OnActionExecutionAsync(ActionExecutingContext contex...

FILE: reCAPTCHA.AspNetCore/CodeDom.cs
  class CompilerError (line 5) | public class CompilerError
  class CompilerErrorCollection (line 11) | public class CompilerErrorCollection : List<CompilerError>

FILE: reCAPTCHA.AspNetCore/IRecaptchaService.cs
  type IRecaptchaService (line 9) | public interface IRecaptchaService
    method Validate (line 11) | Task<RecaptchaResponse> Validate(HttpRequest request, bool antiForgery...
    method Validate (line 13) | Task<RecaptchaResponse> Validate(string responseCode);

FILE: reCAPTCHA.AspNetCore/RecaptchaHelper.cs
  class RecaptchaHelper (line 8) | public static class RecaptchaHelper
    method Recaptcha (line 17) | public static HtmlString Recaptcha<T>(this IHtmlHelper helper, Recaptc...

FILE: reCAPTCHA.AspNetCore/RecaptchaResponse.cs
  class RecaptchaResponse (line 5) | public class RecaptchaResponse
    method RecaptchaResponse (line 8) | public RecaptchaResponse(bool success)

FILE: reCAPTCHA.AspNetCore/RecaptchaService.cs
  class RecaptchaService (line 10) | public class RecaptchaService : IRecaptchaService
    method RecaptchaService (line 16) | public RecaptchaService(IOptions<RecaptchaSettings> options, ILogger<R...
    method Validate (line 22) | public async Task<RecaptchaResponse> Validate(HttpRequest request, boo...
    method Validate (line 45) | public async Task<RecaptchaResponse> Validate(string responseCode)

FILE: reCAPTCHA.AspNetCore/RecaptchaServiceCollection.cs
  class RecaptchaServiceCollection (line 11) | public static class RecaptchaServiceCollection
    method AddRecaptcha (line 19) | public static IServiceCollection AddRecaptcha(this IServiceCollection ...
    method AddRecaptcha (line 42) | public static IServiceCollection AddRecaptcha(this IServiceCollection ...

FILE: reCAPTCHA.AspNetCore/RecaptchaSettings.cs
  class RecaptchaSettings (line 3) | public class RecaptchaSettings

FILE: reCAPTCHA.AspNetCore/Templates/RecaptchaV2CheckboxModelBinder.cs
  class RecaptchaV2Checkbox (line 7) | public partial class RecaptchaV2Checkbox
    method RecaptchaV2Checkbox (line 11) | public RecaptchaV2Checkbox(Versions.RecaptchaV2Checkbox model)

FILE: reCAPTCHA.AspNetCore/Templates/RecaptchaV2InvisibleModelBinder.cs
  class RecaptchaV2Invisible (line 7) | public partial class RecaptchaV2Invisible
    method RecaptchaV2Invisible (line 11) | public RecaptchaV2Invisible(Versions.RecaptchaV2Invisible model)

FILE: reCAPTCHA.AspNetCore/Templates/RecaptchaV3HiddenInput.cs
  method TransformText (line 29) | public virtual string TransformText()

FILE: reCAPTCHA.AspNetCore/Templates/RecaptchaV3HiddenInputModelBinder.cs
  class RecaptchaV3HiddenInput (line 7) | public partial class RecaptchaV3HiddenInput
    method RecaptchaV3HiddenInput (line 11) | public RecaptchaV3HiddenInput(Versions.RecaptchaV3HiddenInput model)

FILE: reCAPTCHA.AspNetCore/Versions/RecaptchaV2Checkbox.cs
  class RecaptchaV2Checkbox (line 3) | public class RecaptchaV2Checkbox : RecaptchaVersion

FILE: reCAPTCHA.AspNetCore/Versions/RecaptchaV2Invisible.cs
  class RecaptchaV2Invisible (line 7) | public class RecaptchaV2Invisible : RecaptchaVersion

FILE: reCAPTCHA.AspNetCore/Versions/RecaptchaV3HiddenInput.cs
  class RecaptchaV3HiddenInput (line 7) | public class RecaptchaV3HiddenInput : RecaptchaVersion

FILE: reCAPTCHA.AspNetCore/Versions/RecaptchaVersion.cs
  class RecaptchaVersion (line 10) | public class RecaptchaVersion
Condensed preview — 67 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (1,232K chars).
[
  {
    "path": ".gitignore",
    "chars": 4860,
    "preview": "## Ignore Visual Studio temporary files, build results, and\n## files generated by popular Visual Studio add-ons.\n##\n## G"
  },
  {
    "path": "CODE_OF_CONDUCT.md",
    "chars": 3358,
    "preview": "# Contributor Covenant Code of Conduct\n\n## Our Pledge\n\nIn the interest of fostering an open and welcoming environment, w"
  },
  {
    "path": "CONTRIBUTING.md",
    "chars": 928,
    "preview": "*First off, thanks for taking the time to contribute!*\n\n# Features\n\nThe purpose of this library is to create an inclusiv"
  },
  {
    "path": "LICENSE",
    "chars": 1080,
    "preview": "MIT License\n\nCopyright (c) 2017 Timothy \"Ravun\" Meadows\n\nPermission is hereby granted, free of charge, to any person obt"
  },
  {
    "path": "README.md",
    "chars": 7073,
    "preview": "# reCAPTCHA.AspNetCore\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/lic"
  },
  {
    "path": "reCAPTCHA.AspNetCore/Attributes/RecaptchaResponseAttribute.cs",
    "chars": 2482,
    "preview": "using System;\nusing System.ComponentModel.DataAnnotations;\nusing System.Configuration;\nusing Microsoft.Extensions.Depen"
  },
  {
    "path": "reCAPTCHA.AspNetCore/Attributes/ValidateRecaptchaAttribute.cs",
    "chars": 1451,
    "preview": "using System;\nusing Microsoft.AspNetCore.Mvc.Filters;\nusing Microsoft.Extensions.DependencyInjection;\n\nnamespace reCAPT"
  },
  {
    "path": "reCAPTCHA.AspNetCore/Attributes/ValidateRecaptchaFilter.cs",
    "chars": 1022,
    "preview": "using System;\nusing System.Threading.Tasks;\nusing Microsoft.AspNetCore.Mvc.Filters;\n\nnamespace reCAPTCHA.AspNetCore.Att"
  },
  {
    "path": "reCAPTCHA.AspNetCore/CodeDom.cs",
    "chars": 387,
    "preview": "using System.Collections.Generic;\n\nnamespace System.CodeDom.Compiler\n{\n    public class CompilerError\n    {\n        pub"
  },
  {
    "path": "reCAPTCHA.AspNetCore/IRecaptchaService.cs",
    "chars": 370,
    "preview": "using System;\nusing System.Collections.Generic;\nusing System.Text;\nusing System.Threading.Tasks;\nusing Microsoft.AspNet"
  },
  {
    "path": "reCAPTCHA.AspNetCore/RecaptchaHelper.cs",
    "chars": 2768,
    "preview": "using System;\nusing Microsoft.AspNetCore.Html;\nusing Microsoft.AspNetCore.Mvc.Rendering;\nusing reCAPTCHA.AspNetCore.Ver"
  },
  {
    "path": "reCAPTCHA.AspNetCore/RecaptchaResponse.cs",
    "chars": 426,
    "preview": "using System;\n\nnamespace reCAPTCHA.AspNetCore\n{\n    public class RecaptchaResponse\n    {\n\n        public RecaptchaRespo"
  },
  {
    "path": "reCAPTCHA.AspNetCore/RecaptchaService.cs",
    "chars": 2546,
    "preview": "using Microsoft.AspNetCore.Http;\nusing Microsoft.Extensions.Logging;\nusing Microsoft.Extensions.Options;\nusing System.N"
  },
  {
    "path": "reCAPTCHA.AspNetCore/RecaptchaServiceCollection.cs",
    "chars": 2328,
    "preview": "using Microsoft.Extensions.Configuration;\nusing Microsoft.Extensions.DependencyInjection;\nusing System;\nusing Microsoft"
  },
  {
    "path": "reCAPTCHA.AspNetCore/RecaptchaSettings.cs",
    "chars": 1139,
    "preview": "namespace reCAPTCHA.AspNetCore\n{\n    public class RecaptchaSettings\n    {\n        /// <summary>\n        /// Google Reca"
  },
  {
    "path": "reCAPTCHA.AspNetCore/Templates/RecaptchaV2Checkbox.cs",
    "chars": 22590,
    "preview": "// ------------------------------------------------------------------------------\n// <auto-generated>\n//     This code "
  },
  {
    "path": "reCAPTCHA.AspNetCore/Templates/RecaptchaV2Checkbox.tt",
    "chars": 1674,
    "preview": "<#@ template language=\"C#\" #>\n<#@ assembly name=\"System.Core\" #>\n\n<div id=\"<#= Model.Uid #>\" class=\"g-recaptcha\" data-s"
  },
  {
    "path": "reCAPTCHA.AspNetCore/Templates/RecaptchaV2CheckboxModelBinder.cs",
    "chars": 929,
    "preview": "using System;\nusing System.Collections.Generic;\nusing System.Text;\n\nnamespace reCAPTCHA.AspNetCore.Templates\n{\n    publ"
  },
  {
    "path": "reCAPTCHA.AspNetCore/Templates/RecaptchaV2Invisible.cs",
    "chars": 20625,
    "preview": "// ------------------------------------------------------------------------------\n// <auto-generated>\n//     This code "
  },
  {
    "path": "reCAPTCHA.AspNetCore/Templates/RecaptchaV2Invisible.tt",
    "chars": 1656,
    "preview": "<#@ template language=\"C#\" #>\n<#@ assembly name=\"System.Core\" #>\n<#@ import namespace=\"System.Linq\" #>\n<#@ import names"
  },
  {
    "path": "reCAPTCHA.AspNetCore/Templates/RecaptchaV2InvisibleModelBinder.cs",
    "chars": 832,
    "preview": "using System;\nusing System.Collections.Generic;\nusing System.Text;\n\nnamespace reCAPTCHA.AspNetCore.Templates\n{\n    publ"
  },
  {
    "path": "reCAPTCHA.AspNetCore/Templates/RecaptchaV3HiddenInput.cs",
    "chars": 17491,
    "preview": "// ------------------------------------------------------------------------------\n// <auto-generated>\n//     This code "
  },
  {
    "path": "reCAPTCHA.AspNetCore/Templates/RecaptchaV3HiddenInput.tt",
    "chars": 1207,
    "preview": "<#@ template language=\"C#\" #>\n<#@ assembly name=\"System.Core\" #>\n<#@ import namespace=\"System.Linq\" #>\n<#@ import names"
  },
  {
    "path": "reCAPTCHA.AspNetCore/Templates/RecaptchaV3HiddenInputModelBinder.cs",
    "chars": 854,
    "preview": "using System;\nusing System.Collections.Generic;\nusing System.Text;\n\nnamespace reCAPTCHA.AspNetCore.Templates\n{\n    publ"
  },
  {
    "path": "reCAPTCHA.AspNetCore/Versions/RecaptchaV2Checkbox.cs",
    "chars": 374,
    "preview": "namespace reCAPTCHA.AspNetCore.Versions\n{\n    public class RecaptchaV2Checkbox : RecaptchaVersion\n    {\n        public "
  },
  {
    "path": "reCAPTCHA.AspNetCore/Versions/RecaptchaV2Invisible.cs",
    "chars": 390,
    "preview": "using System;\nusing System.Collections.Generic;\nusing System.Text;\n\nnamespace reCAPTCHA.AspNetCore.Versions\n{\n    publi"
  },
  {
    "path": "reCAPTCHA.AspNetCore/Versions/RecaptchaV3HiddenInput.cs",
    "chars": 356,
    "preview": "using System;\nusing System.Collections.Generic;\nusing System.Text;\n\nnamespace reCAPTCHA.AspNetCore.Versions\n{\n    publi"
  },
  {
    "path": "reCAPTCHA.AspNetCore/Versions/RecaptchaVersion.cs",
    "chars": 516,
    "preview": "using System;\nusing System.Collections.Generic;\nusing System.Text;\n\nnamespace reCAPTCHA.AspNetCore.Versions\n{\n    /// <"
  },
  {
    "path": "reCAPTCHA.AspNetCore/reCAPTCHA.AspNetCore.csproj",
    "chars": 2371,
    "preview": "<Project Sdk=\"Microsoft.NET.Sdk\">\n\n  <PropertyGroup>\n    <TargetFramework>netcoreapp3.1</TargetFramework>\n    <GenerateP"
  },
  {
    "path": "reCAPTCHA.AspNetCore.Example/Controllers/HomeController.cs",
    "chars": 3045,
    "preview": "using System.Diagnostics;\nusing System.Threading.Tasks;\nusing Microsoft.AspNetCore.Mvc;\nusing reCAPTCHA.AspNetCore.Attr"
  },
  {
    "path": "reCAPTCHA.AspNetCore.Example/Controllers/SomeAPIControlelr.cs",
    "chars": 741,
    "preview": "using Microsoft.AspNetCore.Mvc;\nusing reCAPTCHA.AspNetCore.Attributes;\nusing reCAPTCHA.AspNetCore.Example.Models;\nusing"
  },
  {
    "path": "reCAPTCHA.AspNetCore.Example/Models/Contact4Model.cs",
    "chars": 288,
    "preview": "using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Threading.Tasks;\n\nnamespace reCAPTCHA.A"
  },
  {
    "path": "reCAPTCHA.AspNetCore.Example/Models/ContactModel.cs",
    "chars": 235,
    "preview": "using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Threading.Tasks;\n\nnamespace reCAPTCHA.A"
  },
  {
    "path": "reCAPTCHA.AspNetCore.Example/Models/ErrorViewModel.cs",
    "chars": 227,
    "preview": "using System;\n\nnamespace reCAPTCHA.AspNetCore.Example.Models\n{\n    public class ErrorViewModel\n    {\n        public stri"
  },
  {
    "path": "reCAPTCHA.AspNetCore.Example/Models/OtherModel.cs",
    "chars": 237,
    "preview": "using reCAPTCHA.AspNetCore.Attributes;\n\nnamespace reCAPTCHA.AspNetCore.Example.Models\n{\n    public class OtherModel\n   "
  },
  {
    "path": "reCAPTCHA.AspNetCore.Example/Program.cs",
    "chars": 710,
    "preview": "using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Threading.Tasks;\nusing Microsoft.AspNetC"
  },
  {
    "path": "reCAPTCHA.AspNetCore.Example/Startup.cs",
    "chars": 1971,
    "preview": "using Microsoft.AspNetCore.Builder;\nusing Microsoft.AspNetCore.Hosting;\nusing Microsoft.Extensions.Configuration;\nusing "
  },
  {
    "path": "reCAPTCHA.AspNetCore.Example/Views/Home/Contact.cshtml",
    "chars": 1228,
    "preview": "@using reCAPTCHA.AspNetCore\n@using reCAPTCHA.AspNetCore.Versions;\n@using Microsoft.Extensions.Options\n\n@model ContactMo"
  },
  {
    "path": "reCAPTCHA.AspNetCore.Example/Views/Home/Contact2.cshtml",
    "chars": 1279,
    "preview": "@using reCAPTCHA.AspNetCore\n@using reCAPTCHA.AspNetCore.Versions;\n@using Microsoft.Extensions.Options\n\n@model ContactMo"
  },
  {
    "path": "reCAPTCHA.AspNetCore.Example/Views/Home/Contact3.cshtml",
    "chars": 1609,
    "preview": "@using reCAPTCHA.AspNetCore\n@using reCAPTCHA.AspNetCore.Versions;\n@using Microsoft.Extensions.Options\n\n@model ContactMo"
  },
  {
    "path": "reCAPTCHA.AspNetCore.Example/Views/Home/Contact4.cshtml",
    "chars": 2053,
    "preview": "@using reCAPTCHA.AspNetCore\n@using reCAPTCHA.AspNetCore.Versions;\n@using Microsoft.Extensions.Options\n\n@model ContactMo"
  },
  {
    "path": "reCAPTCHA.AspNetCore.Example/Views/Home/Index.cshtml",
    "chars": 229,
    "preview": "@{\n    ViewData[\"Title\"] = \"Home Page\";\n}\n\n<div class=\"text-center\">\n    <h1 class=\"display-4\">Welcome</h1>\n    <p>Lear"
  },
  {
    "path": "reCAPTCHA.AspNetCore.Example/Views/Home/Privacy.cshtml",
    "chars": 136,
    "preview": "@{\n    ViewData[\"Title\"] = \"Privacy Policy\";\n}\n<h1>@ViewData[\"Title\"]</h1>\n\n<p>Use this page to detail your site's priv"
  },
  {
    "path": "reCAPTCHA.AspNetCore.Example/Views/Shared/Error.cshtml",
    "chars": 857,
    "preview": "@model ErrorViewModel\n@{\n    ViewData[\"Title\"] = \"Error\";\n}\n\n<h1 class=\"text-danger\">Error.</h1>\n<h2 class=\"text-danger"
  },
  {
    "path": "reCAPTCHA.AspNetCore.Example/Views/Shared/_Layout.cshtml",
    "chars": 2853,
    "preview": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"utf-8\" />\n    <meta name=\"viewport\" content=\"width=device-wi"
  },
  {
    "path": "reCAPTCHA.AspNetCore.Example/Views/Shared/_ValidationScriptsPartial.cshtml",
    "chars": 172,
    "preview": "<script src=\"~/lib/jquery-validation/dist/jquery.validate.min.js\"></script>\n<script src=\"~/lib/jquery-validation-unobtr"
  },
  {
    "path": "reCAPTCHA.AspNetCore.Example/Views/_ViewImports.cshtml",
    "chars": 133,
    "preview": "@using reCAPTCHA.AspNetCore.Example\n@using reCAPTCHA.AspNetCore.Example.Models\n@addTagHelper *, Microsoft.AspNetCore.Mv"
  },
  {
    "path": "reCAPTCHA.AspNetCore.Example/Views/_ViewStart.cshtml",
    "chars": 30,
    "preview": "@{\n    Layout = \"_Layout\";\n}\n"
  },
  {
    "path": "reCAPTCHA.AspNetCore.Example/appsettings.Development.json",
    "chars": 159,
    "preview": "{\n  \"Logging\": {\n    \"LogLevel\": {\n      \"Default\": \"Information\",\n      \"Microsoft\": \"Warning\",\n      \"Microsoft.Hostin"
  },
  {
    "path": "reCAPTCHA.AspNetCore.Example/appsettings.json",
    "chars": 331,
    "preview": "{\n  \"Logging\": {\n    \"LogLevel\": {\n      \"Default\": \"Information\",\n      \"Microsoft\": \"Warning\",\n      \"Microsoft.Hostin"
  },
  {
    "path": "reCAPTCHA.AspNetCore.Example/reCAPTCHA.AspNetCore.Example.csproj",
    "chars": 256,
    "preview": "<Project Sdk=\"Microsoft.NET.Sdk.Web\">\n\n  <PropertyGroup>\n    <TargetFramework>netcoreapp3.1</TargetFramework>\n  </Proper"
  },
  {
    "path": "reCAPTCHA.AspNetCore.Example/wwwroot/css/site.css",
    "chars": 1344,
    "preview": "/* Please see documentation at https://docs.microsoft.com/aspnet/core/client-side/bundling-and-minification\nfor details"
  },
  {
    "path": "reCAPTCHA.AspNetCore.Example/wwwroot/js/site.js",
    "chars": 224,
    "preview": "// Please see documentation at https://docs.microsoft.com/aspnet/core/client-side/bundling-and-minification\n// for deta"
  },
  {
    "path": "reCAPTCHA.AspNetCore.Example/wwwroot/lib/bootstrap/LICENSE",
    "chars": 1131,
    "preview": "The MIT License (MIT)\n\nCopyright (c) 2011-2018 Twitter, Inc.\nCopyright (c) 2011-2018 The Bootstrap Authors\n\nPermission i"
  },
  {
    "path": "reCAPTCHA.AspNetCore.Example/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.css",
    "chars": 64548,
    "preview": "/*!\n * Bootstrap Grid v4.3.1 (https://getbootstrap.com/)\n * Copyright 2011-2019 The Bootstrap Authors\n * Copyright 2011-"
  },
  {
    "path": "reCAPTCHA.AspNetCore.Example/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.css",
    "chars": 4897,
    "preview": "/*!\n * Bootstrap Reboot v4.3.1 (https://getbootstrap.com/)\n * Copyright 2011-2019 The Bootstrap Authors\n * Copyright 201"
  },
  {
    "path": "reCAPTCHA.AspNetCore.Example/wwwroot/lib/bootstrap/dist/css/bootstrap.css",
    "chars": 192348,
    "preview": "/*!\n * Bootstrap v4.3.1 (https://getbootstrap.com/)\n * Copyright 2011-2019 The Bootstrap Authors\n * Copyright 2011-2019 "
  },
  {
    "path": "reCAPTCHA.AspNetCore.Example/wwwroot/lib/bootstrap/dist/js/bootstrap.bundle.js",
    "chars": 222909,
    "preview": "/*!\n  * Bootstrap v4.3.1 (https://getbootstrap.com/)\n  * Copyright 2011-2019 The Bootstrap Authors (https://github.com/t"
  },
  {
    "path": "reCAPTCHA.AspNetCore.Example/wwwroot/lib/bootstrap/dist/js/bootstrap.js",
    "chars": 131637,
    "preview": "/*!\n  * Bootstrap v4.3.1 (https://getbootstrap.com/)\n  * Copyright 2011-2019 The Bootstrap Authors (https://github.com/t"
  },
  {
    "path": "reCAPTCHA.AspNetCore.Example/wwwroot/lib/jquery/LICENSE.txt",
    "chars": 1605,
    "preview": "Copyright JS Foundation and other contributors, https://js.foundation/\n\nThis software consists of voluntary contribution"
  },
  {
    "path": "reCAPTCHA.AspNetCore.Example/wwwroot/lib/jquery/dist/jquery.js",
    "chars": 288580,
    "preview": "/*!\n * jQuery JavaScript Library v3.6.0\n * https://jquery.com/\n *\n * Includes Sizzle.js\n * https://sizzlejs.com/\n *\n * C"
  },
  {
    "path": "reCAPTCHA.AspNetCore.Example/wwwroot/lib/jquery-validation/LICENSE.md",
    "chars": 1094,
    "preview": "The MIT License (MIT)\n=====================\n\nCopyright Jörn Zaefferer\n\nPermission is hereby granted, free of charge, to "
  },
  {
    "path": "reCAPTCHA.AspNetCore.Example/wwwroot/lib/jquery-validation/dist/additional-methods.js",
    "chars": 42006,
    "preview": "/*!\n * jQuery Validation Plugin v1.17.0\n *\n * https://jqueryvalidation.org/\n *\n * Copyright (c) 2017 Jörn Zaefferer\n * R"
  },
  {
    "path": "reCAPTCHA.AspNetCore.Example/wwwroot/lib/jquery-validation/dist/jquery.validate.js",
    "chars": 48675,
    "preview": "/*!\n * jQuery Validation Plugin v1.17.0\n *\n * https://jqueryvalidation.org/\n *\n * Copyright (c) 2017 Jörn Zaefferer\n * R"
  },
  {
    "path": "reCAPTCHA.AspNetCore.Example/wwwroot/lib/jquery-validation-unobtrusive/LICENSE.txt",
    "chars": 575,
    "preview": "Copyright (c) .NET Foundation. All rights reserved.\n\nLicensed under the Apache License, Version 2.0 (the \"License\"); you"
  },
  {
    "path": "reCAPTCHA.AspNetCore.Example/wwwroot/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.js",
    "chars": 19366,
    "preview": "// Unobtrusive validation support library for jQuery and jQuery Validate\n// Copyright (c) .NET Foundation. All rights re"
  },
  {
    "path": "reCAPTCHA.AspNetCore.sln",
    "chars": 1671,
    "preview": "\nMicrosoft Visual Studio Solution File, Format Version 12.00\n# Visual Studio Version 16\nVisualStudioVersion = 16.0.2980"
  }
]

About this extraction

This page contains the full source code of the TimothyMeadows/reCAPTCHA.AspNetCore GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 67 files (1.1 MB), approximately 316.8k tokens, and a symbol index with 268 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!