{"id":28834856,"url":"https://github.com/karthik25/featurify","last_synced_at":"2025-09-19T18:31:31.487Z","repository":{"id":144145500,"uuid":"136962309","full_name":"karthik25/featurify","owner":"karthik25","description":"Implementation of feature Flags that integrates seamlessly with .net core, to handle user specific features easily","archived":false,"fork":false,"pushed_at":"2018-12-03T04:25:53.000Z","size":550,"stargazers_count":7,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-08-20T21:56:23.807Z","etag":null,"topics":["csharp","feature-toggle","nuget"],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/karthik25.png","metadata":{"files":{"readme":"ReadMe.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2018-06-11T18:00:17.000Z","updated_at":"2023-03-05T07:01:24.000Z","dependencies_parsed_at":null,"dependency_job_id":"d478a575-5b3b-4c4d-b1f0-7ea2a4beaabe","html_url":"https://github.com/karthik25/featurify","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/karthik25/featurify","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/karthik25%2Ffeaturify","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/karthik25%2Ffeaturify/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/karthik25%2Ffeaturify/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/karthik25%2Ffeaturify/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/karthik25","download_url":"https://codeload.github.com/karthik25/featurify/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/karthik25%2Ffeaturify/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":274088625,"owners_count":25220260,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-09-07T02:00:09.463Z","response_time":67,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["csharp","feature-toggle","nuget"],"created_at":"2025-06-19T10:01:09.303Z","updated_at":"2025-09-19T18:31:31.479Z","avatar_url":"https://github.com/karthik25.png","language":"C#","readme":"# Featurify\n\n### What is Featurify?\n\nFeaturify is just yet another implementation of feature flags thats super easy to setup and use. It intends to solve one and only one issue where feature flags are user specific.\n\n### Background\n\nFeaturify is designed to be really light weight and easily integrate with .net core 2.0+ web applications. This is intended to be \none part of a two piece puzzle. If you are interested in simple application settings based feature flags, this library is not for \nyou! There are a number of other options for that purpose (refer to various sections at the end of this file). \n\nFirst part of this puzzle is elaborated in the usage section. Second part of the puzzle is to design a user interface that would \nhelp administrators identify the features, and also tie them to users (step 2 in usage deals with the integration to this part of the puzzle). \n\nThe need for this came up for my project because I found out LaunchDarkly that provides feature flags as a service, but its not \nfree! The not free part let to this package and this would require minimal effort to achieve the same. \n\n### Usage\n\n1. Add the `Featurify` nuget package using the nuget package manager. The `Featurify.Contract` nuget package is also added automatically. If you want to have a seperate project to define `IUserInfoStrategy`, `IToggleMetadataFinder` and other associated classes, you can just add the `Featurify.Contracts` nuget package to that.\n\n2. Create a class (implementing `IUserInfoStrategy`) that would provide the user information for the current user. \n\n```csharp\npublic class DemoAppUserFinderStrategy : IUserInfoStrategy\n{\n   private readonly IHttpContextAccessor accessor;\n\n   public DemoAppUserFinderStrategy(IHttpContextAccessor accessor)\n   {\n      this.accessor = accessor;\n   }\n\n   public async Task\u003cstring\u003e GetCurrentUserId()\n   {\n      // This is just an illustration. In real life you would ideally use the instance of IHttpContextAccessor\n      //      to get the logged in user's user id or email address\n   \n      await Task.CompletedTask;\n      return \"b0486d0f-9114-41a7-a095-e4e92201a41e\";\n   }\n}\n```\n3. (Optional) Create a class that (implementing `IFeatureNameTransformer`) will dictate the format of feature names. Default is `Featurify.{featureName}`\n\n4. Create a class  (implementing `IToggleMetadataFinder`) that would provide the metadata for the feature for a/all specific user(s)\n\n```csharp\npublic class DemoAppFeatureMetadataFinder: IToggleMetadataFinder\n{\n    private readonly IAppDbContext dbContext;\n\n    public DemoAppFeatureMetadataFinder(IAppDbContext dbContext)\n    {\n        this.dbContext = dbContext;\n    }\n\n    public async Task\u003cIToggleMetadata\u003e FindToggleStatus(string featureName, string userId)\n    {\n        // This is just an illustration. In real life you would use a data context to identify the feature toggle\n        //      status for the user\n        //   featureName =\u003e the transformed feature name based on your initial setup\n\t//                  default is \"Featurify.{featureName}\"\n        //   userId =\u003e this will be logged in user's id identified by your IUserInfoStrategy instance\n    \n        await Task.CompletedTask;\n        var metadata = new Toggle\n        {\n            Name = featureName,\n            Value = featureName.Contains(\"ImportFeature\") ? true : false,\n            UserId = \"?\" // Indicates any user, see step 5 for more details\n        };\n        return metadata;\n     }\n}\n\npublic class Toggle : IToggleMetadata\n{\n     public string Name { get; set; }\n     public bool Value { get; set; }\n     public string UserId { get; set; }\n}\n```\n\n5. Add the featurify service in Startup.cs\n\n```csharp\npublic void ConfigureServices(IServiceCollection services)\n{\n    services.AddMvc();\n\n    services.AddFeaturify\u003cDemoAppFeatureMetadataFinder, DemoAppUserFinderStrategy\u003e(options =\u003e\n    {\n\t// Identifier if a feature is common for all users\n        options.AnyUserVerifier = \"?\"; \n\t// If this is set to true, and a match is not found through IToggleMetadataFinder.FindToggleStatus, an exception will be thrown\n        options.UseStrict = false; \n    });\n}\n```\n\n6. You can now use the package as shown below:\n\n***Use it in the controller***\n\n```csharp\n// Create a class to represent your feature\npublic class ImportFeature : IFeatureToggle\n{\n}\n\npublic class HomeController : Controller\n{\n     private readonly IFeaturifyServer server;\n\n     public HomeController(IFeaturifyServer server)\n     {\n        this.server = server;\n     }\n\n     public async Task\u003cIActionResult\u003e Contact()\n     {\n        ViewData[\"Message\"] = \"Your contact page.\";\n        var model = new ContactViewModel\n           {\n               CanImport = await server.Is\u003cImportFeature\u003e().Enabled() // Verify if the feature is enabled\n           };\n         return View(model);\n      }\n}\n```\n\n   (or)\n\n***Use it in the views***\n\n```csharp\n// Create a class to represent your feature\npublic class ExportFeature : IFeatureToggle\n{\n}\n```\n\nUse it in a view by injecting an instance of `IFeaturifyServer`\n\n```html\n@using Featurify\n@using Featurify.Contracts\n@using Featurify.Demo.Features\n\n@inject IFeaturifyServer Featurify\n\n@if (await Featurify.Is\u003cExportFeature\u003e().Enabled())\n{\n    \u003cbutton class=\"btn btn-success\"\u003eExport Users\u003c/button\u003e\n}\nelse\n{\n    \u003cbutton class=\"btn btn-danger\" disabled\u003eExport Users\u003c/button\u003e\n}\n```\n\nIn both the cases listed above the `FeaturifyServer` first uses the user strategy to get the unique identifier for the logged in user.\nIf a custom feature name transformer is defined, that is used to transform the feature name. Then, the metadata finder assigned is \nused to find the metadata by passing in the feature name and the user id. In this case, for demo purposes, import feature is turned on\nand the export feature is turned off.\n\n### Note\n\nThere is also a syntactic sugar that you can use when verifying if a feature is enabled for the logged in user. Here is an example:\n\n```html\n@using Featurify\n@using Featurify.Contracts\n@using Featurify.Demo.Features\n\n@inject IFeaturifyServer Featurify\n\n@if (await Featurify.Enabled\u003cExportFeature\u003e())\n{\n    \u003cbutton class=\"btn btn-success\"\u003eExport Users\u003c/button\u003e\n}\nelse\n{\n    \u003cbutton class=\"btn btn-danger\" disabled\u003eExport Users\u003c/button\u003e\n}\n```\n\n### More Samples\n\nThere are a few more samples in [this](https://github.com/karthik25/featurify-samples) repository. Check out the sample within ***identity-framework*** for an implementation in a project that uses the identity framework. The toggle metadata is out of a static list though in this case.\n\n### Credits\n\n* Feature Toggle - For the inspiration to eliminate magic strings (https://github.com/jason-roberts/FeatureToggle)\n\n### Simple Feature Toggles Based on Application Settings\n\nIf you are looking for an implementation of feature flags in .net which can be used out of the box with the help of the application settings file, \ncheck out http://enterprisedevops.org/feature-toggle-frameworks-list, where feature toggles for various languages are listed.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkarthik25%2Ffeaturify","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkarthik25%2Ffeaturify","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkarthik25%2Ffeaturify/lists"}