Git Product home page Git Product logo

Comments (10)

mdarefull avatar mdarefull commented on May 18, 2024 5

@jimmyca15 IMO, this would really increase the value of this library and shouldn't be difficult to implement.

We already implemented a a very simple IAsyncPageFilter with similar implementation provided by @haacked and it's nicely working:

    [AttributeUsage(AttributeTargets.Class)]
    public class RazorPageFeatureGate : Attribute, IAsyncPageFilter
    {
        private string Feature { get; }
        public RazorPageFeatureGate(string feature)
            => Feature = feature;

        public virtual async Task OnPageHandlerExecutionAsync(PageHandlerExecutingContext context, PageHandlerExecutionDelegate next)
        {
            var fm = context.HttpContext.RequestServices.GetRequiredService<IFeatureManagerSnapshot>();
            var isEnabled = await fm.IsEnabledAsync(Feature).ConfigureAwait(false);
            if (isEnabled)
            {
                await next.Invoke().ConfigureAwait(false);
            }
            else
            {
                context.HttpContext.Response.StatusCode = 404;
                await context.HttpContext.Response.CompleteAsync().ConfigureAwait(false);
            }
        }

        public virtual Task OnPageHandlerSelectionAsync(PageHandlerSelectedContext context) => Task.CompletedTask;
    }

from featuremanagement-dotnet.

haacked avatar haacked commented on May 18, 2024 3

Just as a follow-up, I hacked up a proof of concept to show this would work.

[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
public class FeatureToggleAttribute : FeatureGateAttribute
{
    public FeatureToggleAttribute(params string[] features)
        : this(RequirementType.All, features)
    {
    }

    public FeatureToggleAttribute(RequirementType requirementType, params string[] features)
        : base(requirementType, features)
    {
    }

    public FeatureToggleAttribute(RequirementType requirementType, params object[] features)
        : base(requirementType, features)
    {
    }
    
    public FeatureToggleAttribute(params object[] features)
        : this(RequirementType.All, features)
    {
    }

    public override async Task OnResultExecutionAsync(ResultExecutingContext context, ResultExecutionDelegate next)
    {
        var fm = context.HttpContext.RequestServices.GetRequiredService<IFeatureManagerSnapshot>();
        bool flag;
        if (RequirementType == RequirementType.All)
            flag = await Features.All<string>((Func<string, Task<bool>>) (async feature =>
                await fm.IsEnabledAsync(feature).ConfigureAwait(false)));
        else
            flag = await Features.Any<string>((Func<string, Task<bool>>) (async feature =>
                await fm.IsEnabledAsync(feature).ConfigureAwait(false)));
        if (flag)
        {
            await next().ConfigureAwait(false);
        }
        else
        {
            context.HttpContext.Response.StatusCode = 404;
            await context.HttpContext.Response.CompleteAsync();
        }
    }
}

This code makes use of internal classes within this repo that I didn't copy. But it shows that the basic idea would work.

from featuremanagement-dotnet.

jimmyca15 avatar jimmyca15 commented on May 18, 2024 3

This has been released in Microsoft.FeatureManagement.AspNetCore 2.5.0

Documentation update is in the works.

from featuremanagement-dotnet.

MarcWils avatar MarcWils commented on May 18, 2024 1

Calling Complete on the response also disables custom error pages.

context.HttpContext.Response.StatusCode = 404;
await context.HttpContext.Response.CompleteAsync().ConfigureAwait(false);

Wouldn't it be better to avoid page execution by setting the PageHandlerExecutingContext.Result?

context.Result = new NotFoundResult();

from featuremanagement-dotnet.

ArieJones avatar ArieJones commented on May 18, 2024

+1 for this as this is exactly what we were looking at as a solution in one of our apps ..

from featuremanagement-dotnet.

jimmyca15 avatar jimmyca15 commented on May 18, 2024

I spent some time looking into this because I wanted to provide some out of the box support for Razor Pages in the same way that we provide it for MVC controllers. There is an unfortunate difference between supporting controllers via OnActionExecutionAsync and support Razor Pages via OnResultExecutionAsync. OnResultExecutionAsync is invoked after a page handler has already executed. You are correct that this is the only way to declaratively add a handler to a Page Handler. If we wanted to support Razor Pages with just an attribute, we would have to take that route, but the intent of the FeatureGate attribute is to prevent the action/handler from running if the feature is not enabled. Therefore, it looks like support for this may not be a good option with what is available directly out of ASP.NET Core.

I will look a bit more to see if it makes sense to provide a global IPageFilter that can check if a page is decorated with a FeatureGateAttribute and execute it before the handler similar to how it works in an MVC scenario. This may require expensive reflection though and additional boiler plate code on startup to add the global filter.

from featuremanagement-dotnet.

haacked avatar haacked commented on May 18, 2024

Good point on the result execution filter being too late.

Could FeatureGateAttribute itself implement IPageFilter and IAsyncPageFilter?

from featuremanagement-dotnet.

imsaha avatar imsaha commented on May 18, 2024
 services
               .AddRazorPages(options =>
               {
                   ...
                  options.Conventions.AddAreaFolderApplicationModelConvention("Admin", "/Customers", cOption =>
                   {
                       cOption.Filters.Add(new RazorPageFeatureGate(ApplicationFeatureFlags.ManageCustomer));
                   });
               })

Apply feature gate filter to area folder

from featuremanagement-dotnet.

CarlVerret avatar CarlVerret commented on May 18, 2024

We already implemented a a very simple IAsyncPageFilter with similar implementation provided by @haacked and it's nicely working:

I suggest you make a PR from this. Worked like a charm ! Thanks for sharing

from featuremanagement-dotnet.

jimmyca15 avatar jimmyca15 commented on May 18, 2024

Since page filters and action filters are executed in isolation we can add this new functionality in the existing FeatureGateAttribute. I have a sent out a PR #166.

from featuremanagement-dotnet.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.