DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Related

  • GDPR Compliance With .NET: Securing Data the Right Way
  • How to Enhance the Performance of .NET Core Applications for Large Responses
  • Developing Minimal APIs Quickly With Open Source ASP.NET Core
  • Revolutionizing Content Management

Trending

  • Distributed Rate Limiting in Java: A Deep Dive into Bucket4j + PostgreSQL
  • Mastering Fluent Bit: Controlling Logs With Fluent Bit on Kubernetes (Part 4)
  • Multiple File Upload is Easy in HTML5
  • Converting List to String in Terraform
  1. DZone
  2. Coding
  3. Frameworks
  4. Reconfiguring CORS Policy in ASP.NET Core at Runtime

Reconfiguring CORS Policy in ASP.NET Core at Runtime

Have you ever created a runtime version of your app only to realize you needed to change the public properties? Lear how to easily do this with ASP.NET Core.

By 
Tomasz Pęczek user avatar
Tomasz Pęczek
·
Apr. 27, 17 · Tutorial
Likes (2)
Comment
Save
Tweet
Share
11.8K Views

Join the DZone community and get the full member experience.

Join For Free

ASP.NET Core comes with ready to use Cross-Origin Resource Sharing support in the form of Microsoft.AspNetCore.Cors package. The usage is very straightforward, you just need to register the services, configure the policy and enable CORS either with middleware (for a whole pipeline or a specific branch), filter (globally for MVC) or attribute (at the MVC controller/action level). This is all nicely described in the documentation. But what if there is a need to reconfigure the policy at runtime?

Let's assume that there is an application which contains two APIs. One is considered "private" so only other applications from the same suite can use it, while the second is "public" and a client administrator should be able to configure it so it can be used with any 3rd party application.

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddCors(options =>
        {
            options.AddPolicy("Private", builder =>
            {
                builder.WithOrigins("http://appone.suite.com, http://apptwo.suite.com");
                ...
            });

            options.AddPolicy("Public", builder =>
            {
                // Apply "public" policy (based on information read from storage etc.)
                ...
            });
        })
        ...;
    }

    ...
}

The initial configuration of the policy is not an issue, the problem is the part when the admin decides to change the policy. The whole application shouldn't require a restart for changes to take effect, so the policy needs to be accessed and reconfigured.

How the Policy Can Be Accessed

The initialization code shows that the policies are being added to CorsOptions. Internally, the IServiceCollection.AddCors is plugging the options into the ASP.NET Core configuration framework by calling IServiceCollection.Configure. This means that they can be retrieved with the help of Dependency Injection as IOptions and considered a singleton. This is enough information to start building a service which will help with accessing the policy.

public class CorsPolicyAccessor : ICorsPolicyAccessor
{
    private readonly CorsOptions _options;

    public CorsPolicyAccessor(IOptions<CorsOptions> options)
    {
        if (options == null)
        {
            throw new ArgumentNullException(nameof(options));
        }

        _options = options.Value;
    }
}

From this point it's easy. The CorsOptions exposes the GetPolicy method and the DefaultPolicyName property which can be used for exposing access to the policy.

public class CorsPolicyAccessor : ICorsPolicyAccessor
{
    ...

    public CorsPolicy GetPolicy()
    {
        return _options.GetPolicy(_options.DefaultPolicyName);
    }

    public CorsPolicy GetPolicy(string name)
    {
        return _options.GetPolicy(name);
    }
}

Now the new service can be registered (preferably after the AddCors call).

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddCors(options =>
        {
            ...
        })
        .AddTransient<ICorsPolicyAccessor, CorsPolicyAccessor>()
        ...;
    }

    ...
}

Exposing the Policy With MVC

With the help of the newly created ICorsPolicyAccessor service and Dependency Injection, the CORS policy can now be reconfigured at runtime, for example from an ASP.NET Core MVC controller. For starters, let's create an action and view all the lists whose origins are in the Public policy.

public class OriginsController : Controller
{
    private readonly ICorsPolicyAccessor _corsPolicyAccessor;

    public OriginsController(ICorsPolicyAccessor corsPolicyAccessor)
    {
        _corsPolicyAccessor = corsPolicyAccessor;
    }

    [AcceptVerbs("GET")]
    public IActionResult Manage()
    {
        return View(new OriginsModel(_corsPolicyAccessor.GetPolicy("Public").Origins));
    }
}


public class OriginsModel
{
    private readonly IList<string> _origins;

    public IEnumerable<string> Origins => _origins;

    public OriginsModel(IList<string> origins)
    {
        _origins = origins;
    }
}


@model OriginsModel
<!DOCTYPE html>
<html>
...
<body>
    <div>
        <ul>
            @foreach(var origin in Model.Origins)
            { 
                <li>@origin</li>
            }
        </ul>
    </div>
</body>
</html>

Navigating to the URL pointing at the action should result in a list of all the origins. This can be easily extended with the capabilities of adding and removing origins. First, the View Model should be changed so the list of origins can be used to generate a select element.

public class OriginsModel
{
    ...

    public List<SelectListItem> Origins => _origins.Select(origin => new SelectListItem
    {
        Text = origin,
        Value = origin
    }).ToList();

    ...
}

This allows you to add some inputs and forms to handle the operations (this could be done a lot nicer with AJAX but I want to keep things simple for the sake of clarity).

@model OriginsModel
<!DOCTYPE html>
<html>
...
<body>
    <div>
        <ul>
            @foreach(var origin in Model.Origins)
            { 
                <li>@origin.Text</li>
            }
        </ul>
        <form asp-action="Add" method="post">
            <fieldset>
                <legend>Adding an origing</legend>
                <input type="text" name="origin" />
                <input type="submit" value="Add" />
            </fieldset>
        </form>
        <form asp-action="Remove" method="post">
            <fieldset>
                <legend>Removing an origing</legend>
                <select name="origin" asp-items="Model.Origins"></select>
                <input type="submit" value="Remove" />
            </fieldset>
        </form>
    </div>
</body>
</html>

The last thing to do is handling the Add and Remove actions. I'm going to use the PRG Pattern here which should allow a clear separation of responsibilities.

public class OriginsController : Controller
{
    ...

    [AcceptVerbs("POST")]
    public IActionResult Add(string origin)
    {
        _corsPolicyAccessor.GetPolicy("Public").Origins.Add(origin);

        return RedirectToAction(nameof(Manage));
    }

    [AcceptVerbs("POST")]
    public IActionResult Remove(string origin)
    {
        _corsPolicyAccessor.GetPolicy("Public").Origins.Remove(origin);

        return RedirectToAction(nameof(Manage));
    }
}

Testing this will show that, indeed, changes are being picked up immediately (although there is a small risk of a race involved). This simple demo shows how easy it is to reconfigure part of a policy. With this approach, any of CorsPolicy public properties can be changed.

ASP.NET ASP.NET Core

Published at DZone with permission of Tomasz Pęczek. See the original article here.

Opinions expressed by DZone contributors are their own.

Related

  • GDPR Compliance With .NET: Securing Data the Right Way
  • How to Enhance the Performance of .NET Core Applications for Large Responses
  • Developing Minimal APIs Quickly With Open Source ASP.NET Core
  • Revolutionizing Content Management

Partner Resources

×

Comments

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • [email protected]

Let's be friends: