├── .editorconfig ├── .gitattributes ├── .github ├── ISSUE_TEMPLATE │ ├── BUG-REPORT.yml │ ├── ENHANCEMENT.yml │ ├── FEATURE-REQUEST.md │ └── config.yml ├── pull_request_template.md └── workflows │ ├── csharp.yml │ ├── csharp_release.yml │ ├── integration_test.yml │ ├── sonarqube.yml │ ├── source_clear_cron.yml │ └── ticket_reference_check.yml ├── .gitignore ├── CHANGELOG.md ├── CODEOWNERS ├── CONTRIBUTING.md ├── LICENSE ├── OptimizelySDK.DemoApp ├── App_Start │ ├── BundleConfig.cs │ ├── FilterConfig.cs │ └── RouteConfig.cs ├── Content │ ├── Images │ │ ├── item_1.png │ │ ├── item_2.png │ │ ├── item_3.png │ │ ├── item_4.png │ │ ├── item_5.png │ │ ├── item_6.png │ │ ├── item_7.png │ │ ├── item_8.png │ │ └── item_9.png │ ├── Site.css │ ├── bootstrap-grid.css │ ├── bootstrap-grid.css.map │ ├── bootstrap-grid.min.css │ ├── bootstrap-grid.min.css.map │ ├── bootstrap-grid.rtl.css │ ├── bootstrap-grid.rtl.css.map │ ├── bootstrap-grid.rtl.min.css │ ├── bootstrap-grid.rtl.min.css.map │ ├── bootstrap-reboot.css │ ├── bootstrap-reboot.css.map │ ├── bootstrap-reboot.min.css │ ├── bootstrap-reboot.min.css.map │ ├── bootstrap-reboot.rtl.css │ ├── bootstrap-reboot.rtl.css.map │ ├── bootstrap-reboot.rtl.min.css │ ├── bootstrap-reboot.rtl.min.css.map │ ├── bootstrap-utilities.css │ ├── bootstrap-utilities.css.map │ ├── bootstrap-utilities.min.css │ ├── bootstrap-utilities.min.css.map │ ├── bootstrap-utilities.rtl.css │ ├── bootstrap-utilities.rtl.css.map │ ├── bootstrap-utilities.rtl.min.css │ ├── bootstrap-utilities.rtl.min.css.map │ ├── bootstrap.css │ ├── bootstrap.css.map │ ├── bootstrap.min.css │ ├── bootstrap.min.css.map │ ├── bootstrap.rtl.css │ ├── bootstrap.rtl.css.map │ ├── bootstrap.rtl.min.css │ └── bootstrap.rtl.min.css.map ├── Controllers │ ├── DemoController.cs │ └── HomeController.cs ├── Global.asax ├── Global.asax.cs ├── Log4Net.config ├── Models │ ├── Config.cs │ ├── DemoViewModel.cs │ ├── Product.cs │ └── Visitor.cs ├── OptimizelySDK.DemoApp.csproj ├── Properties │ └── AssemblyInfo.cs ├── README.md ├── Scripts │ ├── README.md │ ├── _references.js │ ├── bootstrap.bundle.js │ ├── bootstrap.bundle.js.map │ ├── bootstrap.bundle.min.js │ ├── bootstrap.bundle.min.js.map │ ├── bootstrap.esm.js │ ├── bootstrap.esm.js.map │ ├── bootstrap.esm.min.js │ ├── bootstrap.esm.min.js.map │ ├── bootstrap.js │ ├── bootstrap.js.map │ ├── bootstrap.min.js │ ├── bootstrap.min.js.map │ ├── esm │ │ ├── popper-utils.js │ │ ├── popper-utils.js.map │ │ ├── popper-utils.min.js │ │ ├── popper-utils.min.js.map │ │ ├── popper.js │ │ ├── popper.js.map │ │ ├── popper.min.js │ │ └── popper.min.js.map │ ├── index.d.ts │ ├── jquery-1.10.2.intellisense.js │ ├── jquery-3.7.0.intellisense.js │ ├── jquery-3.7.0.js │ ├── jquery-3.7.0.min.js │ ├── jquery-3.7.0.min.map │ ├── jquery-3.7.0.slim.js │ ├── jquery-3.7.0.slim.min.js │ ├── jquery-3.7.0.slim.min.map │ ├── jquery.validate-vsdoc.js │ ├── jquery.validate.js │ ├── jquery.validate.min.js │ ├── jquery.validate.unobtrusive.js │ ├── jquery.validate.unobtrusive.min.js │ ├── modernizr-2.6.2.js │ ├── popper-utils.js │ ├── popper-utils.js.map │ ├── popper-utils.min.js │ ├── popper-utils.min.js.map │ ├── popper.js │ ├── popper.js.map │ ├── popper.min.js │ ├── popper.min.js.map │ ├── respond.js │ ├── respond.min.js │ └── umd │ │ ├── popper-utils.js │ │ ├── popper-utils.js.map │ │ ├── popper-utils.min.js │ │ ├── popper-utils.min.js.map │ │ ├── popper.js │ │ ├── popper.js.map │ │ ├── popper.min.js │ │ └── popper.min.js.map ├── Utils │ ├── InMemoryHandler.cs │ ├── Log4NetLogger.cs │ └── MultiLogger.cs ├── Views │ ├── Demo │ │ ├── Config.cshtml │ │ ├── Index.cshtml │ │ ├── Messages.cshtml │ │ ├── SelectVisitor.cshtml │ │ ├── Shop.cshtml │ │ └── _DemoMenu.cshtml │ ├── Home │ │ └── Index.cshtml │ ├── Shared │ │ ├── Error.cshtml │ │ └── _Layout.cshtml │ ├── Web.config │ └── _ViewStart.cshtml ├── Web.Debug.config ├── Web.Release.config ├── Web.config ├── favicon.ico └── packages.config ├── OptimizelySDK.NETFramework.sln ├── OptimizelySDK.Net35 ├── JsonNet │ └── Newtonsoft.Json.dll ├── OptimizelySDK.Net35.csproj ├── Properties │ └── AssemblyInfo.cs └── packages.config ├── OptimizelySDK.Net40 ├── OptimizelySDK.Net40.csproj ├── Properties │ └── AssemblyInfo.cs └── packages.config ├── OptimizelySDK.NetStandard16 ├── ICloneable.cs ├── OptimizelySDK.NetStandard16.csproj ├── OptimizelySDK.NetStandard16.sln └── Properties │ └── AssemblyInfo.cs ├── OptimizelySDK.NetStandard20 ├── OptimizelySDK.NetStandard20.csproj └── Properties │ └── AssemblyInfo.cs ├── OptimizelySDK.Tests ├── App.config ├── Assertions.cs ├── AudienceConditionsTests │ ├── ConditionEvaluationTest.cs │ ├── ConditionsTest.cs │ └── SegmentsTests.cs ├── BucketerTest.cs ├── ClientConfigHandlerTest.cs ├── ConfigTest │ ├── FallbackProjectConfigManagerTest.cs │ ├── HttpProjectConfigManagerTest.cs │ ├── PollingProjectConfigManagerTest.cs │ ├── ProjectConfigProps.cs │ └── TestPollingProjectConfigManager.cs ├── DecisionServiceTest.cs ├── DefaultErrorHandlerTest.cs ├── EmptyRolloutRule.json ├── EntityTests │ ├── FeatureVariableTest.cs │ └── IntegrationTest.cs ├── EventTests │ ├── BatchEventProcessorTest.cs │ ├── CanonicalEvent.cs │ ├── DefaultEventDispatcherTest.cs │ ├── EventBuilderTest.cs │ ├── EventEntitiesTest.cs │ ├── EventFactoryTest.cs │ ├── EventProcessorProps.cs │ ├── ForwardingEventProcessorTest.cs │ ├── LogEventTest.cs │ ├── TestEventDispatcher.cs │ ├── TestForwardingEventDispatcher.cs │ └── UserEventFactoryTest.cs ├── ForcedDecisionsStoreTest.cs ├── IntegrationEmptyDatafile.json ├── IntegrationNonOdpDatafile.json ├── IntegrationOdpDatafile.json ├── IntegrationOdpWithOtherFieldsDatafile.json ├── InvalidEventDispatcher.cs ├── NotificationTests │ └── NotificationCenterTests.cs ├── OdpSegmentsDatafile.json ├── OdpTests │ ├── HttpClientTestUtil.cs │ ├── LruCacheTest.cs │ ├── OdpConfigTest.cs │ ├── OdpEventApiManagerTest.cs │ ├── OdpEventManagerTests.cs │ ├── OdpManagerTest.cs │ ├── OdpSegmentApiManagerTest.cs │ └── OdpSegmentManagerTest.cs ├── OptimizelyConfigTests │ └── OptimizelyConfigTest.cs ├── OptimizelyDecisions │ └── OptimizelyDecisionTest.cs ├── OptimizelyFactoryTest.cs ├── OptimizelyJSONTest.cs ├── OptimizelySDK.Tests.csproj ├── OptimizelyTest.cs ├── OptimizelyUserContextTest.cs ├── ProjectConfigTest.cs ├── Properties │ └── AssemblyInfo.cs ├── TestBucketer.cs ├── TestData.json ├── TestSetup.cs ├── Utils │ ├── Reflection.cs │ ├── TestConversionExtensions.cs │ ├── TestData.cs │ └── TestHttpProjectConfigManagerUtil.cs ├── UtilsTests │ ├── ConditionParserTest.cs │ ├── EventTagUtilsTest.cs │ ├── ExceptionExtensionsTest.cs │ ├── ExperimentUtilsTest.cs │ ├── PrivateObject.cs │ └── ValidatorTest.cs ├── ValidEventDispatcher.cs ├── emptydatafile.json ├── packages.config ├── similar_exp_keys.json ├── similar_rule_keys_bucketing.json ├── simple_ab_experiments.json ├── typed_audience_datafile.json └── unsupported_version_datafile.json ├── OptimizelySDK.nuspec.template ├── OptimizelySDK.png ├── OptimizelySDK.sln ├── OptimizelySDK.sln.DotSettings ├── OptimizelySDK ├── AudienceConditions │ ├── AndCondition.cs │ ├── AudienceIdCondition.cs │ ├── BaseCondition.cs │ ├── EmptyCondition.cs │ ├── ICondition.cs │ ├── NotCondition.cs │ ├── OrCondition.cs │ └── SemanticVersion.cs ├── Bucketing │ ├── Bucketer.cs │ ├── Decision.cs │ ├── DecisionService.cs │ ├── UserProfile.cs │ ├── UserProfileService.cs │ ├── UserProfileTracker.cs │ └── UserProfileUtil.cs ├── ClientConfigHandler.cs ├── Config │ ├── DatafileProjectConfig.cs │ ├── FallbackProjectConfigManager.cs │ ├── HttpProjectConfigManager.cs │ ├── PollingProjectConfigManager.cs │ └── ProjectConfigManager.cs ├── Entity │ ├── Attribute.cs │ ├── Audience.cs │ ├── Entity.cs │ ├── Event.cs │ ├── EventTags.cs │ ├── Experiment.cs │ ├── FeatureDecision.cs │ ├── FeatureFlag.cs │ ├── FeatureVariable.cs │ ├── FeatureVariableUsage.cs │ ├── ForcedVariation.cs │ ├── Group.cs │ ├── IdKeyEntity.cs │ ├── Integration.cs │ ├── Result.cs │ ├── Rollout.cs │ ├── TrafficAllocation.cs │ ├── UserAttributes.cs │ └── Variation.cs ├── ErrorHandler │ ├── DefaultErrorHandler.cs │ ├── IErrorHandler.cs │ └── NoOpErrorHandler.cs ├── Event │ ├── BatchEventProcessor.cs │ ├── Builder │ │ ├── EventBuilder.cs │ │ └── Params.cs │ ├── Dispatcher │ │ ├── DefaultEventDispatcher.cs │ │ ├── HttpClientEventDispatcher45.cs │ │ ├── IEventDispatcher.cs │ │ └── WebRequestEventDispatcher35.cs │ ├── Entity │ │ ├── ConversionEvent.cs │ │ ├── Decision.cs │ │ ├── DecisionMetadata.cs │ │ ├── EventBatch.cs │ │ ├── EventContext.cs │ │ ├── ImpressionEvent.cs │ │ ├── Snapshot.cs │ │ ├── SnapshotEvent.cs │ │ ├── UserEvent.cs │ │ ├── Visitor.cs │ │ └── VisitorAttribute.cs │ ├── EventFactory.cs │ ├── EventProcessor.cs │ ├── ForwardingEventProcessor.cs │ ├── LogEvent.cs │ └── UserEventFactory.cs ├── Exceptions │ └── OptimizelyException.cs ├── ForcedDecisionsStore.cs ├── IOptimizely.cs ├── Logger │ ├── DefaultLogger.cs │ ├── ILogger.cs │ └── NoOpLogger.cs ├── Notifications │ ├── NotificationCenter.cs │ └── NotificationCenterRegistry.cs ├── Odp │ ├── Constants.cs │ ├── Entity │ │ ├── Audience.cs │ │ ├── Customer.cs │ │ ├── Data.cs │ │ ├── Edge.cs │ │ ├── Error.cs │ │ ├── Extension.cs │ │ ├── Location.cs │ │ ├── Node.cs │ │ ├── OdpEvent.cs │ │ └── Response.cs │ ├── Enums.cs │ ├── ICache.cs │ ├── IOdpEventApiManager.cs │ ├── IOdpEventManager.cs │ ├── IOdpManager.cs │ ├── IOdpSegmentApiManager.cs │ ├── IOdpSegmentManager.cs │ ├── LruCache.cs │ ├── OdpConfig.cs │ ├── OdpEventApiManager.cs │ ├── OdpEventManager.cs │ ├── OdpManager.cs │ ├── OdpSegmentApiManager.cs │ └── OdpSegmentManager.cs ├── Optimizely.cs ├── OptimizelyDecisionContext.cs ├── OptimizelyDecisions │ ├── DecisionMessage.cs │ ├── DecisionReasons.cs │ ├── OptimizelyDecideOption.cs │ └── OptimizelyDecision.cs ├── OptimizelyFactory.cs ├── OptimizelyForcedDecision.cs ├── OptimizelyJSON.cs ├── OptimizelySDK.csproj ├── OptimizelyUserContext.cs ├── OptlyConfig │ ├── IOptimizelyConfigManager.cs │ ├── OptimizelyAttribute.cs │ ├── OptimizelyAudience.cs │ ├── OptimizelyConfig.cs │ ├── OptimizelyConfigService.cs │ ├── OptimizelyEvent.cs │ ├── OptimizelyExperiment.cs │ ├── OptimizelyFeature.cs │ ├── OptimizelyVariable.cs │ └── OptimizelyVariation.cs ├── ProjectConfig.cs ├── Properties │ └── AssemblyInfo.cs ├── Utils │ ├── AttributeMatchTypes.cs │ ├── CollectionExtensions.cs │ ├── ConditionParser.cs │ ├── ConfigParser.cs │ ├── ControlAttributes.cs │ ├── DateTimeUtils.cs │ ├── DecisionInfoTypes.cs │ ├── EventTagUtils.cs │ ├── ExceptionExtensions.cs │ ├── ExperimentUtils.cs │ ├── Schema.cs │ ├── Validator.cs │ └── schema.json └── packages.config ├── README.md ├── docs └── readme-sync │ └── sdk-reference-guides │ └── csharp-sdk │ ├── 010 - install-sdk-csharp.md │ ├── 010 -install-sdk-csharp.md │ ├── 020 - initialize-sdk-csharp.md │ ├── 030 - example-usage-csharp.md │ ├── 040 - optimizelyconfig-csharp.md │ ├── 050 - implement-a-user-profile-csharp.md │ ├── 060 - configure-event-dispatcher-csharp.md │ ├── 070 - event-batching-csharp.md │ ├── 080 - customize-logger-csharp.md │ ├── 090 - customize-error-handler-csharp.md │ ├── 100 - pass-in-audience-attributes-csharp.md │ ├── 110 - set-up-notification-listener-csharp.md │ ├── 120 - activate-csharp.md │ ├── 130 - get-enabled-features-csharp.md │ ├── 140 - get-feature-variable-csharp.md │ ├── 150 - get-forced-variation-csharp.md │ ├── 160 - get-variation-csharp.md │ ├── 170 - is-feature-enabled-csharp.md │ ├── 180 - set-forced-variation-csharp.md │ ├── 190 - track-csharp.md │ └── index.md ├── install_mono.sh ├── keypair.snk └── pull_request_template.md /.github/ISSUE_TEMPLATE/ENHANCEMENT.yml: -------------------------------------------------------------------------------- 1 | name: ✨Enhancement 2 | description: Create a new ticket for a Enhancement/Tech-initiative for the benefit of the SDK which would be considered for a minor version update. 3 | title: "[ENHANCEMENT] " 4 | labels: ["enhancement"] 5 | body: 6 | - type: textarea 7 | id: description 8 | attributes: 9 | label: "Description" 10 | description: Briefly describe the enhancement in a few sentences. 11 | placeholder: Short description... 12 | validations: 13 | required: true 14 | - type: textarea 15 | id: benefits 16 | attributes: 17 | label: "Benefits" 18 | description: How would the enhancement benefit to your product or usage? 19 | placeholder: Benefits... 20 | validations: 21 | required: true 22 | - type: textarea 23 | id: detail 24 | attributes: 25 | label: "Detail" 26 | description: How would you like the enhancement to work? Please provide as much detail as possible 27 | placeholder: Detailed description... 28 | validations: 29 | required: false 30 | - type: textarea 31 | id: examples 32 | attributes: 33 | label: "Examples" 34 | description: Are there any examples of this enhancement in other products/services? If so, please provide links or references. 35 | placeholder: Links/References... 36 | validations: 37 | required: false 38 | - type: textarea 39 | id: risks 40 | attributes: 41 | label: "Risks/Downsides" 42 | description: Do you think this enhancement could have any potential downsides or risks? 43 | placeholder: Risks/Downsides... 44 | validations: 45 | required: false -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/FEATURE-REQUEST.md: -------------------------------------------------------------------------------- 1 | <!-- 2 | Thanks for filing in issue! Are you requesting a new feature? If so, please share your feedback with us on the following link. 3 | --> 4 | ## Feedback requesting a new feature can be shared [here.](https://feedback.optimizely.com/) 5 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false 2 | contact_links: 3 | - name: 💡Feature Requests 4 | url: https://feedback.optimizely.com/ 5 | about: Feedback requesting a new feature can be shared here. -------------------------------------------------------------------------------- /.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | ## Summary 2 | - The "what"; a concise description of each logical change 3 | - Another change 4 | 5 | The "why", or other context. 6 | 7 | ## Test plan 8 | 9 | ## Issues 10 | - "THING-1234" or "Fixes #123" -------------------------------------------------------------------------------- /.github/workflows/integration_test.yml: -------------------------------------------------------------------------------- 1 | name: Reusable action of running integration of production suite 2 | 3 | on: 4 | workflow_call: 5 | inputs: 6 | FULLSTACK_TEST_REPO: 7 | required: false 8 | type: string 9 | secrets: 10 | CI_USER_TOKEN: 11 | required: true 12 | jobs: 13 | test: 14 | runs-on: ubuntu-latest 15 | steps: 16 | - uses: actions/checkout@v2 17 | with: 18 | # You should create a personal access token and store it in your repository 19 | token: ${{ secrets.CI_USER_TOKEN }} 20 | repository: 'optimizely/ci-helper-tools' 21 | path: 'home/runner/ci-helper-tools' 22 | ref: 'master' 23 | - name: set SDK Branch if PR 24 | env: 25 | HEAD_REF: ${{ github.head_ref }} 26 | if: ${{ github.event_name == 'pull_request' }} 27 | run: | 28 | echo "SDK_BRANCH=$HEAD_REF" >> $GITHUB_ENV 29 | - name: set SDK Branch if not pull request 30 | env: 31 | REF_NAME: ${{ github.ref_name }} 32 | if: ${{ github.event_name != 'pull_request' }} 33 | run: | 34 | echo "SDK_BRANCH=$REF_NAME" >> $GITHUB_ENV 35 | - name: Trigger build 36 | env: 37 | SDK: csharp 38 | FULLSTACK_TEST_REPO: ${{ inputs.FULLSTACK_TEST_REPO }} 39 | BUILD_NUMBER: ${{ github.run_id }} 40 | TESTAPP_BRANCH: master 41 | GITHUB_TOKEN: ${{ secrets.CI_USER_TOKEN }} 42 | EVENT_TYPE: ${{ github.event_name }} 43 | GITHUB_CONTEXT: ${{ toJson(github) }} 44 | #REPO_SLUG: ${{ github.repository }} 45 | PULL_REQUEST_SLUG: ${{ github.repository }} 46 | UPSTREAM_REPO: ${{ github.repository }} 47 | PULL_REQUEST_SHA: ${{ github.event.pull_request.head.sha }} 48 | PULL_REQUEST_NUMBER: ${{ github.event.pull_request.number }} 49 | UPSTREAM_SHA: ${{ github.sha }} 50 | EVENT_MESSAGE: ${{ github.event.message }} 51 | HOME: 'home/runner' 52 | run: | 53 | echo "$GITHUB_CONTEXT" 54 | home/runner/ci-helper-tools/trigger-script-with-status-update.sh 55 | -------------------------------------------------------------------------------- /.github/workflows/sonarqube.yml: -------------------------------------------------------------------------------- 1 | name: SonarQube 2 | on: 3 | push: 4 | branches: 5 | - dsier/sonarqube 6 | jobs: 7 | build: 8 | name: Build 9 | runs-on: windows-latest 10 | steps: 11 | - name: Set up JDK 11 12 | uses: actions/setup-java@v4 13 | with: 14 | java-version: 1.11 15 | - uses: actions/checkout@v4 16 | with: 17 | fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis 18 | - name: Cache SonarCloud packages 19 | uses: actions/cache@v4 20 | with: 21 | path: ~\sonar\cache 22 | key: ${{ runner.os }}-sonar 23 | restore-keys: ${{ runner.os }}-sonar 24 | - name: Cache SonarCloud scanner 25 | id: cache-sonar-scanner 26 | uses: actions/cache@v4 27 | with: 28 | path: .\.sonar\scanner 29 | key: ${{ runner.os }}-sonar-scanner 30 | restore-keys: ${{ runner.os }}-sonar-scanner 31 | - name: Install SonarCloud scanner 32 | if: steps.cache-sonar-scanner.outputs.cache-hit != 'true' 33 | shell: powershell 34 | run: | 35 | New-Item -Path .\.sonar\scanner -ItemType Directory 36 | dotnet tool update dotnet-sonarscanner --tool-path .\.sonar\scanner 37 | - name: Build and analyze 38 | env: 39 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed to get PR information, if any 40 | SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} 41 | shell: powershell 42 | run: | 43 | .\.sonar\scanner\dotnet-sonarscanner begin /k:"csharpsdk" /o:"optidevx" /d:sonar.login="${{ secrets.SONAR_TOKEN }}" /d:sonar.host.url="https://sonarcloud.io" 44 | dotnet build .\OptimizelySDK\ 45 | .\.sonar\scanner\dotnet-sonarscanner end /d:sonar.login="${{ secrets.SONAR_TOKEN 46 | -------------------------------------------------------------------------------- /.github/workflows/source_clear_cron.yml: -------------------------------------------------------------------------------- 1 | name: Source clear 2 | 3 | on: 4 | schedule: 5 | # Runs "weekly" 6 | - cron: '0 0 * * 0' 7 | 8 | jobs: 9 | source_clear: 10 | runs-on: ubuntu-latest 11 | steps: 12 | - uses: actions/checkout@v2 13 | - name: Source clear scan 14 | env: 15 | SRCCLR_API_TOKEN: ${{ secrets.SRCCLR_API_TOKEN }} 16 | run: curl -sSL https://download.sourceclear.com/ci.sh | bash -s – scan 17 | -------------------------------------------------------------------------------- /.github/workflows/ticket_reference_check.yml: -------------------------------------------------------------------------------- 1 | name: Jira Ticket Reference Check 2 | 3 | on: 4 | pull_request: 5 | types: [opened, edited, reopened, synchronize] 6 | 7 | jobs: 8 | jira_ticket_reference_check: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - name: Check for Jira ticket reference 12 | uses: optimizely/github-action-ticket-reference-checker-public@master 13 | with: 14 | bodyRegex: 'FSSDK-(?<ticketNumber>\d+)' 15 | -------------------------------------------------------------------------------- /CODEOWNERS: -------------------------------------------------------------------------------- 1 | # This is a comment. 2 | # Each line is a file pattern followed by one or more owners. 3 | 4 | # These owners will be the default owners for everything in the repo. 5 | # Unless a later match takes precedence, @global-owner1 and @global-owner2 6 | # will be requested for review when someone opens a pull request. 7 | * @optimizely/fullstack-devs 8 | 9 | # Order is important; the last matching pattern takes the most precedence. 10 | # When someone opens a pull request that only modifies JS files, only @js-owner 11 | # and not the global owner(s) will be requested for a review. 12 | #*.js @js-owner 13 | 14 | # You can also use email addresses if you prefer. They'll be used to look up 15 | # users just like we do for commit author emails. 16 | #docs/* docs@example.com 17 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/optimizely/csharp-sdk/282b7cf7577d1adf2fedaad33625dab34aea5fa6/CONTRIBUTING.md -------------------------------------------------------------------------------- /OptimizelySDK.DemoApp/App_Start/BundleConfig.cs: -------------------------------------------------------------------------------- 1 | using System.Web; 2 | using System.Web.Optimization; 3 | 4 | namespace OptimizelySDK.DemoApp 5 | { 6 | public class BundleConfig 7 | { 8 | // For more information on bundling, visit http://go.microsoft.com/fwlink/?LinkId=301862 9 | public static void RegisterBundles(BundleCollection bundles) 10 | { 11 | bundles.Add(new ScriptBundle("~/bundles/jquery").Include( 12 | "~/Scripts/jquery-{version}.js")); 13 | 14 | bundles.Add(new ScriptBundle("~/bundles/jqueryval").Include( 15 | "~/Scripts/jquery.validate*")); 16 | 17 | // Use the development version of Modernizr to develop with and learn from. Then, when you're 18 | // ready for production, use the build tool at http://modernizr.com to pick only the tests you need. 19 | bundles.Add(new ScriptBundle("~/bundles/modernizr").Include( 20 | "~/Scripts/modernizr-*")); 21 | 22 | bundles.Add(new ScriptBundle("~/bundles/bootstrap").Include( 23 | "~/Scripts/bootstrap.js", 24 | "~/Scripts/respond.js")); 25 | 26 | bundles.Add(new StyleBundle("~/Content/css").Include( 27 | "~/Content/bootstrap.css", 28 | "~/Content/site.css")); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /OptimizelySDK.DemoApp/App_Start/FilterConfig.cs: -------------------------------------------------------------------------------- 1 | using System.Web; 2 | using System.Web.Mvc; 3 | 4 | namespace OptimizelySDK.DemoApp 5 | { 6 | public class FilterConfig 7 | { 8 | public static void RegisterGlobalFilters(GlobalFilterCollection filters) 9 | { 10 | filters.Add(new HandleErrorAttribute()); 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /OptimizelySDK.DemoApp/App_Start/RouteConfig.cs: -------------------------------------------------------------------------------- 1 | using System.Web.Mvc; 2 | using System.Web.Routing; 3 | 4 | namespace OptimizelySDK.DemoApp 5 | { 6 | public class RouteConfig 7 | { 8 | public static void RegisterRoutes(RouteCollection routes) 9 | { 10 | routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); 11 | 12 | routes.MapRoute( 13 | name: "Default", 14 | url: "{controller}/{action}/{id}", 15 | defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional } 16 | ); 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /OptimizelySDK.DemoApp/Content/Images/item_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/optimizely/csharp-sdk/282b7cf7577d1adf2fedaad33625dab34aea5fa6/OptimizelySDK.DemoApp/Content/Images/item_1.png -------------------------------------------------------------------------------- /OptimizelySDK.DemoApp/Content/Images/item_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/optimizely/csharp-sdk/282b7cf7577d1adf2fedaad33625dab34aea5fa6/OptimizelySDK.DemoApp/Content/Images/item_2.png -------------------------------------------------------------------------------- /OptimizelySDK.DemoApp/Content/Images/item_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/optimizely/csharp-sdk/282b7cf7577d1adf2fedaad33625dab34aea5fa6/OptimizelySDK.DemoApp/Content/Images/item_3.png -------------------------------------------------------------------------------- /OptimizelySDK.DemoApp/Content/Images/item_4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/optimizely/csharp-sdk/282b7cf7577d1adf2fedaad33625dab34aea5fa6/OptimizelySDK.DemoApp/Content/Images/item_4.png -------------------------------------------------------------------------------- /OptimizelySDK.DemoApp/Content/Images/item_5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/optimizely/csharp-sdk/282b7cf7577d1adf2fedaad33625dab34aea5fa6/OptimizelySDK.DemoApp/Content/Images/item_5.png -------------------------------------------------------------------------------- /OptimizelySDK.DemoApp/Content/Images/item_6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/optimizely/csharp-sdk/282b7cf7577d1adf2fedaad33625dab34aea5fa6/OptimizelySDK.DemoApp/Content/Images/item_6.png -------------------------------------------------------------------------------- /OptimizelySDK.DemoApp/Content/Images/item_7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/optimizely/csharp-sdk/282b7cf7577d1adf2fedaad33625dab34aea5fa6/OptimizelySDK.DemoApp/Content/Images/item_7.png -------------------------------------------------------------------------------- /OptimizelySDK.DemoApp/Content/Images/item_8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/optimizely/csharp-sdk/282b7cf7577d1adf2fedaad33625dab34aea5fa6/OptimizelySDK.DemoApp/Content/Images/item_8.png -------------------------------------------------------------------------------- /OptimizelySDK.DemoApp/Content/Images/item_9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/optimizely/csharp-sdk/282b7cf7577d1adf2fedaad33625dab34aea5fa6/OptimizelySDK.DemoApp/Content/Images/item_9.png -------------------------------------------------------------------------------- /OptimizelySDK.DemoApp/Content/Site.css: -------------------------------------------------------------------------------- 1 | body { 2 | padding-bottom: 20px; 3 | } 4 | 5 | /* Set padding to keep content from hitting the edges */ 6 | .body-content { 7 | padding-left: 15px; 8 | padding-right: 15px; 9 | } 10 | 11 | /* Override the default bootstrap behavior where horizontal description lists 12 | will truncate terms that are too long to fit in the left column 13 | */ 14 | .dl-horizontal dt { 15 | white-space: normal; 16 | } 17 | 18 | /* Set width on the form input elements since they're 100% wide by default */ 19 | input, 20 | select, 21 | textarea { 22 | max-width: 280px; 23 | } 24 | -------------------------------------------------------------------------------- /OptimizelySDK.DemoApp/Controllers/HomeController.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017, Optimizely 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | using System.Web.Mvc; 17 | 18 | namespace OptimizelySDK.DemoApp.Controllers 19 | { 20 | public class HomeController : Controller 21 | { 22 | public ActionResult Index() 23 | { 24 | return View(); 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /OptimizelySDK.DemoApp/Global.asax: -------------------------------------------------------------------------------- 1 | <%@ Application Codebehind="Global.asax.cs" Inherits="OptimizelySDK.DemoApp.MvcApplication" Language="C#" %> 2 | -------------------------------------------------------------------------------- /OptimizelySDK.DemoApp/Global.asax.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Web; 5 | using System.Web.Mvc; 6 | using System.Web.Optimization; 7 | using System.Web.Routing; 8 | 9 | namespace OptimizelySDK.DemoApp 10 | { 11 | public class MvcApplication : System.Web.HttpApplication 12 | { 13 | protected void Application_Start() 14 | { 15 | AreaRegistration.RegisterAllAreas(); 16 | FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); 17 | RouteConfig.RegisterRoutes(RouteTable.Routes); 18 | BundleConfig.RegisterBundles(BundleTable.Bundles); 19 | log4net.Config.XmlConfigurator.Configure(); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /OptimizelySDK.DemoApp/Log4Net.config: -------------------------------------------------------------------------------- 1 | <!-- log4net configuration --> 2 | <log4net> 3 | <appender name="FileAppender" type="log4net.Appender.FileAppender"> 4 | <file value="DemoApp.log" /> 5 | <appendToFile value="true" /> 6 | <lockingModel type="log4net.Appender.FileAppender+MinimalLock" /> 7 | <layout type="log4net.Layout.PatternLayout"> 8 | <conversionPattern value="%date [%thread] %level %logger - %message%newline" /> 9 | </layout> 10 | <filter type="log4net.Filter.LevelRangeFilter"> 11 | <levelMin value="INFO" /> 12 | <levelMax value="FATAL" /> 13 | </filter> 14 | </appender> 15 | <!--LOGGER FOR INFO/ERRORS--> 16 | <root> 17 | <level value="INFO"/> 18 | <appender-ref ref="FileAppender"/> 19 | </root> 20 | </log4net> 21 | -------------------------------------------------------------------------------- /OptimizelySDK.DemoApp/Models/Config.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017, Optimizely 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | namespace OptimizelySDK.DemoApp.Models 17 | { 18 | public class Config 19 | { 20 | public string ProjectId { get; set; } 21 | public string ExperimentKey { get; set; } 22 | public string EventKey { get; set; } 23 | public string ProjectConfigJson { get; set; } 24 | } 25 | } -------------------------------------------------------------------------------- /OptimizelySDK.DemoApp/Models/DemoViewModel.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2018, Optimizely 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | namespace OptimizelySDK.DemoApp.Models 17 | { 18 | public class DemoViewModel 19 | { 20 | public Product[] Products { get; set; } 21 | public Visitor CurrentVisitor { get; set; } 22 | public string Message { get; set; } 23 | public string VariationKey { get; set; } 24 | } 25 | } -------------------------------------------------------------------------------- /OptimizelySDK.DemoApp/Models/Product.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2018, Optimizely 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | using System.IO; 18 | 19 | namespace OptimizelySDK.DemoApp.Models 20 | { 21 | public class Product 22 | { 23 | private const string IMAGES_DIR = "~/Content/Images"; 24 | 25 | public int Id { get; set; } 26 | public string Name { get; set; } 27 | public string Color { get; set; } 28 | public string Category { get; set; } 29 | public decimal Price { get; set; } 30 | 31 | private string imagePath; 32 | public string ImagePath 33 | { 34 | get 35 | { 36 | return imagePath; 37 | } 38 | set 39 | { 40 | imagePath = Path.Combine(IMAGES_DIR, value); 41 | } 42 | } 43 | } 44 | } -------------------------------------------------------------------------------- /OptimizelySDK.DemoApp/Models/Visitor.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017, Optimizely 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | using OptimizelySDK.Entity; 17 | 18 | namespace OptimizelySDK.DemoApp.Models 19 | { 20 | public class Visitor 21 | { 22 | public int Id { get; set; } 23 | 24 | public string Name { get; set; } 25 | 26 | public int Age { get; set; } 27 | 28 | public UserAttributes GetUserAttributes() 29 | { 30 | return new UserAttributes 31 | { 32 | { "user_id", Id.ToString()}, 33 | { "user_name", Name }, 34 | { "age", Age.ToString() }, 35 | 36 | }; 37 | } 38 | } 39 | } -------------------------------------------------------------------------------- /OptimizelySDK.DemoApp/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("OptimizelySDK.DemoApp")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("OptimizelySDK.DemoApp")] 13 | [assembly: AssemblyCopyright("Copyright © 2017-2023")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // Make types and members with internal scope visible to friend 23 | // OptimizelySDK.Tests unit tests. 24 | #pragma warning disable 1700 25 | [assembly: InternalsVisibleTo("OptimizelySDK.Tests, PublicKey=ThePublicKey")] 26 | #pragma warning restore 1700 27 | 28 | // The following GUID is for the ID of the typelib if this project is exposed to COM 29 | [assembly: Guid("732a5e33-93e5-476d-af8a-e06279c2d28d")] 30 | 31 | // Version information for an assembly consists of the following four values: 32 | // 33 | // Major Version 34 | // Minor Version 35 | // Build Number 36 | // Revision 37 | // 38 | // You can specify all the values or you can default the Revision and Build Numbers 39 | // by using the '*' as shown below: 40 | [assembly: AssemblyVersion("4.1.0.0")] 41 | [assembly: AssemblyFileVersion("4.1.0.0")] 42 | [assembly: AssemblyInformationalVersion("4.1.0")] // Used by NuGet. 43 | -------------------------------------------------------------------------------- /OptimizelySDK.DemoApp/Scripts/_references.js: -------------------------------------------------------------------------------- 1 | /// <reference path="jquery-3.7.0.js" /> 2 | /// <autosync enabled="true" /> 3 | /// <reference path="bootstrap.min.js" /> 4 | /// <reference path="jquery.validate.min.js" /> 5 | /// <reference path="jquery.validate.unobtrusive.min.js" /> 6 | /// <reference path="jquery-1.10.2.min.js" /> 7 | /// <reference path="modernizr-2.6.2.js" /> 8 | /// <reference path="respond.min.js" /> 9 | -------------------------------------------------------------------------------- /OptimizelySDK.DemoApp/Utils/InMemoryHandler.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017, Optimizely 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | using OptimizelySDK.ErrorHandler; 17 | using OptimizelySDK.Logger; 18 | using System; 19 | using System.Collections.Generic; 20 | 21 | namespace OptimizelySDK.DemoApp.Utils 22 | { 23 | public class HandlerItem 24 | { 25 | public string Timestamp { get; set; } 26 | public string Type { get; set; } 27 | public string Message { get; set; } 28 | } 29 | 30 | /// <summary> 31 | /// Helper class to collect Logs and Errors in memory for display to the user for troubleshooting 32 | /// </summary> 33 | public class InMemoryHandler : ILogger, IErrorHandler 34 | { 35 | public List<HandlerItem> HandlerItems { get; private set; } = new List<HandlerItem>(); 36 | 37 | public void Clear() 38 | { 39 | HandlerItems = new List<HandlerItem>(); 40 | } 41 | 42 | private string Timestamp 43 | { 44 | get 45 | { 46 | var now = DateTime.Now; 47 | return string.Format("{0} {1}", now.ToShortDateString(), now.ToLongTimeString()); 48 | } 49 | } 50 | 51 | public void HandleError(Exception exception) 52 | { 53 | HandlerItems.Add(new HandlerItem 54 | { 55 | Timestamp = Timestamp, 56 | Type = "ERROR", 57 | Message = exception.Message 58 | }); 59 | } 60 | 61 | public void Log(LogLevel level, string message) 62 | { 63 | HandlerItems.Add(new HandlerItem 64 | { 65 | Timestamp = Timestamp, 66 | Type = "LOG " + level, 67 | Message = message 68 | }); 69 | } 70 | } 71 | } -------------------------------------------------------------------------------- /OptimizelySDK.DemoApp/Utils/Log4NetLogger.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017, Optimizely 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | namespace OptimizelySDK.DemoApp.Utils 17 | { 18 | /// <summary> 19 | /// Sample implementation of a log4net OptimizelySDK Logger implementation 20 | /// This maps the the logger calls to the corresponding log4net call 21 | /// </summary> 22 | public class Log4NetLogger : OptimizelySDK.Logger.ILogger 23 | { 24 | readonly static log4net.ILog Logger = log4net.LogManager.GetLogger(typeof(Log4NetLogger)); 25 | 26 | public void Log(OptimizelySDK.Logger.LogLevel level, string message) 27 | { 28 | // Add more info to the messages to demonstrate which logs are coming from this Sample Logger 29 | message = string.Format("[Optimizely Sample Log4NetLogger] {0}", message); 30 | 31 | // Log to log4net mapping to the appropriate level 32 | Logger.Logger.Log(typeof(Log4NetLogger), MapLogLevel(level), message, null); 33 | } 34 | 35 | private static log4net.Core.Level MapLogLevel(OptimizelySDK.Logger.LogLevel level) 36 | { 37 | switch (level) 38 | { 39 | default: 40 | case OptimizelySDK.Logger.LogLevel.INFO: return log4net.Core.Level.Info; 41 | case OptimizelySDK.Logger.LogLevel.DEBUG: return log4net.Core.Level.Debug; 42 | case OptimizelySDK.Logger.LogLevel.ERROR: return log4net.Core.Level.Error; 43 | } 44 | } 45 | } 46 | } -------------------------------------------------------------------------------- /OptimizelySDK.DemoApp/Utils/MultiLogger.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017, Optimizely 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | using OptimizelySDK.Logger; 17 | 18 | namespace OptimizelySDK.DemoApp.Utils 19 | { 20 | /// <summary> 21 | /// Helper logger class to log to multiple loggers 22 | /// </summary> 23 | public class MultiLogger : ILogger 24 | { 25 | private ILogger[] Loggers; 26 | 27 | public MultiLogger(ILogger[] loggers) 28 | { 29 | Loggers = loggers; 30 | } 31 | 32 | public void Log(LogLevel level, string message) 33 | { 34 | foreach (ILogger log in Loggers) 35 | log.Log(level, message); 36 | } 37 | } 38 | } -------------------------------------------------------------------------------- /OptimizelySDK.DemoApp/Views/Demo/Index.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | /* 3 | * Copyright 2017, Optimizely 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | } 18 | @{ 19 | ViewBag.Title = "Index"; 20 | } 21 | 22 | @Html.Partial("_DemoMenu") 23 | 24 | <div> 25 | This app demonstrates how to use the Optimizely .Net SDK.<br /><br /> 26 | To get started, click on "Configuration" to enter your Optimizely settings. 27 | </div> -------------------------------------------------------------------------------- /OptimizelySDK.DemoApp/Views/Demo/Messages.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | /* 3 | * Copyright 2017-2018, Optimizely 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | } 18 | 19 | @model List<OptimizelySDK.DemoApp.Utils.HandlerItem> 20 | @{ 21 | ViewBag.Title = "Messages"; 22 | } 23 | 24 | <div class="container"> 25 | @Html.Partial("_DemoMenu") 26 | <h2>Messages <small>(last 1000)</small></h2> 27 | <div> 28 | <a href="/Demo/ClearMessages" class="btn btn-info">Clear Messages</a> 29 | </div> 30 | <br /> 31 | <table class="table table-striped"> 32 | <thead><tr><td>Timestamp</td><td>Type</td><td>Message</td></tr></thead> 33 | @foreach (var item in Model.Skip(Math.Max(Model.Count - 1000, 0)).Take(1000)) 34 | { 35 | <tr> 36 | <td>@item.Timestamp</td> 37 | <td>@item.Type</td> 38 | <td><pre>@item.Message</pre></td> 39 | </tr> 40 | } 41 | </table> 42 | </div> -------------------------------------------------------------------------------- /OptimizelySDK.DemoApp/Views/Demo/SelectVisitor.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | /* 3 | * Copyright 2017-2018, Optimizely 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | } 18 | 19 | @model IEnumerable<OptimizelySDK.DemoApp.Models.Visitor> 20 | @{ 21 | ViewBag.Title = "Select Visitor"; 22 | var visitorId = @HttpContext.Current.Session["VisitorId"] != null ? (int)@HttpContext.Current.Session["VisitorId"] : 1; 23 | } 24 | <div class="container"> 25 | @Html.Partial("_DemoMenu") 26 | 27 | <div class="row"> 28 | <div class="col-md-4"> 29 | <ul class="list-group"> 30 | @foreach (var visitor in Model) 31 | { 32 | <a class="list-group-item @(visitorId == visitor.Id ? "active" : "")" href="SelectVisitor?visitorId=@visitor.Id">@visitor.Name</a> 33 | } 34 | </ul> 35 | </div> 36 | </div> 37 | </div> 38 | -------------------------------------------------------------------------------- /OptimizelySDK.DemoApp/Views/Demo/Shop.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | /* 3 | * Copyright 2017-2018, Optimizely 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | } 18 | 19 | @model OptimizelySDK.DemoApp.Models.DemoViewModel 20 | @{ 21 | ViewBag.Title = "Shop"; 22 | } 23 | 24 | @if (!string.IsNullOrEmpty(Model.Message)) 25 | { 26 | <div class="alert alert-success">@Model.Message</div> 27 | } 28 | 29 | <div class="container"> 30 | @Html.Partial("_DemoMenu") 31 | 32 | <div class="container"> 33 | <div class="card-header text-center"> 34 | Variation: @Model.VariationKey 35 | </div> 36 | <div class="row grid-group"> 37 | @foreach (var product in Model.Products) 38 | { 39 | <div class="item col-xs-3 col-lg-3" style="margin-bottom:45px;"> 40 | <div class="thumbnail"> 41 | <img class="img-fluid group list-group-image" style="width: 100%;height: 240px;" src="@Url.Content(product.ImagePath)" alt="@product.Name"> 42 | <div class="caption"> 43 | <h5 class="group inner list-group-item-heading">@product.Name</h5> 44 | <p class="group inner list-group-item-text"></p> 45 | <ul class="list-group list-group-flush"> 46 | <li class="list-group-item">Color: @product.Color</li> 47 | <li class="list-group-item">Category: @product.Category</li> 48 | </ul> 49 | <p></p> 50 | <div class="row"> 51 | <div class="col-xs-12 col-md-6"> 52 | <p class="lead">@string.Format("{0:c}", product.Price)</p> 53 | </div> 54 | <div class="col-xs-12 col-md-6"> 55 | <a href="Buy?visitorId=@Model.CurrentVisitor.Id&productId=@product.Id" class="btn btn-info">Buy Now</a> 56 | </div> 57 | </div> 58 | </div> 59 | </div> 60 | </div> 61 | } 62 | </div> 63 | </div> 64 | </div> -------------------------------------------------------------------------------- /OptimizelySDK.DemoApp/Views/Demo/_DemoMenu.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | /* 3 | * Copyright 2017-2018, Optimizely 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | } 18 | 19 | @helper HighlightLink(string expectedRouteValue) 20 | { 21 | @(string.Equals(ViewContext.RouteData.Values["Action"].ToString(), expectedRouteValue, StringComparison.OrdinalIgnoreCase) ? "active" : "") 22 | } 23 | 24 | <div class="row"> 25 | <div class="col-sm-9 pt-3 pb-3"> 26 | <ul class="nav nav-tabs"> 27 | <li class="nav-item"><a class="nav-link @HighlightLink("Config")" href="~/Demo/Config">Configuration</a></li> 28 | <li class="nav-item"><a class="nav-link @HighlightLink("SelectVisitor")" href="~/Demo/SelectVisitor">Select Simuilated Visitor</a></li> 29 | <li class="nav-item"><a class="nav-link @HighlightLink("Shop")" href="~/Demo/Shop">Shop</a></li> 30 | <li class="nav-item"><a class="nav-link @HighlightLink("Messages")" href="~/Demo/Messages">Messages (Log and Errors)</a></li> 31 | </ul> 32 | </div> 33 | </div> -------------------------------------------------------------------------------- /OptimizelySDK.DemoApp/Views/Home/Index.cshtml: -------------------------------------------------------------------------------- 1 | @{ /* 2 | * Copyright 2017-2018, Optimizely 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | } 17 | @{ 18 | ViewBag.Title = "Home Page"; 19 | } 20 | 21 | <div class="jumbotron"> 22 | <div class="container"> 23 | <h1>Optimizely</h1> 24 | <p class="lead">Optimizely's C# SDK lets you integrate Optimizely in .NET applications.</p> 25 | </div> 26 | </div> 27 | <div class="container"> 28 | <div class="row"> 29 | <div class="col-md-4"> 30 | <h2>Demo App</h2> 31 | <p> 32 | Begin your Optimizely A/B test of a simulated shopping website experience with Optimizely C# SDK. 33 | </p> 34 | <br /> 35 | <br /> 36 | <p align="center"> 37 | <a href="~/Demo/Config" class="btn btn-info">Demo App »</a> 38 | </p> 39 | <br /> 40 | <br /> 41 | </div> 42 | <div class="col-md-4"> 43 | <h2>Optimizely SDK Documentation</h2> 44 | <p> 45 | Optimizely is an Experimentation Platform that allows you to run experiments and roll out new 46 | features on your website, mobile app, server-side application, or any other internet-connected 47 | device. In addition to our Web solution, we offer SDKs for developers to run experiments in iOS, 48 | Android, Python, Java, Ruby, Node, PHP, and JavaScript. 49 | </p> 50 | <p align="center"><a class="btn btn-info" href="https://developers.optimizely.com/overview/">Learn more »</a></p> 51 | </div> 52 | <div class="col-md-4"> 53 | <h2>Discover Optimizely</h2> 54 | <p> 55 | Digital Innovation is all around you. Ready to tap into it? Optimizely lets you experiment on 56 | everything—from design choices to algorithms. That way the best ideas always win, and the best 57 | customer experiences get even better. 58 | </p> 59 | <p align="center"><a class="btn btn-info" href="https://www.optimizely.com">Learn more »</a></p> 60 | </div> 61 | </div> 62 | </div> -------------------------------------------------------------------------------- /OptimizelySDK.DemoApp/Views/Shared/Error.cshtml: -------------------------------------------------------------------------------- 1 | <!DOCTYPE html> 2 | <html> 3 | <head> 4 | <meta name="viewport" content="width=device-width" /> 5 | <title>Error 6 | 7 | 8 |
9 |

Error.

10 |

An error occurred while processing your request.

11 |
12 | 13 | 14 | -------------------------------------------------------------------------------- /OptimizelySDK.DemoApp/Views/Shared/_Layout.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | /* 3 | * Copyright 2017-2018, 2023 Optimizely 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * https://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | } 18 | 19 | 20 | 21 | 22 | 23 | 24 | @ViewBag.Title - My ASP.NET Application 25 | @Styles.Render("~/Content/css") 26 | @Scripts.Render("~/bundles/modernizr") 27 | 28 | 29 | 45 | @RenderBody() 46 | 47 | @Scripts.Render("~/bundles/jquery") 48 | @Scripts.Render("~/bundles/bootstrap") 49 | @RenderSection("scripts", required: false) 50 | 51 | 52 | -------------------------------------------------------------------------------- /OptimizelySDK.DemoApp/Views/Web.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 |
7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /OptimizelySDK.DemoApp/Views/_ViewStart.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | Layout = "~/Views/Shared/_Layout.cshtml"; 3 | } 4 | -------------------------------------------------------------------------------- /OptimizelySDK.DemoApp/Web.Debug.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 17 | 18 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /OptimizelySDK.DemoApp/Web.Release.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 17 | 18 | 19 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /OptimizelySDK.DemoApp/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/optimizely/csharp-sdk/282b7cf7577d1adf2fedaad33625dab34aea5fa6/OptimizelySDK.DemoApp/favicon.ico -------------------------------------------------------------------------------- /OptimizelySDK.DemoApp/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /OptimizelySDK.Net35/JsonNet/Newtonsoft.Json.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/optimizely/csharp-sdk/282b7cf7577d1adf2fedaad33625dab34aea5fa6/OptimizelySDK.Net35/JsonNet/Newtonsoft.Json.dll -------------------------------------------------------------------------------- /OptimizelySDK.Net35/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("OptimizelySDK.Net35")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("OptimizelySDK.Net35")] 13 | [assembly: AssemblyCopyright("Copyright © 2017-2023")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // Make types and members with internal scope visible to friend 23 | // OptimizelySDK.Tests unit tests. 24 | #pragma warning disable 1700 25 | [assembly: InternalsVisibleTo("OptimizelySDK.Tests, PublicKey=ThePublicKey")] 26 | #pragma warning restore 1700 27 | 28 | // The following GUID is for the ID of the typelib if this project is exposed to COM 29 | [assembly: Guid("c8ff7012-37b7-4d64-ab45-0c62195302ec")] 30 | 31 | // Version information for an assembly consists of the following four values: 32 | // 33 | // Major Version 34 | // Minor Version 35 | // Build Number 36 | // Revision 37 | // 38 | // You can specify all the values or you can default the Build and Revision Numbers 39 | // by using the '*' as shown below: 40 | [assembly: AssemblyVersion("4.1.0.0")] 41 | [assembly: AssemblyFileVersion("4.1.0.0")] 42 | [assembly: AssemblyInformationalVersion("4.1.0")] // Used by NuGet. 43 | -------------------------------------------------------------------------------- /OptimizelySDK.Net35/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /OptimizelySDK.Net40/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("OptimizelySDK.Net40")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("OptimizelySDK.Net40")] 13 | [assembly: AssemblyCopyright("Copyright © 2017-2023")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // Make types and members with internal scope visible to friend 23 | // OptimizelySDK.Tests unit tests. 24 | #pragma warning disable 1700 25 | [assembly: InternalsVisibleTo("OptimizelySDK.Tests, PublicKey=ThePublicKey")] 26 | #pragma warning restore 1700 27 | 28 | // The following GUID is for the ID of the typelib if this project is exposed to COM 29 | [assembly: Guid("41afd990-bc81-49e3-bd85-40972bb2c262")] 30 | 31 | // Version information for an assembly consists of the following four values: 32 | // 33 | // Major Version 34 | // Minor Version 35 | // Build Number 36 | // Revision 37 | // 38 | // You can specify all the values or you can default the Build and Revision Numbers 39 | // by using the '*' as shown below: 40 | [assembly: AssemblyVersion("4.1.0.0")] 41 | [assembly: AssemblyFileVersion("4.1.0.0")] 42 | [assembly: AssemblyInformationalVersion("4.1.0")] // Used by NuGet. 43 | -------------------------------------------------------------------------------- /OptimizelySDK.Net40/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /OptimizelySDK.NetStandard16/ICloneable.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017, Optimizely 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | namespace OptimizelySDK 17 | { 18 | public interface ICloneable 19 | { 20 | object Clone(); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /OptimizelySDK.NetStandard16/OptimizelySDK.NetStandard16.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OptimizelySDK.NetStandard16", "OptimizelySDK.NetStandard16.csproj", "{0A7EBA5C-A049-48AE-861D-8881EFA6B9E2}" 5 | EndProject 6 | Global 7 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 8 | Release|Any CPU = Release|Any CPU 9 | Debug|Any CPU = Debug|Any CPU 10 | EndGlobalSection 11 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 12 | {0A7EBA5C-A049-48AE-861D-8881EFA6B9E2}.Release|Any CPU.ActiveCfg = Release|Any CPU 13 | {0A7EBA5C-A049-48AE-861D-8881EFA6B9E2}.Release|Any CPU.Build.0 = Release|Any CPU 14 | {0A7EBA5C-A049-48AE-861D-8881EFA6B9E2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {0A7EBA5C-A049-48AE-861D-8881EFA6B9E2}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | EndGlobalSection 17 | EndGlobal 18 | -------------------------------------------------------------------------------- /OptimizelySDK.NetStandard16/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("OptimizelySDK.NetStandard16")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("OptimizelySDK.NetStandard16")] 13 | [assembly: AssemblyCopyright("Copyright © 2017-2023")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // Make types and members with internal scope visible to friend 23 | // OptimizelySDK.Tests unit tests. 24 | #pragma warning disable 1700 25 | [assembly: InternalsVisibleTo("OptimizelySDK.Tests, PublicKey=ThePublicKey")] 26 | #pragma warning restore 1700 27 | 28 | // The following GUID is for the ID of the typelib if this project is exposed to COM 29 | [assembly: Guid("40906323-a8be-4a71-8e42-9646b23d56cf")] 30 | 31 | // Version information for an assembly consists of the following four values: 32 | // 33 | // Major Version 34 | // Minor Version 35 | // Build Number 36 | // Revision 37 | // 38 | // You can specify all the values or you can default the Build and Revision Numbers 39 | // by using the '*' as shown below: 40 | [assembly: AssemblyVersion("4.1.0")] 41 | [assembly: AssemblyFileVersion("4.1.0.0")] 42 | [assembly: AssemblyInformationalVersion("4.1.0")] // Used by NuGet. 43 | -------------------------------------------------------------------------------- /OptimizelySDK.NetStandard20/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("OptimizelySDK.NetStandard20")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("OptimizelySDK.NetStandard20")] 13 | [assembly: AssemblyCopyright("Copyright © 2019-2023")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // Make types and members with internal scope visible to friend 23 | // OptimizelySDK.Tests unit tests. 24 | #pragma warning disable 1700 25 | [assembly: InternalsVisibleTo("OptimizelySDK.Tests, PublicKey=ThePublicKey")] 26 | #pragma warning restore 1700 27 | 28 | // The following GUID is for the ID of the typelib if this project is exposed to COM 29 | [assembly: Guid("40906323-a8be-4a71-8e42-9646b23d56cf")] 30 | 31 | // Version information for an assembly consists of the following four values: 32 | // 33 | // Major Version 34 | // Minor Version 35 | // Build Number 36 | // Revision 37 | // 38 | // You can specify all the values or you can default the Build and Revision Numbers 39 | // by using the '*' as shown below: 40 | [assembly: AssemblyVersion("4.1.0.0")] 41 | [assembly: AssemblyFileVersion("4.1.0.0")] 42 | [assembly: AssemblyInformationalVersion("4.1.0")] // Used by NuGet. 43 | -------------------------------------------------------------------------------- /OptimizelySDK.Tests/App.config: -------------------------------------------------------------------------------- 1 |  2 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /OptimizelySDK.Tests/ClientConfigHandlerTest.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019-2020, Optimizely 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #if !NETSTANDARD1_6 && !NET35 18 | 19 | using System.Configuration; 20 | using NUnit.Framework; 21 | 22 | namespace OptimizelySDK.Tests 23 | { 24 | [TestFixture] 25 | public class ClientConfigHandlerTest 26 | { 27 | [Test] 28 | public void TestHTTPAppConfigSection() 29 | { 30 | var configSection = 31 | ConfigurationManager.GetSection("optlySDKConfigSection") as 32 | OptimizelySDKConfigSection; 33 | var httpSetting = configSection.HttpProjectConfig; 34 | Assert.IsNotNull(httpSetting); 35 | Assert.IsTrue(httpSetting.AutoUpdate); 36 | Assert.AreEqual(httpSetting.BlockingTimeOutPeriod, 10000); 37 | Assert.AreEqual(httpSetting.Format, "https://cdn.optimizely.com/data/{0}.json"); 38 | Assert.IsTrue(httpSetting.DefaultStart); 39 | Assert.AreEqual(httpSetting.PollingInterval, 2000); 40 | Assert.AreEqual(httpSetting.SDKKey, "43214321"); 41 | Assert.AreEqual(httpSetting.Url, "www.testurl.com"); 42 | Assert.AreEqual(httpSetting.DatafileAccessToken, "testingtoken123"); 43 | } 44 | 45 | [Test] 46 | public void TestBatchEventAppConfigSection() 47 | { 48 | var configSection = 49 | ConfigurationManager.GetSection("optlySDKConfigSection") as 50 | OptimizelySDKConfigSection; 51 | var batchSetting = configSection.BatchEventProcessor; 52 | Assert.IsNotNull(batchSetting); 53 | Assert.AreEqual(batchSetting.BatchSize, 10); 54 | Assert.AreEqual(batchSetting.FlushInterval, 2000); 55 | Assert.AreEqual(batchSetting.TimeoutInterval, 10000); 56 | Assert.IsTrue(batchSetting.DefaultStart); 57 | } 58 | } 59 | } 60 | #endif 61 | -------------------------------------------------------------------------------- /OptimizelySDK.Tests/ConfigTest/FallbackProjectConfigManagerTest.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019, Optimizely 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | using NUnit.Framework; 18 | using OptimizelySDK.Config; 19 | 20 | namespace OptimizelySDK.Tests.DatafileManagement_Tests 21 | { 22 | [TestFixture] 23 | public class AtomicProjectConfigManagerTest 24 | { 25 | private FallbackProjectConfigManager ConfigManager; 26 | 27 | [Test] 28 | public void TestStaticProjectConfigManagerReturnsCorrectProjectConfig() 29 | { 30 | var expectedConfig = 31 | DatafileProjectConfig.Create(TestData.TypedAudienceDatafile, null, null); 32 | ConfigManager = new FallbackProjectConfigManager(expectedConfig); 33 | 34 | Assert.True(TestData.CompareObjects(expectedConfig, ConfigManager.GetConfig())); 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /OptimizelySDK.Tests/EmptyRolloutRule.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "4", 3 | "rollouts": [ 4 | { 5 | "experiments": [ 6 | ], 7 | "id": "18309384009" 8 | } 9 | ], 10 | "typedAudiences": [], 11 | "anonymizeIP": true, 12 | "projectId": "18326250003", 13 | "variables": [], 14 | "featureFlags": [ 15 | { 16 | "experimentIds": [], 17 | "rolloutId": "18309384009", 18 | "variables": [ 19 | { 20 | "defaultValue": "", 21 | "type": "string", 22 | "id": "18323951833", 23 | "key": "var_1" 24 | } 25 | ], 26 | "id": "18244658520", 27 | "key": "empty_rollout" 28 | }, 29 | { 30 | "experimentIds": [], 31 | "rolloutId": "", 32 | "variables": [ 33 | { 34 | "defaultValue": "", 35 | "type": "string", 36 | "id": "2832355113", 37 | "key": "var_2" 38 | } 39 | ], 40 | "id": "24246538512", 41 | "key": "empty_rollout_id" 42 | } 43 | ], 44 | "experiments": [], 45 | "audiences": [ 46 | { 47 | "conditions": "[\"or\", {\"match\": \"exact\", \"name\": \"$opt_dummy_attribute\", \"type\": \"custom_attribute\", \"value\": \"$opt_dummy_value\"}]", 48 | "id": "$opt_dummy_audience", 49 | "name": "Optimizely-Generated Audience for Backwards Compatibility" 50 | } 51 | ], 52 | "groups": [], 53 | "attributes": [], 54 | "botFiltering": false, 55 | "accountId": "8272261422", 56 | "events": [], 57 | "revision": "2" 58 | } 59 | -------------------------------------------------------------------------------- /OptimizelySDK.Tests/EntityTests/FeatureVariableTest.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019-2020, Optimizely 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | using System; 18 | using NUnit.Framework; 19 | using OptimizelySDK.Entity; 20 | 21 | namespace OptimizelySDK.Tests.EntityTests 22 | { 23 | [TestFixture] 24 | public class FeatureVariableTest 25 | { 26 | [Test] 27 | public void TestFeatureVariableTypeName() 28 | { 29 | Assert.AreEqual( 30 | FeatureVariable.GetFeatureVariableTypeName(FeatureVariable.BOOLEAN_TYPE), 31 | "GetFeatureVariableBoolean"); 32 | Assert.AreEqual(FeatureVariable.GetFeatureVariableTypeName(FeatureVariable.DOUBLE_TYPE), 33 | "GetFeatureVariableDouble"); 34 | Assert.AreEqual( 35 | FeatureVariable.GetFeatureVariableTypeName(FeatureVariable.INTEGER_TYPE), 36 | "GetFeatureVariableInteger"); 37 | Assert.AreEqual(FeatureVariable.GetFeatureVariableTypeName(FeatureVariable.STRING_TYPE), 38 | "GetFeatureVariableString"); 39 | Assert.AreEqual(FeatureVariable.GetFeatureVariableTypeName(FeatureVariable.JSON_TYPE), 40 | "GetFeatureVariableJSON"); 41 | } 42 | 43 | [Test] 44 | public void TestConstantValues() 45 | { 46 | Assert.AreEqual(FeatureVariable.BOOLEAN_TYPE, "boolean"); 47 | Assert.AreEqual(FeatureVariable.DOUBLE_TYPE, "double"); 48 | Assert.AreEqual(FeatureVariable.INTEGER_TYPE, "integer"); 49 | Assert.AreEqual(FeatureVariable.STRING_TYPE, "string"); 50 | Assert.AreEqual(FeatureVariable.JSON_TYPE, "json"); 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /OptimizelySDK.Tests/EventTests/DefaultEventDispatcherTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using Moq; 4 | using Newtonsoft.Json.Linq; 5 | using NUnit.Framework; 6 | using OptimizelySDK.Entity; 7 | using OptimizelySDK.Event; 8 | using OptimizelySDK.Event.Builder; 9 | using OptimizelySDK.Event.Dispatcher; 10 | using OptimizelySDK.Logger; 11 | 12 | namespace OptimizelySDK.Tests.EventTests 13 | { 14 | [TestFixture] 15 | public class DefaultEventDispatcherTest 16 | { 17 | [Test] 18 | public void TestDispatchEvent() 19 | { 20 | var logEvent = new LogEvent("", 21 | new Dictionary 22 | { 23 | { "accountId", "1234" }, 24 | { "projectId", "9876" }, 25 | { "visitorId", "testUser" }, 26 | }, 27 | "POST", 28 | new Dictionary 29 | { 30 | { "Content-Type", "application/json" }, 31 | }); 32 | 33 | var expectionedOptions = new Dictionary 34 | { 35 | { "headers", logEvent.Headers }, 36 | { "json", logEvent.Params }, 37 | { "timeout", 10 }, 38 | { "connect_timeout", 10 }, 39 | }; 40 | 41 | //TODO: Have to mock http calls. Will discuss with Randall. 42 | var eventDispatcher = new DefaultEventDispatcher(new Mock().Object); 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /OptimizelySDK.Tests/EventTests/TestForwardingEventDispatcher.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using NUnit.Framework; 7 | using OptimizelySDK.Event; 8 | using OptimizelySDK.Event.Dispatcher; 9 | using OptimizelySDK.Logger; 10 | 11 | namespace OptimizelySDK.Tests.EventTests 12 | { 13 | public class TestForwardingEventDispatcher : IEventDispatcher 14 | { 15 | public ILogger Logger { get; set; } 16 | public bool IsUpdated { get; set; } = false; 17 | 18 | public void DispatchEvent(LogEvent logEvent) 19 | { 20 | Assert.AreEqual(logEvent.HttpVerb, "POST"); 21 | Assert.AreEqual(logEvent.Url, EventFactory.EVENT_ENDPOINT); 22 | IsUpdated = true; 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /OptimizelySDK.Tests/IntegrationEmptyDatafile.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "4", 3 | "rollouts": [], 4 | "anonymizeIP": true, 5 | "projectId": "20441150641", 6 | "variables": [], 7 | "featureFlags": [], 8 | "experiments": [], 9 | "audiences": [], 10 | "groups": [], 11 | "integrations": [], 12 | "attributes": [], 13 | "accountId": "11467598500", 14 | "events": [], 15 | "revision": "241", 16 | "sdkKey": "EmptyIntegrationDatafile", 17 | "environmentKey": "Production" 18 | } 19 | -------------------------------------------------------------------------------- /OptimizelySDK.Tests/IntegrationNonOdpDatafile.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "4", 3 | "rollouts": [ 4 | { 5 | "experiments": [ 6 | ], 7 | "id": "18309384009" 8 | } 9 | ], 10 | "typedAudiences": [], 11 | "anonymizeIP": true, 12 | "projectId": "18326250003", 13 | "variables": [], 14 | "featureFlags": [ 15 | { 16 | "experimentIds": [], 17 | "rolloutId": "18309384009", 18 | "variables": [ 19 | { 20 | "defaultValue": "", 21 | "type": "string", 22 | "id": "18323951833", 23 | "key": "var_1" 24 | } 25 | ], 26 | "id": "18244658520", 27 | "key": "empty_rollout" 28 | }, 29 | { 30 | "experimentIds": [], 31 | "rolloutId": "", 32 | "variables": [ 33 | { 34 | "defaultValue": "", 35 | "type": "string", 36 | "id": "2832355113", 37 | "key": "var_2" 38 | } 39 | ], 40 | "id": "24246538512", 41 | "key": "empty_rollout_id" 42 | } 43 | ], 44 | "experiments": [], 45 | "audiences": [ 46 | { 47 | "conditions": "[\"or\", {\"match\": \"exact\", \"name\": \"$opt_dummy_attribute\", \"type\": \"custom_attribute\", \"value\": \"$opt_dummy_value\"}]", 48 | "id": "$opt_dummy_audience", 49 | "name": "Optimizely-Generated Audience for Backwards Compatibility" 50 | } 51 | ], 52 | "groups": [], 53 | "integrations": [ 54 | { 55 | "key": "not-odp", 56 | "host": "https://example.com", 57 | "publicKey": "CleAr1y-!a-R3a7-pUbl1c-k3y" 58 | } 59 | ], 60 | "attributes": [], 61 | "botFiltering": false, 62 | "accountId": "8272261422", 63 | "events": [], 64 | "revision": "2" 65 | } 66 | -------------------------------------------------------------------------------- /OptimizelySDK.Tests/InvalidEventDispatcher.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017, Optimizely 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | using System; 18 | using OptimizelySDK.Event.Dispatcher; 19 | using OptimizelySDK.Logger; 20 | 21 | namespace OptimizelySDK.Tests 22 | { 23 | internal class InvalidEventDispatcher : IEventDispatcher 24 | { 25 | public ILogger Logger { get; set; } 26 | 27 | public void DispatchEvent(Event.LogEvent logEvent) 28 | { 29 | throw new Exception("Invalid dispatch event"); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /OptimizelySDK.Tests/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | 4 | // General Information about an assembly is controlled through the following 5 | // set of attributes. Change these attribute values to modify the information 6 | // associated with an assembly. 7 | [assembly: AssemblyTitle("OptimizelySDK.Tests")] 8 | [assembly: AssemblyDescription("")] 9 | [assembly: AssemblyConfiguration("")] 10 | [assembly: AssemblyCompany("")] 11 | [assembly: AssemblyProduct("OptimizelySDK.Tests")] 12 | [assembly: AssemblyCopyright("Copyright © 2017-2023")] 13 | [assembly: AssemblyTrademark("")] 14 | [assembly: AssemblyCulture("")] 15 | 16 | // Setting ComVisible to false makes the types in this assembly not visible 17 | // to COM components. If you need to access a type in this assembly from 18 | // COM, set the ComVisible attribute to true on that type. 19 | [assembly: ComVisible(false)] 20 | 21 | // The following GUID is for the ID of the typelib if this project is exposed to COM 22 | [assembly: Guid("ab9820af-3125-4ed3-9344-07bf570b4c30")] 23 | 24 | // Version information for an assembly consists of the following four values: 25 | // 26 | // Major Version 27 | // Minor Version 28 | // Build Number 29 | // Revision 30 | // 31 | // You can specify all the values or you can default the Revision and Build Numbers 32 | // by using the '*' as shown below: 33 | [assembly: AssemblyVersion("4.1.0.0")] 34 | [assembly: AssemblyFileVersion("4.1.0.0")] 35 | [assembly: AssemblyInformationalVersion("4.1.0")] // Used by NuGet. 36 | -------------------------------------------------------------------------------- /OptimizelySDK.Tests/TestBucketer.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017, Optimizely 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | namespace OptimizelySDK.Tests 18 | { 19 | internal class TestBucketer : Bucketing.Bucketer 20 | { 21 | public TestBucketer(Logger.ILogger logger) 22 | : base(logger) { } 23 | 24 | public void SetBucketValues(int[] bucketValues) 25 | { 26 | BucketValues = bucketValues; 27 | Ndx = 0; 28 | } 29 | 30 | private int[] BucketValues { get; set; } 31 | 32 | private int Ndx = 0; 33 | 34 | public override int GenerateBucketValue(string bucketingId) 35 | { 36 | if (BucketValues == null || BucketValues.Length == 0) 37 | { 38 | return 0; 39 | } 40 | 41 | Ndx %= BucketValues.Length; 42 | return BucketValues[Ndx++]; 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /OptimizelySDK.Tests/TestSetup.cs: -------------------------------------------------------------------------------- 1 | using System.Globalization; 2 | using System.Threading; 3 | using NUnit.Framework; 4 | 5 | namespace OptimizelySDK.Tests 6 | { 7 | [SetUpFixture] 8 | public class TestSetup 9 | { 10 | [SetUp] 11 | public void Init() 12 | { 13 | /* There are some issues doing assertions on tests with floating point numbers using the .ToString() 14 | * method, as it's culture dependent. EG: TestGetFeatureVariableValueForTypeGivenFeatureFlagIsNotEnabledForUser, 15 | * assigning the culture to English will make this kind of tests to work on others culture based systems. */ 16 | Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture("en-US"); 17 | } 18 | 19 | [TearDown] 20 | public void Cleanup() 21 | { 22 | // Empty, but required: https://nunit.org/nunitv2/docs/2.6.4/setupFixture.html 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /OptimizelySDK.Tests/UtilsTests/ExceptionExtensionsTest.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019, Optimizely 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | using System; 18 | using NUnit.Framework; 19 | using OptimizelySDK.Utils; 20 | 21 | namespace OptimizelySDK.Tests.UtilsTests 22 | { 23 | public class ExceptionExtensionsTest 24 | { 25 | [Test] 26 | public void TestGetAllMessagesReturnsAllInnerExceptionMessages() 27 | { 28 | var exception = new Exception("Outer exception.", 29 | new Exception("Inner exception.", new Exception("Second level inner exception."))); 30 | var expectedMessage = 31 | "Outer exception.\nInner exception.\nSecond level inner exception."; 32 | 33 | Assert.AreEqual(expectedMessage, exception.GetAllMessages()); 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /OptimizelySDK.Tests/ValidEventDispatcher.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017, Optimizely 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | using OptimizelySDK.Event.Dispatcher; 18 | using OptimizelySDK.Logger; 19 | 20 | namespace OptimizelySDK.Tests 21 | { 22 | internal class ValidEventDispatcher : IEventDispatcher 23 | { 24 | public ILogger Logger { get; set; } 25 | public void DispatchEvent(Event.LogEvent logEvent) { } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /OptimizelySDK.Tests/emptydatafile.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "4", 3 | "rollouts": [], 4 | "anonymizeIP": true, 5 | "projectId": "10431130345", 6 | "variables": [], 7 | "featureFlags": [], 8 | "experiments": [], 9 | "audiences": [], 10 | "groups": [], 11 | "attributes": [], 12 | "accountId": "10367498574", 13 | "events": [], 14 | "revision": "241", 15 | "sdkKey": "emptydatafile", 16 | "environmentKey": "Production" 17 | } 18 | -------------------------------------------------------------------------------- /OptimizelySDK.Tests/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /OptimizelySDK.Tests/unsupported_version_datafile.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "5", 3 | "rollouts": [], 4 | "projectId": "10431130345", 5 | "variables": [], 6 | "featureFlags": [], 7 | "experiments": [ 8 | { 9 | "status": "Running", 10 | "key": "ab_running_exp_untargeted", 11 | "layerId": "10417730432", 12 | "trafficAllocation": [ 13 | { 14 | "entityId": "10418551353", 15 | "endOfRange": 10000 16 | } 17 | ], 18 | "audienceIds": [], 19 | "variations": [ 20 | { 21 | "variables": [], 22 | "id": "10418551353", 23 | "key": "all_traffic_variation" 24 | }, 25 | { 26 | "variables": [], 27 | "id": "10418510624", 28 | "key": "no_traffic_variation" 29 | } 30 | ], 31 | "forcedVariations": {}, 32 | "id": "10420810910" 33 | } 34 | ], 35 | "audiences": [], 36 | "groups": [], 37 | "attributes": [], 38 | "accountId": "10367498574", 39 | "events": [ 40 | { 41 | "experimentIds": [ 42 | "10420810910" 43 | ], 44 | "id": "10404198134", 45 | "key": "winning" 46 | } 47 | ], 48 | "revision": "1337" 49 | } 50 | -------------------------------------------------------------------------------- /OptimizelySDK.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/optimizely/csharp-sdk/282b7cf7577d1adf2fedaad33625dab34aea5fa6/OptimizelySDK.png -------------------------------------------------------------------------------- /OptimizelySDK/AudienceConditions/AndCondition.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019-2022, Optimizely 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | using OptimizelySDK.Entity; 18 | using OptimizelySDK.Logger; 19 | 20 | namespace OptimizelySDK.AudienceConditions 21 | { 22 | /// 23 | /// Represents an 'AND' condition operation for audience evaluation. 24 | /// 25 | public class AndCondition : ICondition 26 | { 27 | public ICondition[] Conditions { get; set; } 28 | 29 | public bool? Evaluate(ProjectConfig config, OptimizelyUserContext userContext, 30 | ILogger logger 31 | ) 32 | { 33 | // According to the matrix: 34 | // false and true is false 35 | // false and null is false 36 | // true and null is null. 37 | // true and false is false 38 | // true and true is true 39 | // null and null is null 40 | var foundNull = false; 41 | foreach (var condition in Conditions) 42 | { 43 | var result = condition.Evaluate(config, userContext, logger); 44 | if (result == null) 45 | { 46 | foundNull = true; 47 | } 48 | else if (result == false) 49 | { 50 | return false; 51 | } 52 | } 53 | 54 | if (foundNull) 55 | { 56 | return null; 57 | } 58 | 59 | return true; 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /OptimizelySDK/AudienceConditions/AudienceIdCondition.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019-2022, Optimizely 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | using OptimizelySDK.Logger; 18 | 19 | namespace OptimizelySDK.AudienceConditions 20 | { 21 | /// 22 | /// Represents Audience Id condition for audience evaluation. 23 | /// 24 | public class AudienceIdCondition : ICondition 25 | { 26 | public string AudienceId { get; set; } 27 | 28 | public bool? Evaluate(ProjectConfig config, OptimizelyUserContext userContext, 29 | ILogger logger 30 | ) 31 | { 32 | var audience = config?.GetAudience(AudienceId); 33 | if (audience == null || string.IsNullOrEmpty(audience.Id)) 34 | { 35 | return null; 36 | } 37 | 38 | logger.Log(LogLevel.DEBUG, 39 | $@"Starting to evaluate audience ""{AudienceId}"" with conditions: { 40 | audience.ConditionsString}"); 41 | var result = audience.ConditionList.Evaluate(config, userContext, logger); 42 | var resultText = result?.ToString().ToUpper() ?? "UNKNOWN"; 43 | logger.Log(LogLevel.DEBUG, $@"Audience ""{AudienceId}"" evaluated to {resultText}"); 44 | 45 | return result; 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /OptimizelySDK/AudienceConditions/EmptyCondition.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019, 2022, Optimizely 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | using OptimizelySDK.Entity; 18 | using OptimizelySDK.Logger; 19 | 20 | namespace OptimizelySDK.AudienceConditions 21 | { 22 | /// 23 | /// Represents a condition that evaluates to true for every audience evaluation. 24 | /// 25 | public class EmptyCondition : ICondition 26 | { 27 | public bool? Evaluate(ProjectConfig config, OptimizelyUserContext userContext, 28 | ILogger logger 29 | ) 30 | { 31 | return true; 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /OptimizelySDK/AudienceConditions/ICondition.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019, 2022, Optimizely 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | using OptimizelySDK.Logger; 18 | 19 | namespace OptimizelySDK.AudienceConditions 20 | { 21 | /// 22 | /// Interface implemented by all condition classes for audience evaluation. 23 | /// 24 | public interface ICondition 25 | { 26 | bool? Evaluate(ProjectConfig config, OptimizelyUserContext userContext, ILogger logger); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /OptimizelySDK/AudienceConditions/NotCondition.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019-2022, Optimizely 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | using OptimizelySDK.Entity; 18 | using OptimizelySDK.Logger; 19 | 20 | namespace OptimizelySDK.AudienceConditions 21 | { 22 | /// 23 | /// Represents a 'NOT' condition operation for audience evaluation. 24 | /// 25 | public class NotCondition : ICondition 26 | { 27 | public ICondition Condition { get; set; } 28 | 29 | public bool? Evaluate(ProjectConfig config, OptimizelyUserContext userContext, 30 | ILogger logger 31 | ) 32 | { 33 | var result = Condition?.Evaluate(config, userContext, logger); 34 | return result == null ? null : !result; 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /OptimizelySDK/AudienceConditions/OrCondition.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019-2022, Optimizely 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | using OptimizelySDK.Entity; 18 | using OptimizelySDK.Logger; 19 | 20 | namespace OptimizelySDK.AudienceConditions 21 | { 22 | /// 23 | /// Represents an 'OR' condition operation for audience evaluation. 24 | /// 25 | public class OrCondition : ICondition 26 | { 27 | public ICondition[] Conditions { get; set; } 28 | 29 | public bool? Evaluate(ProjectConfig config, OptimizelyUserContext userContext, 30 | ILogger logger 31 | ) 32 | { 33 | // According to the matrix: 34 | // true returns true 35 | // false or null is null 36 | // false or false is false 37 | // null or null is null 38 | var foundNull = false; 39 | foreach (var condition in Conditions) 40 | { 41 | var result = condition.Evaluate(config, userContext, logger); 42 | if (result == null) 43 | { 44 | foundNull = true; 45 | } 46 | else if (result == true) 47 | { 48 | return true; 49 | } 50 | } 51 | 52 | if (foundNull) 53 | { 54 | return null; 55 | } 56 | 57 | return false; 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /OptimizelySDK/Bucketing/Decision.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017, Optimizely 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | using System.Collections.Generic; 18 | 19 | namespace OptimizelySDK.Bucketing 20 | { 21 | public class Decision 22 | { 23 | /// 24 | /// The ID of the Variation into which the user was bucketed. 25 | /// 26 | public string VariationId { get; set; } 27 | 28 | /// 29 | /// Initialize a Decision object. 30 | /// 31 | /// The ID of the variation into which the user was bucketed. 32 | public Decision(string variationId) 33 | { 34 | VariationId = variationId; 35 | } 36 | 37 | public Dictionary ToMap() 38 | { 39 | return new Dictionary 40 | { 41 | { UserProfile.VARIATION_ID_KEY, VariationId }, 42 | }; 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /OptimizelySDK/Bucketing/UserProfileService.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017, Optimizely 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | using System; 18 | using System.Collections.Generic; 19 | 20 | namespace OptimizelySDK.Bucketing 21 | { 22 | /// 23 | /// Class encapsulating user profile service functionality. 24 | /// Override with your own implementation for storing and retrieving the user profile. 25 | /// 26 | public interface UserProfileService 27 | { 28 | Dictionary Lookup(String userId); 29 | 30 | void Save(Dictionary userProfile); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /OptimizelySDK/Bucketing/UserProfileUtil.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017, Optimizely 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | using System.Collections.Generic; 18 | using System.Linq; 19 | 20 | namespace OptimizelySDK.Bucketing 21 | { 22 | public class UserProfileUtil 23 | { 24 | /// 25 | /// Validate whether a Dictionary can be transformed into a UserProfile. 26 | /// 27 | /// 28 | /// True if the map can be converted into a UserProfile. False if the map cannot be converted. 29 | public static bool IsValidUserProfileMap(Dictionary map) 30 | { 31 | // The Map must contain a value for the user ID and experiment bucket map 32 | if (!map.ContainsKey(UserProfile.USER_ID_KEY) || 33 | !map.ContainsKey(UserProfile.EXPERIMENT_BUCKET_MAP_KEY)) 34 | { 35 | return false; 36 | } 37 | 38 | // the map is good enough for us to use 39 | return true; 40 | } 41 | 42 | /// 43 | /// Convert a Map to a UserProfile instance. 44 | /// 45 | /// The map to construct the UserProfile 46 | /// A UserProfile instance. 47 | public static UserProfile ConvertMapToUserProfile(Dictionary map) 48 | { 49 | var experimentBucketMap = 50 | (Dictionary>)map[ 51 | UserProfile.EXPERIMENT_BUCKET_MAP_KEY]; 52 | var decisions = experimentBucketMap.ToDictionary( 53 | kvp => kvp.Key, 54 | kvp => new Decision(kvp.Value[UserProfile.VARIATION_ID_KEY])); 55 | 56 | return new UserProfile( 57 | (string)map[UserProfile.USER_ID_KEY], 58 | decisions); 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /OptimizelySDK/Config/FallbackProjectConfigManager.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019, 2022-2023 Optimizely 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | using System; 18 | 19 | namespace OptimizelySDK.Config 20 | { 21 | /// 22 | /// Implementation of ProjectConfigManager interface that simply 23 | /// returns the stored ProjectConfig instance which is immmutable. 24 | /// 25 | public class FallbackProjectConfigManager : ProjectConfigManager 26 | { 27 | private ProjectConfig ProjectConfig; 28 | 29 | /// 30 | /// Initializes a new instance of the FallbackProjectConfigManager class 31 | /// with the given ProjectConfig instance. 32 | /// 33 | /// Instance of ProjectConfig. 34 | public FallbackProjectConfigManager(ProjectConfig config) 35 | { 36 | ProjectConfig = config; 37 | } 38 | 39 | /// 40 | /// Returns the stored ProjectConfig instance. 41 | /// 42 | /// ProjectConfig instance 43 | public ProjectConfig GetConfig() 44 | { 45 | return ProjectConfig; 46 | } 47 | 48 | /// 49 | /// SDK Key for Fallback is not used and always null 50 | /// 51 | public virtual string SdkKey => null; 52 | 53 | /// 54 | /// Access to current cached project configuration 55 | /// 56 | /// ProjectConfig instance 57 | public virtual ProjectConfig CachedProjectConfig => ProjectConfig; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /OptimizelySDK/Config/ProjectConfigManager.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019, 2022-2023 Optimizely 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | namespace OptimizelySDK.Config 18 | { 19 | /// 20 | /// Interface for fetching ProjectConfig instance. 21 | /// 22 | public interface ProjectConfigManager 23 | { 24 | /// 25 | /// Implementations of this method should block until a datafile is available. 26 | /// 27 | /// ProjectConfig instance 28 | ProjectConfig GetConfig(); 29 | 30 | /// 31 | /// SDK key in use for this project 32 | /// 33 | string SdkKey { get; } 34 | 35 | /// 36 | /// Access to current cached project configuration 37 | /// 38 | /// ProjectConfig instance or null if project config is not ready 39 | ProjectConfig CachedProjectConfig { get; } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /OptimizelySDK/Entity/Attribute.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017, Optimizely 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | namespace OptimizelySDK.Entity 18 | { 19 | public class Attribute : IdKeyEntity { } 20 | } 21 | -------------------------------------------------------------------------------- /OptimizelySDK/Entity/Entity.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017, Optimizely 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | using System; 18 | 19 | namespace OptimizelySDK.Entity 20 | { 21 | public abstract class Entity : ICloneable 22 | { 23 | public object Clone() 24 | { 25 | return MemberwiseClone(); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /OptimizelySDK/Entity/Event.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017, Optimizely 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | namespace OptimizelySDK.Entity 18 | { 19 | public class Event : IdKeyEntity 20 | { 21 | /// 22 | /// Associated Experiment with this Event 23 | /// 24 | public string[] ExperimentIds { get; set; } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /OptimizelySDK/Entity/EventTags.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017, Optimizely 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | using System.Collections.Generic; 18 | using OptimizelySDK.Logger; 19 | 20 | namespace OptimizelySDK.Entity 21 | { 22 | public class EventTags : Dictionary 23 | { 24 | public EventTags FilterNullValues(ILogger logger) 25 | { 26 | var answer = new EventTags(); 27 | foreach (var pair in this) 28 | { 29 | if (pair.Value != null) 30 | { 31 | answer[pair.Key] = pair.Value; 32 | } 33 | else 34 | { 35 | logger.Log(LogLevel.ERROR, 36 | $"[EventTags] Null value for key {pair.Key} removed and will not be sent to results."); 37 | } 38 | } 39 | 40 | return answer; 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /OptimizelySDK/Entity/FeatureDecision.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017, 2019, Optimizely 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | namespace OptimizelySDK.Entity 18 | { 19 | public class FeatureDecision 20 | { 21 | public const string DECISION_SOURCE_FEATURE_TEST = "feature-test"; 22 | public const string DECISION_SOURCE_ROLLOUT = "rollout"; 23 | 24 | public Experiment Experiment { get; } 25 | public Variation Variation { get; } 26 | public string Source { get; } 27 | 28 | public FeatureDecision(Experiment experiment, Variation variation, string source) 29 | { 30 | Experiment = experiment; 31 | Variation = variation; 32 | Source = source; 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /OptimizelySDK/Entity/FeatureFlag.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017, Optimizely 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | using System.Collections.Generic; 18 | using OptimizelySDK.Utils; 19 | 20 | namespace OptimizelySDK.Entity 21 | { 22 | public class FeatureFlag : IdKeyEntity 23 | { 24 | public string RolloutId { get; set; } 25 | 26 | public List ExperimentIds { get; set; } 27 | 28 | private List _Variables; 29 | 30 | public List Variables 31 | { 32 | get => _Variables; 33 | set 34 | { 35 | _Variables = value; 36 | 37 | // Generating Feature Variable key map. 38 | if (_Variables != null) 39 | { 40 | VariableKeyToFeatureVariableMap = 41 | ConfigParser.GenerateMap(_Variables, v => v.Key, true); 42 | } 43 | } 44 | } 45 | 46 | public Dictionary VariableKeyToFeatureVariableMap { get; set; } 47 | 48 | public FeatureVariable GetFeatureVariableFromKey(string variableKey) 49 | { 50 | if (VariableKeyToFeatureVariableMap != null && 51 | VariableKeyToFeatureVariableMap.ContainsKey(variableKey)) 52 | { 53 | return VariableKeyToFeatureVariableMap[variableKey]; 54 | } 55 | 56 | return null; 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /OptimizelySDK/Entity/FeatureVariableUsage.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017, Optimizely 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | namespace OptimizelySDK.Entity 18 | { 19 | public class FeatureVariableUsage : Entity 20 | { 21 | /// 22 | /// Audience ID 23 | /// 24 | public string Id { get; set; } 25 | 26 | /// 27 | /// Audience Name 28 | /// 29 | public string Value { get; set; } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /OptimizelySDK/Entity/ForcedVariation.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017, Optimizely 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | namespace OptimizelySDK.Entity 18 | { 19 | public class ForcedVariation : IdKeyEntity { } 20 | } 21 | -------------------------------------------------------------------------------- /OptimizelySDK/Entity/Group.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017, Optimizely 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | namespace OptimizelySDK.Entity 18 | { 19 | public class Group : Entity 20 | { 21 | /// 22 | /// Group ID 23 | /// 24 | public string Id { get; set; } 25 | 26 | /// 27 | /// Group policy 28 | /// 29 | public string Policy { get; set; } 30 | 31 | /// 32 | /// List of Experiments in the group 33 | /// 34 | public Experiment[] Experiments { get; set; } 35 | 36 | /// 37 | /// List of Traffic allocation of experiments in the group 38 | /// 39 | public TrafficAllocation[] TrafficAllocation { get; set; } 40 | 41 | #if false 42 | /** 43 | * @param $trafficAllocation array Traffic allocation of experiments in group. 44 | */ 45 | public function setTrafficAllocation($trafficAllocation) 46 | { 47 | $this->_trafficAllocation = 48 | ConfigParser::generateMap($trafficAllocation, null, TrafficAllocation::class); 49 | } 50 | #endif 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /OptimizelySDK/Entity/IdKeyEntity.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017, Optimizely 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | using System; 18 | 19 | namespace OptimizelySDK.Entity 20 | { 21 | /// 22 | /// Base class for Entities that have an ID and Key 23 | /// 24 | public abstract class IdKeyEntity : Entity, IEquatable 25 | { 26 | /// 27 | /// Entity ID 28 | /// 29 | public string Id { get; set; } 30 | 31 | /// 32 | /// Entity Key 33 | /// 34 | public string Key { get; set; } 35 | 36 | public override bool Equals(object other) 37 | { 38 | var entity = other as IdKeyEntity; 39 | if (entity == null || other.GetType() != GetType()) 40 | { 41 | return false; 42 | } 43 | 44 | return Id == entity.Id && Key == entity.Key; 45 | } 46 | 47 | public override int GetHashCode() 48 | { 49 | return (Id + Key).GetHashCode(); 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /OptimizelySDK/Entity/Integration.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022, Optimizely 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | using System.Text; 18 | 19 | namespace OptimizelySDK.Entity 20 | { 21 | public class Integration : IdKeyEntity 22 | { 23 | public string Host { get; set; } 24 | 25 | public string PublicKey { get; set; } 26 | 27 | public override string ToString() 28 | { 29 | var sb = new StringBuilder(); 30 | sb.AppendFormat("Integration{{key='{0}'", Key); 31 | 32 | if (!string.IsNullOrEmpty(Host)) 33 | { 34 | sb.AppendFormat(", host='{0}'", Host); 35 | } 36 | 37 | if (!string.IsNullOrEmpty(PublicKey)) 38 | { 39 | sb.AppendFormat(", publicKey='{0}'", PublicKey); 40 | } 41 | 42 | sb.Append("}"); 43 | 44 | return sb.ToString(); 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /OptimizelySDK/Entity/Result.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2021 Optimizely 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | using OptimizelySDK.OptimizelyDecisions; 18 | 19 | namespace OptimizelySDK.Entity 20 | { 21 | public class Result 22 | { 23 | public T ResultObject; 24 | public DecisionReasons DecisionReasons; 25 | 26 | public static Result NewResult(T resultObject, DecisionReasons decisionReasons) 27 | { 28 | return new Result { DecisionReasons = decisionReasons, ResultObject = resultObject }; 29 | } 30 | 31 | public Result SetReasons(DecisionReasons decisionReasons) 32 | { 33 | DecisionReasons = decisionReasons; 34 | 35 | return this; 36 | } 37 | 38 | public static Result NullResult(DecisionReasons decisionReasons) 39 | { 40 | return NewResult(default, decisionReasons); 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /OptimizelySDK/Entity/Rollout.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017, Optimizely 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | using System.Collections.Generic; 18 | 19 | namespace OptimizelySDK.Entity 20 | { 21 | public class Rollout : IdKeyEntity 22 | { 23 | public List Experiments { get; set; } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /OptimizelySDK/Entity/TrafficAllocation.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017, Optimizely 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | namespace OptimizelySDK.Entity 18 | { 19 | public class TrafficAllocation : Entity 20 | { 21 | /// 22 | /// String ID representing experiment or variation depending on parent 23 | /// 24 | public string EntityId { get; set; } 25 | 26 | /// 27 | /// Last bucket number for the experiment or variation 28 | /// 29 | public int EndOfRange { get; set; } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /OptimizelySDK/Entity/UserAttributes.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2018,2020, Optimizely 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | using System.Collections.Generic; 18 | 19 | namespace OptimizelySDK.Entity 20 | { 21 | public class UserAttributes : Dictionary 22 | { 23 | public UserAttributes() : base() { } 24 | 25 | public UserAttributes(IDictionary dictionary) : base(dictionary) { } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /OptimizelySDK/Entity/Variation.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017, Optimizely 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | using System.Collections.Generic; 18 | using OptimizelySDK.Utils; 19 | 20 | namespace OptimizelySDK.Entity 21 | { 22 | public class Variation : IdKeyEntity 23 | { 24 | private List _FeatureVariableUsageInstances; 25 | 26 | [Newtonsoft.Json.JsonProperty("variables")] 27 | public List FeatureVariableUsageInstances 28 | { 29 | get => _FeatureVariableUsageInstances; 30 | set 31 | { 32 | _FeatureVariableUsageInstances = value; 33 | 34 | // Generating Variable Usage key map. 35 | if (_FeatureVariableUsageInstances != null) 36 | { 37 | VariableIdToVariableUsageInstanceMap = 38 | ConfigParser.GenerateMap( 39 | _FeatureVariableUsageInstances, v => v.Id.ToString(), true); 40 | } 41 | } 42 | } 43 | 44 | public Dictionary VariableIdToVariableUsageInstanceMap 45 | { 46 | get; 47 | set; 48 | } 49 | 50 | public FeatureVariableUsage GetFeatureVariableUsageFromId(string variableId) 51 | { 52 | if (VariableIdToVariableUsageInstanceMap != null && 53 | VariableIdToVariableUsageInstanceMap.ContainsKey(variableId)) 54 | { 55 | return VariableIdToVariableUsageInstanceMap[variableId]; 56 | } 57 | 58 | return null; 59 | } 60 | 61 | public bool? FeatureEnabled { get; set; } 62 | 63 | public bool IsFeatureEnabled => FeatureEnabled ?? false; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /OptimizelySDK/ErrorHandler/DefaultErrorHandler.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017, Optimizely 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | using System; 18 | using OptimizelySDK.Logger; 19 | 20 | namespace OptimizelySDK.ErrorHandler 21 | { 22 | public class DefaultErrorHandler : IErrorHandler 23 | { 24 | /// 25 | /// Create a DefaultErrorHandler 26 | /// 27 | /// Optional logger to be used to include exception message in the log 28 | /// Whether or not to actaully throw the exceptions, true by default 29 | public DefaultErrorHandler(ILogger logger = null, bool throwExceptions = true) 30 | { 31 | Logger = logger; 32 | ThrowExceptions = throwExceptions; 33 | } 34 | 35 | public void HandleError(Exception exception) 36 | { 37 | if (Logger != null) 38 | { 39 | Logger.Log(LogLevel.ERROR, exception.Message); 40 | } 41 | 42 | if (ThrowExceptions) 43 | { 44 | throw exception; 45 | } 46 | } 47 | 48 | /// 49 | /// An optional Logger include exceptions in your log 50 | /// 51 | private ILogger Logger; 52 | 53 | private bool ThrowExceptions; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /OptimizelySDK/ErrorHandler/IErrorHandler.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017, Optimizely 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | using System; 18 | 19 | namespace OptimizelySDK.ErrorHandler 20 | { 21 | public interface IErrorHandler 22 | { 23 | void HandleError(Exception exception); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /OptimizelySDK/ErrorHandler/NoOpErrorHandler.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017, Optimizely 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | using System; 18 | using OptimizelySDK.Logger; 19 | 20 | namespace OptimizelySDK.ErrorHandler 21 | { 22 | public class NoOpErrorHandler : DefaultErrorHandler 23 | { 24 | public NoOpErrorHandler(ILogger logger = null) 25 | : base(logger, false) { } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /OptimizelySDK/Event/Builder/Params.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017, 2019-2020, Optimizely 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | using System; 18 | using OptimizelySDK.Event.Entity; 19 | 20 | namespace OptimizelySDK.Event.Builder 21 | { 22 | [Obsolete("This class is deprecated.")] 23 | public static class Params 24 | { 25 | public const string ACCOUNT_ID = "account_id"; 26 | public const string ANONYMIZE_IP = "anonymize_ip"; 27 | public const string CAMPAIGN_ID = "campaign_id"; 28 | public const string CLIENT_ENGINE = "client_name"; 29 | public const string CLIENT_VERSION = "client_version"; 30 | public const string DECISIONS = "decisions"; 31 | public const string ENRICH_DECISIONS = "enrich_decisions"; 32 | public const string ENTITY_ID = "entity_id"; 33 | public const string EVENTS = "events"; 34 | public const string EXPERIMENT_ID = "experiment_id"; 35 | public const string METADATA = "metadata"; 36 | public const string PROJECT_ID = "project_id"; 37 | public const string REVISION = "revision"; 38 | public const string TIME = "timestamp"; 39 | public const string TIMESTAMP = "timestamp"; 40 | public const string VARIATION_ID = "variation_id"; 41 | public const string VISITOR_ID = "visitorId"; 42 | public const string VISITORS = "visitors"; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /OptimizelySDK/Event/Dispatcher/DefaultEventDispatcher.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017, Optimizely 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | namespace OptimizelySDK.Event.Dispatcher 18 | { 19 | /// 20 | /// Default Event Dispatcher 21 | /// Selects the appropriate dispatcher based on the .Net Framework version 22 | /// 23 | public class DefaultEventDispatcher : 24 | #if NET35 || NET40 25 | WebRequestClientEventDispatcher35 26 | #else 27 | HttpClientEventDispatcher45 28 | #endif 29 | { 30 | public DefaultEventDispatcher(Logger.ILogger logger) 31 | { 32 | Logger = logger; 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /OptimizelySDK/Event/Dispatcher/IEventDispatcher.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017, Optimizely 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | namespace OptimizelySDK.Event.Dispatcher 18 | { 19 | public interface IEventDispatcher 20 | { 21 | Logger.ILogger Logger { get; set; } 22 | 23 | void DispatchEvent(LogEvent logEvent); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /OptimizelySDK/Event/Entity/Decision.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019-2020, Optimizely 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | using Newtonsoft.Json; 18 | 19 | namespace OptimizelySDK.Event.Entity 20 | { 21 | public class Decision 22 | { 23 | [JsonProperty("campaign_id")] 24 | public string CampaignId { get; private set; } 25 | 26 | [JsonProperty("experiment_id")] 27 | public string ExperimentId { get; private set; } 28 | 29 | [JsonProperty("metadata")] 30 | public DecisionMetadata Metadata { get; private set; } 31 | 32 | [JsonProperty("variation_id")] 33 | public string VariationId { get; private set; } 34 | 35 | public Decision() { } 36 | 37 | public Decision(string campaignId, string experimentId, string variationId, 38 | DecisionMetadata metadata = null 39 | ) 40 | { 41 | CampaignId = campaignId; 42 | ExperimentId = experimentId; 43 | Metadata = metadata; 44 | VariationId = variationId; 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /OptimizelySDK/Event/Entity/DecisionMetadata.cs: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * Copyright 2020, Optimizely and contributors 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | using Newtonsoft.Json; 19 | 20 | namespace OptimizelySDK.Event.Entity 21 | { 22 | /// 23 | /// DecisionMetadata captures additional information regarding the decision 24 | /// 25 | public class DecisionMetadata 26 | { 27 | [JsonProperty("flag_key")] 28 | public string FlagKey { get; private set; } 29 | 30 | [JsonProperty("rule_key")] 31 | public string RuleKey { get; private set; } 32 | 33 | [JsonProperty("rule_type")] 34 | public string RuleType { get; private set; } 35 | 36 | [JsonProperty("variation_key")] 37 | public string VariationKey { get; private set; } 38 | 39 | [JsonProperty("enabled")] 40 | public bool Enabled { get; private set; } 41 | 42 | public DecisionMetadata(string flagKey, string ruleKey, string ruleType, 43 | string variationKey = "", bool enabled = false 44 | ) 45 | { 46 | FlagKey = flagKey; 47 | RuleKey = ruleKey; 48 | RuleType = ruleType; 49 | VariationKey = variationKey; 50 | Enabled = enabled; 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /OptimizelySDK/Event/Entity/Snapshot.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019, Optimizely 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | using Newtonsoft.Json; 18 | 19 | namespace OptimizelySDK.Event.Entity 20 | { 21 | public class Snapshot 22 | { 23 | [JsonProperty("decisions", NullValueHandling = NullValueHandling.Ignore)] 24 | public Decision[] Decisions { get; private set; } 25 | 26 | [JsonProperty("events")] 27 | public SnapshotEvent[] Events { get; private set; } 28 | 29 | public Snapshot(SnapshotEvent[] events, Decision[] decisions = null) 30 | { 31 | Events = events; 32 | Decisions = decisions; 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /OptimizelySDK/Event/Entity/UserEvent.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019, Optimizely 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | using System; 18 | 19 | namespace OptimizelySDK.Event.Entity 20 | { 21 | /// 22 | /// Class represent user event 23 | /// 24 | public class UserEvent 25 | { 26 | public EventContext Context { get; protected set; } 27 | public string UUID { get; protected set; } 28 | public long Timestamp { get; protected set; } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /OptimizelySDK/Event/Entity/Visitor.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019, Optimizely 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | using Newtonsoft.Json; 18 | 19 | namespace OptimizelySDK.Event.Entity 20 | { 21 | public class Visitor 22 | { 23 | [JsonProperty("snapshots")] 24 | public Snapshot[] Snapshots { get; private set; } 25 | 26 | [JsonProperty("attributes")] 27 | public VisitorAttribute[] Attributes { get; private set; } 28 | 29 | [JsonProperty("visitor_id")] 30 | public string VisitorId { get; private set; } 31 | 32 | public Visitor(Snapshot[] snapshots, VisitorAttribute[] attributes, string visitorId) 33 | { 34 | Snapshots = snapshots; 35 | Attributes = attributes; 36 | VisitorId = visitorId; 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /OptimizelySDK/Event/Entity/VisitorAttribute.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019, Optimizely 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | using Newtonsoft.Json; 18 | 19 | namespace OptimizelySDK.Event.Entity 20 | { 21 | public class VisitorAttribute 22 | { 23 | [JsonProperty("entity_id")] 24 | public string EntityId { get; set; } 25 | 26 | [JsonProperty("key")] 27 | public string Key { get; set; } 28 | 29 | [JsonProperty("type")] 30 | public string Type { get; set; } 31 | 32 | [JsonProperty("value")] 33 | public object Value { get; set; } 34 | 35 | public VisitorAttribute(string entityId, string key, string type, object value) 36 | { 37 | EntityId = entityId; 38 | Key = key; 39 | Type = type; 40 | Value = value; 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /OptimizelySDK/Event/EventProcessor.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019, Optimizely 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | using OptimizelySDK.Event.Entity; 18 | 19 | namespace OptimizelySDK.Event 20 | { 21 | /** 22 | * EventProcessor interface is used to provide an intermediary processing stage within 23 | * event production. It's assumed that the EventProcessor dispatches events via a provided 24 | * EventDispatcher 25 | **/ 26 | public interface EventProcessor 27 | { 28 | void Process(UserEvent userEvent); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /OptimizelySDK/Event/ForwardingEventProcessor.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019, Optimizely 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | using System; 18 | using OptimizelySDK.ErrorHandler; 19 | using OptimizelySDK.Event.Dispatcher; 20 | using OptimizelySDK.Event.Entity; 21 | using OptimizelySDK.Logger; 22 | using OptimizelySDK.Notifications; 23 | 24 | namespace OptimizelySDK.Event 25 | { 26 | public class ForwardingEventProcessor : EventProcessor 27 | { 28 | private ILogger Logger; 29 | private IErrorHandler ErrorHandler; 30 | private IEventDispatcher EventDispatcher; 31 | private NotificationCenter NotificationCenter; 32 | 33 | public ForwardingEventProcessor(IEventDispatcher eventDispatcher, 34 | NotificationCenter notificationCenter, ILogger logger = null, 35 | IErrorHandler errorHandler = null 36 | ) 37 | { 38 | EventDispatcher = eventDispatcher; 39 | NotificationCenter = notificationCenter; 40 | Logger = logger ?? new DefaultLogger(); 41 | ErrorHandler = errorHandler ?? new DefaultErrorHandler(Logger, false); 42 | } 43 | 44 | public void Process(UserEvent userEvent) 45 | { 46 | var logEvent = EventFactory.CreateLogEvent(userEvent, Logger); 47 | 48 | try 49 | { 50 | EventDispatcher.DispatchEvent(logEvent); 51 | NotificationCenter?.SendNotifications(NotificationCenter.NotificationType.LogEvent, 52 | logEvent); 53 | } 54 | catch (Exception ex) 55 | { 56 | Logger.Log(LogLevel.ERROR, 57 | $"Error dispatching event: {logEvent.GetParamsAsJson()}. {ex.Message}"); 58 | ErrorHandler.HandleError(ex); 59 | } 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /OptimizelySDK/Event/LogEvent.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017, Optimizely 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | using System.Collections.Generic; 18 | using System.Linq; 19 | 20 | namespace OptimizelySDK.Event 21 | { 22 | public class LogEvent 23 | { 24 | /// 25 | /// string URL to dispatch log event to 26 | /// 27 | public string Url { get; private set; } 28 | 29 | /// 30 | /// Parameters to be set in the log event 31 | /// 32 | public Dictionary Params { get; private set; } 33 | 34 | /// 35 | /// HTTP verb to be used when dispatching the log event 36 | /// 37 | public string HttpVerb { get; private set; } 38 | 39 | /// 40 | /// Headers to be set when sending the request 41 | /// 42 | public Dictionary Headers { get; private set; } 43 | 44 | public string GetParamsAsJson() 45 | { 46 | return Newtonsoft.Json.JsonConvert.SerializeObject(Params); 47 | } 48 | 49 | /// 50 | /// LogEvent Construtor 51 | /// 52 | public LogEvent(string url, Dictionary parameters, string httpVerb, 53 | Dictionary headers 54 | ) 55 | { 56 | Url = url; 57 | Params = parameters; 58 | HttpVerb = httpVerb; 59 | Headers = headers; 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /OptimizelySDK/Logger/DefaultLogger.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017, Optimizely 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | using System.Diagnostics; 18 | 19 | namespace OptimizelySDK.Logger 20 | { 21 | /// 22 | /// TODO: use Log4Net as the default logger? 23 | /// 24 | public class DefaultLogger : ILogger 25 | { 26 | public void Log(LogLevel level, string message) 27 | { 28 | var line = $"[{level}] : {message}"; 29 | Debug.WriteLine(line); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /OptimizelySDK/Logger/ILogger.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2018, Optimizely 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | namespace OptimizelySDK.Logger 18 | { 19 | public enum LogLevel 20 | { 21 | DEBUG, 22 | INFO, 23 | WARN, 24 | ERROR, 25 | } 26 | 27 | public interface ILogger 28 | { 29 | void Log(LogLevel level, string message); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /OptimizelySDK/Logger/NoOpLogger.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017, Optimizely 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | namespace OptimizelySDK.Logger 18 | { 19 | public class NoOpLogger : ILogger 20 | { 21 | public void Log(LogLevel level, string message) { } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /OptimizelySDK/Odp/Entity/Audience.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Optimizely 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | namespace OptimizelySDK.Odp.Entity 18 | { 19 | /// 20 | /// Segment of a customer base 21 | /// 22 | public class Audience 23 | { 24 | /// 25 | /// Collection of nodes within audience 26 | /// 27 | public Edge[] Edges { get; set; } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /OptimizelySDK/Odp/Entity/Customer.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Optimizely 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | namespace OptimizelySDK.Odp.Entity 18 | { 19 | /// 20 | /// Profile used to group/segment an addressable market 21 | /// 22 | public class Customer 23 | { 24 | /// 25 | /// Segment of a customer base 26 | /// 27 | public Audience Audiences { get; set; } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /OptimizelySDK/Odp/Entity/Data.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Optimizely 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | namespace OptimizelySDK.Odp.Entity 18 | { 19 | /// 20 | /// GraphQL response data returned from a valid query 21 | /// 22 | public class Data 23 | { 24 | /// 25 | /// Grouping of audiences within an overall customer base 26 | /// 27 | public Customer Customer { get; set; } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /OptimizelySDK/Odp/Entity/Edge.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Optimizely 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | namespace OptimizelySDK.Odp.Entity 18 | { 19 | /// 20 | /// Grouping of nodes within an audience 21 | /// 22 | public class Edge 23 | { 24 | /// 25 | /// Atomic portions of a audience 26 | /// 27 | public Node Node { get; set; } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /OptimizelySDK/Odp/Entity/Error.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Optimizely 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | namespace OptimizelySDK.Odp.Entity 18 | { 19 | /// 20 | /// GraphQL response from an errant query 21 | /// 22 | public class Error 23 | { 24 | /// 25 | /// Human-readable message from the error 26 | /// 27 | public string Message { get; set; } 28 | 29 | /// 30 | /// Points of failure producing the error 31 | /// 32 | public Location[] Locations { get; set; } 33 | 34 | /// 35 | /// Files or urls producing the error 36 | /// 37 | public string[] Path { get; set; } 38 | 39 | /// 40 | /// Additional technical error information 41 | /// 42 | public Extension Extensions { get; set; } 43 | 44 | public override string ToString() 45 | { 46 | return $"{Message}"; 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /OptimizelySDK/Odp/Entity/Extension.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022-2023 Optimizely 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | namespace OptimizelySDK.Odp.Entity 18 | { 19 | /// 20 | /// Extended error information 21 | /// 22 | public class Extension 23 | { 24 | /// 25 | /// Named exception type from the error 26 | /// 27 | public string Classification { get; set; } 28 | 29 | /// 30 | /// Code of exception 31 | /// 32 | public string Code { get; set; } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /OptimizelySDK/Odp/Entity/Location.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Optimizely 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | namespace OptimizelySDK.Odp.Entity 18 | { 19 | /// 20 | /// Specifies the precise place in code or data where the error occurred 21 | /// 22 | public class Location 23 | { 24 | /// 25 | /// Code or data line number 26 | /// 27 | public int Line { get; set; } 28 | 29 | /// 30 | /// Code or data column number 31 | /// 32 | public int Column { get; set; } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /OptimizelySDK/Odp/Entity/Node.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Optimizely 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | namespace OptimizelySDK.Odp.Entity 18 | { 19 | /// 20 | /// Atomic grouping an audience 21 | /// 22 | public class Node 23 | { 24 | /// 25 | /// Descriptive label of a node 26 | /// 27 | public string Name { get; set; } 28 | 29 | /// 30 | /// Status of the node 31 | /// 32 | public string State { get; set; } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /OptimizelySDK/Odp/Entity/OdpEvent.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022-2023 Optimizely 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | using System.Collections.Generic; 18 | 19 | namespace OptimizelySDK.Odp.Entity 20 | { 21 | /// 22 | /// Event data object targeted to requirements of the Optimizely Data Platform 23 | /// 24 | public class OdpEvent 25 | { 26 | /// 27 | /// Type of event (typically `fullstack` from SDK events) 28 | /// 29 | public string Type { get; } 30 | 31 | /// 32 | /// Subcategory of the event type 33 | /// 34 | public string Action { get; } 35 | 36 | /// 37 | /// Dictionary for identifiers. The caller must provide at least one key-value pair. 38 | /// 39 | public Dictionary Identifiers { get; set; } 40 | 41 | /// 42 | /// Event data in a key-value pair format 43 | /// 44 | public Dictionary Data { get; set; } 45 | 46 | /// 47 | /// Event to be sent and stored in the Optimizely Data Platform 48 | /// 49 | /// Type of event (typically `fullstack` from SDK events) 50 | /// Subcategory of the event type 51 | /// Key-value map of user identifiers 52 | /// Event data in a key-value pair format 53 | public OdpEvent(string type, string action, Dictionary identifiers, 54 | Dictionary data = null 55 | ) 56 | { 57 | Type = type ?? Constants.ODP_EVENT_TYPE; 58 | Action = action; 59 | Identifiers = identifiers ?? new Dictionary(); 60 | Data = data ?? new Dictionary(); 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /OptimizelySDK/Odp/Entity/Response.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Optimizely 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | namespace OptimizelySDK.Odp.Entity 18 | { 19 | /// 20 | /// Wrapper around valid data and error responses 21 | /// 22 | public class Response 23 | { 24 | /// 25 | /// Valid query response information 26 | /// 27 | public Data Data { get; set; } 28 | 29 | /// 30 | /// Set of errors produced while querying 31 | /// 32 | public Error[] Errors { get; set; } 33 | 34 | /// 35 | /// Determines if an error exists 36 | /// 37 | public bool HasErrors => Errors != null && Errors.Length > 0; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /OptimizelySDK/Odp/Enums.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022-2023 Optimizely 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | namespace OptimizelySDK.Odp 18 | { 19 | /// 20 | /// Options used during segment cache handling 21 | /// 22 | public enum OdpSegmentOption 23 | { 24 | IGNORE_CACHE = 0, 25 | RESET_CACHE = 1, 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /OptimizelySDK/Odp/ICache.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022, Optimizely 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | namespace OptimizelySDK.Odp 18 | { 19 | public interface ICache 20 | where T : class 21 | { 22 | void Save(string key, T value); 23 | T Lookup(string key); 24 | void Reset(); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /OptimizelySDK/Odp/IOdpEventApiManager.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Optimizely 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | using System.Collections.Generic; 18 | using OptimizelySDK.Odp.Entity; 19 | 20 | namespace OptimizelySDK.Odp 21 | { 22 | public interface IOdpEventApiManager 23 | { 24 | bool SendEvents(string apiKey, string apiHost, List events); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /OptimizelySDK/Odp/IOdpSegmentApiManager.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Optimizely 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | using System.Collections.Generic; 18 | 19 | namespace OptimizelySDK.Odp 20 | { 21 | public interface IOdpSegmentApiManager 22 | { 23 | /// 24 | /// Retrieves the audience segments from ODP 25 | /// 26 | /// ODP public key 27 | /// Fully-qualified URL of ODP 28 | /// Server-side should be 'fs_user_id key' 29 | /// Associated value to query for the user key 30 | /// Audience segments to check for experiment inclusion 31 | /// Array of audience segments 32 | string[] FetchSegments(string apiKey, 33 | string apiHost, 34 | string userKey, 35 | string userValue, 36 | List segmentsToCheck 37 | ); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /OptimizelySDK/Odp/IOdpSegmentManager.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Optimizely 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | using System.Collections.Generic; 18 | 19 | namespace OptimizelySDK.Odp 20 | { 21 | /// 22 | /// Interface to schedule connections to ODP for audience segmentation and caches the results. 23 | /// 24 | public interface IOdpSegmentManager 25 | { 26 | /// 27 | /// Attempts to fetch and return a list of a user's qualified segments from the local segments cache. 28 | /// If no cached data exists for the target user, this fetches and caches data from the ODP server instead. 29 | /// 30 | /// The FS User ID identifying the user 31 | /// An array of OptimizelySegmentOption used to ignore and/or reset the cache. 32 | /// Qualified segments for the user from the cache or the ODP server if the cache is empty. 33 | List FetchQualifiedSegments(string fsUserId, List options = null); 34 | 35 | /// 36 | /// Update the ODP configuration settings being used by the Segment Manager 37 | /// 38 | /// New ODP Configuration to apply 39 | void UpdateSettings(OdpConfig odpConfig); 40 | 41 | /// 42 | /// Reset/clear the segments cache 43 | /// 44 | void ResetCache(); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /OptimizelySDK/OptimizelyDecisionContext.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021, Optimizely 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | namespace OptimizelySDK 18 | { 19 | /// 20 | /// OptimizelyDecisionContext contains flag key and rule key to be used for setting 21 | /// and getting forced decision. 22 | /// 23 | public class OptimizelyDecisionContext 24 | { 25 | public const string OPTI_NULL_RULE_KEY = "$opt-null-rule-key"; 26 | public const string OPTI_KEY_DIVIDER = "-$opt$-"; 27 | 28 | private string flagKey; 29 | private string ruleKey; 30 | 31 | /// 32 | /// Represents the object is valid or not. 33 | /// 34 | public bool IsValid { get; private set; } 35 | 36 | /// 37 | /// Flag key of the context. 38 | /// 39 | public string FlagKey => flagKey; 40 | 41 | /// 42 | /// Rule key, it can be experiment or rollout key and nullable. 43 | /// 44 | public string RuleKey => ruleKey; 45 | 46 | public OptimizelyDecisionContext(string flagKey, string ruleKey = null) 47 | { 48 | if (flagKey != null) 49 | { 50 | IsValid = true; 51 | } 52 | 53 | this.flagKey = flagKey; 54 | this.ruleKey = ruleKey; 55 | } 56 | 57 | public string GetKey() 58 | { 59 | return string.Format("{0}{1}{2}", FlagKey, OPTI_KEY_DIVIDER, 60 | RuleKey ?? OPTI_NULL_RULE_KEY); 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /OptimizelySDK/OptimizelyDecisions/DecisionMessage.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020, Optimizely 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | namespace OptimizelySDK.OptimizelyDecisions 18 | { 19 | public class DecisionMessage 20 | { 21 | public const string SDK_NOT_READY = "Optimizely SDK not configured properly yet."; 22 | public const string FLAG_KEY_INVALID = "No flag was found for key \"{0}\"."; 23 | 24 | public const string VARIABLE_VALUE_INVALID = 25 | "Variable value for key \"{0}\" is invalid or wrong type."; 26 | 27 | public static string Reason(string format, params object[] args) 28 | { 29 | return string.Format(format, args); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /OptimizelySDK/OptimizelyDecisions/DecisionReasons.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021, Optimizely 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | using System; 18 | using System.Collections.Generic; 19 | 20 | namespace OptimizelySDK.OptimizelyDecisions 21 | { 22 | public class DecisionReasons 23 | { 24 | protected List Errors = new List(); 25 | private List Infos = new List(); 26 | 27 | public void AddError(string format, params object[] args) 28 | { 29 | var message = string.Format(format, args); 30 | Errors.Add(message); 31 | } 32 | 33 | public string AddInfo(string format, params object[] args) 34 | { 35 | var message = string.Format(format, args); 36 | Infos.Add(message); 37 | 38 | return message; 39 | } 40 | 41 | public static DecisionReasons operator +(DecisionReasons a, DecisionReasons b) 42 | { 43 | if (b == null) 44 | { 45 | return a; 46 | } 47 | 48 | a.Errors.AddRange(b.Errors); 49 | a.Infos.AddRange(b.Infos); 50 | 51 | return a; 52 | } 53 | 54 | public List ToReport(bool includeReasons = false) 55 | { 56 | var reasons = new List(Errors); 57 | 58 | if (includeReasons) 59 | { 60 | reasons.AddRange(Infos); 61 | } 62 | 63 | return reasons; 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /OptimizelySDK/OptimizelyDecisions/OptimizelyDecideOption.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020, Optimizely 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | namespace OptimizelySDK.OptimizelyDecisions 18 | { 19 | public enum OptimizelyDecideOption 20 | { 21 | DISABLE_DECISION_EVENT, 22 | ENABLED_FLAGS_ONLY, 23 | IGNORE_USER_PROFILE_SERVICE, 24 | INCLUDE_REASONS, 25 | EXCLUDE_VARIABLES, 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /OptimizelySDK/OptimizelyForcedDecision.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021, Optimizely 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | namespace OptimizelySDK 18 | { 19 | public class OptimizelyForcedDecision 20 | { 21 | private string _variationKey; 22 | 23 | public OptimizelyForcedDecision(string variationKey) 24 | { 25 | _variationKey = variationKey; 26 | } 27 | 28 | public string VariationKey => _variationKey; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /OptimizelySDK/OptlyConfig/IOptimizelyConfigManager.cs: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2020, Optimizely, Inc. and contributors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | namespace OptimizelySDK.OptlyConfig 18 | { 19 | public interface IOptimizelyConfigManager 20 | { 21 | /// 22 | /// Implementation of this method should return OptimizelyConfig 23 | /// 24 | /// OptimizelyConfig 25 | OptimizelyConfig GetOptimizelyConfig(); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /OptimizelySDK/OptlyConfig/OptimizelyAttribute.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021, Optimizely 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | using OptimizelySDK.Entity; 18 | 19 | namespace OptimizelySDK.OptlyConfig 20 | { 21 | public class OptimizelyAttribute : IdKeyEntity { } 22 | } 23 | -------------------------------------------------------------------------------- /OptimizelySDK/OptlyConfig/OptimizelyAudience.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021, Optimizely 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | namespace OptimizelySDK.OptlyConfig 18 | { 19 | public class OptimizelyAudience 20 | { 21 | /// 22 | /// Audience ID 23 | /// 24 | public string Id { get; set; } 25 | 26 | /// 27 | /// Audience Name 28 | /// 29 | public string Name { get; set; } 30 | 31 | /// 32 | /// Audience Conditions 33 | /// 34 | public object Conditions { get; set; } 35 | 36 | public OptimizelyAudience(string id, string name, object conditions) 37 | { 38 | Id = id; 39 | Name = name; 40 | Conditions = conditions; 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /OptimizelySDK/OptlyConfig/OptimizelyEvent.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021, Optimizely 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | using OptimizelySDK.Entity; 18 | 19 | namespace OptimizelySDK.OptlyConfig 20 | { 21 | public class OptimizelyEvent : IdKeyEntity 22 | { 23 | /// 24 | /// Associated Experiment with this Event 25 | /// 26 | public string[] ExperimentIds { get; set; } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /OptimizelySDK/OptlyConfig/OptimizelyExperiment.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019, 2021, Optimizely 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | using System.Collections.Generic; 18 | 19 | namespace OptimizelySDK.OptlyConfig 20 | { 21 | public class OptimizelyExperiment : Entity.IdKeyEntity 22 | { 23 | public IDictionary VariationsMap { get; private set; } 24 | public string Audiences { get; private set; } 25 | 26 | public OptimizelyExperiment(string id, string key, string audiences, 27 | IDictionary variationsMap 28 | ) 29 | { 30 | Id = id; 31 | Key = key; 32 | Audiences = audiences; 33 | VariationsMap = variationsMap; 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /OptimizelySDK/OptlyConfig/OptimizelyFeature.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019, 2021, Optimizely 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | using System; 18 | using System.Collections.Generic; 19 | 20 | namespace OptimizelySDK.OptlyConfig 21 | { 22 | public class OptimizelyFeature : Entity.IdKeyEntity 23 | { 24 | public List ExperimentRules { get; private set; } 25 | public List DeliveryRules { get; private set; } 26 | 27 | [Obsolete("Use experimentRules and deliveryRules.")] 28 | public IDictionary ExperimentsMap { get; private set; } 29 | 30 | public IDictionary VariablesMap { get; private set; } 31 | 32 | [Obsolete] 33 | public OptimizelyFeature(string id, string key, List experimentRules, 34 | List deliveryRules, 35 | IDictionary experimentsMap, 36 | IDictionary variablesMap 37 | ) 38 | { 39 | Id = id; 40 | Key = key; 41 | ExperimentRules = experimentRules; 42 | DeliveryRules = deliveryRules; 43 | ExperimentsMap = experimentsMap; 44 | VariablesMap = variablesMap; 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /OptimizelySDK/OptlyConfig/OptimizelyVariable.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019, Optimizely 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | using OptimizelySDK.Entity; 18 | 19 | namespace OptimizelySDK.OptlyConfig 20 | { 21 | public class OptimizelyVariable : IdKeyEntity 22 | { 23 | public string Type { get; private set; } 24 | public string Value { get; private set; } 25 | 26 | public OptimizelyVariable(string id, string key, string type, string value) 27 | { 28 | Id = id; 29 | Key = key; 30 | Type = type; 31 | Value = value; 32 | } 33 | 34 | public OptimizelyVariable(FeatureVariable featureVariable, 35 | FeatureVariableUsage featureVariableUsage 36 | ) 37 | { 38 | Id = featureVariable.Id; 39 | Key = featureVariable.Key; 40 | Type = featureVariable.Type.ToString().ToLower(); 41 | Value = featureVariableUsage?.Value ?? featureVariable.DefaultValue; 42 | } 43 | 44 | 45 | public static explicit operator OptimizelyVariable(FeatureVariable featureVariable) 46 | { 47 | return new OptimizelyVariable(featureVariable, null); 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /OptimizelySDK/OptlyConfig/OptimizelyVariation.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019, Optimizely 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | using System.Collections.Generic; 18 | using Newtonsoft.Json; 19 | 20 | namespace OptimizelySDK.OptlyConfig 21 | { 22 | public class OptimizelyVariation : Entity.IdKeyEntity 23 | { 24 | [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] 25 | public bool? FeatureEnabled { get; private set; } 26 | 27 | public IDictionary VariablesMap { get; private set; } 28 | 29 | public OptimizelyVariation(string id, string key, bool? featureEnabled, 30 | IDictionary variablesMap 31 | ) 32 | { 33 | Id = id; 34 | Key = key; 35 | FeatureEnabled = featureEnabled; 36 | VariablesMap = variablesMap; 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /OptimizelySDK/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("OptimizelySDK")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("OptimizelySDK")] 13 | [assembly: AssemblyCopyright("Copyright © 2017-2023")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // Make types and members with internal scope visible to friend 23 | // OptimizelySDK.Tests unit tests. 24 | #pragma warning disable 1700 25 | #if DEBUG 26 | [assembly: InternalsVisibleTo("OptimizelySDK.Tests")] 27 | #else 28 | [assembly: InternalsVisibleTo("OptimizelySDK.Tests, PublicKey=00240000048000009400000006020000002400005253413100040000010001006b0705c5f697a2522639be5d5bc02835aaef2e2cd4adf47c3bbf5ed97187298c17448701597b5a610d29eed362f36f056062bbccd424fc830dd5966a9378302c61e3ddd77effcd9dcfaf739f3ca88149e961f55f23d5ce1948703da33e261f6cc0c681a19ce62ccbfdeca8bd286f93395e4f67e4a2ea7782af581062edab8083")] 29 | #endif 30 | #pragma warning restore 1700 31 | 32 | // The following GUID is for the ID of the typelib if this project is exposed to COM 33 | [assembly: Guid("4dde7faa-110d-441c-ab3b-3f31b593e8bf")] 34 | 35 | // Version information for an assembly consists of the following four values: 36 | // 37 | // Major Version 38 | // Minor Version 39 | // Build Number 40 | // Revision 41 | // 42 | // You can specify all the values or you can default the Build and Revision Numbers 43 | // by using the '*' as shown below: 44 | [assembly: AssemblyVersion("4.1.0.0")] 45 | [assembly: AssemblyFileVersion("4.1.0.0")] 46 | [assembly: AssemblyInformationalVersion("4.1.0")] // Used by NuGet. 47 | -------------------------------------------------------------------------------- /OptimizelySDK/Utils/AttributeMatchTypes.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019-2020, Optimizely 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | namespace OptimizelySDK.Utils 18 | { 19 | public static class AttributeMatchTypes 20 | { 21 | public const string EXACT = "exact"; 22 | public const string EXIST = "exists"; 23 | public const string GREATER_OR_EQUAL = "ge"; 24 | public const string GREATER_THAN = "gt"; 25 | public const string LESS_OR_EQUAL = "le"; 26 | public const string LESS_THAN = "lt"; 27 | public const string SUBSTRING = "substring"; 28 | public const string SEMVER_EQ = "semver_eq"; 29 | public const string SEMVER_GE = "semver_ge"; 30 | public const string SEMVER_GT = "semver_gt"; 31 | public const string SEMVER_LE = "semver_le"; 32 | public const string SEMVER_LT = "semver_lt"; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /OptimizelySDK/Utils/CollectionExtensions.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022-2023, Optimizely 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | using System; 18 | using System.Collections.Generic; 19 | using System.Linq; 20 | 21 | namespace OptimizelySDK.Utils 22 | { 23 | public static class CollectionExtensions 24 | { 25 | /// 26 | /// Merge a Dictionary into another without overwriting existing keys 27 | /// 28 | /// Dictionary that will be merged into 29 | /// Dictionary to merge into another 30 | /// Key type 31 | /// Value type 32 | /// Thrown if target Dictionary is null 33 | public static void MergeInPlace(this Dictionary left, 34 | Dictionary right 35 | ) 36 | { 37 | if (left == null) 38 | { 39 | throw new ArgumentNullException(nameof(left), 40 | "Cannot merge into a null dictionary"); 41 | } 42 | 43 | if (right == null) 44 | { 45 | return; 46 | } 47 | 48 | // Only update the left dictionary when the key doesn't exist 49 | foreach (var kvp in right.Where( 50 | kvp => !left.ContainsKey(kvp.Key))) 51 | { 52 | left.Add(kvp.Key, kvp.Value); 53 | } 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /OptimizelySDK/Utils/ConfigParser.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017, Optimizely 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | using System; 18 | using System.Collections.Generic; 19 | using System.Linq; 20 | 21 | namespace OptimizelySDK.Utils 22 | { 23 | public static class ConfigParser where T : ICloneable 24 | { 25 | /// 26 | /// Creates a map (associative array) that maps to a list of entities 27 | /// 28 | /// The list of entities which will be the "values" of the associative array 29 | /// A function to return the key value from the entity 30 | /// Whether or not to clone the original entity 31 | /// associative array of key => entity 32 | public static Dictionary GenerateMap(IEnumerable entities, 33 | Func getKey, bool clone 34 | ) 35 | { 36 | return entities.ToDictionary(e => getKey(e), e => clone ? (T)e.Clone() : e); 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /OptimizelySDK/Utils/ControlAttributes.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018, Optimizely 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | namespace OptimizelySDK.Utils 18 | { 19 | public class ControlAttributes 20 | { 21 | public const string BOT_FILTERING_ATTRIBUTE = "$opt_bot_filtering"; 22 | public const string BUCKETING_ID_ATTRIBUTE = "$opt_bucketing_id"; 23 | public const string USER_AGENT_ATTRIBUTE = "$opt_user_agent"; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /OptimizelySDK/Utils/DateTimeUtils.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace OptimizelySDK.Utils 4 | { 5 | public static class DateTimeUtils 6 | { 7 | /// 8 | /// Helper to compute Unix time (i.e. since Jan 1, 1970) 9 | /// 10 | public static long SecondsSince1970 => 11 | (long)(DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds; 12 | 13 | public static long MillisecondsSince1970(this DateTime dateTime) 14 | { 15 | return (long)(dateTime - new DateTime(1970, 1, 1)).TotalMilliseconds; 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /OptimizelySDK/Utils/DecisionInfoTypes.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019-2020, Optimizely 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | namespace OptimizelySDK.Utils 18 | { 19 | public static class DecisionNotificationTypes 20 | { 21 | public const string AB_TEST = "ab-test"; 22 | public const string FEATURE = "feature"; 23 | public const string FLAG = "flag"; 24 | public const string FEATURE_TEST = "feature-test"; 25 | public const string FEATURE_VARIABLE = "feature-variable"; 26 | public const string ALL_FEATURE_VARIABLE = "all-feature-variables"; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /OptimizelySDK/Utils/ExceptionExtensions.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019, Optimizely 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | using System; 18 | 19 | namespace OptimizelySDK.Utils 20 | { 21 | public static class ExceptionExtensions 22 | { 23 | public static string GetAllMessages(this Exception exception, string separator = "\n") 24 | { 25 | if (exception.InnerException == null) 26 | { 27 | return exception.Message; 28 | } 29 | 30 | return string.IsNullOrEmpty(exception.Message) ? 31 | "" : 32 | $"{exception.Message}{separator}{GetAllMessages(exception.InnerException, separator)}"; 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /OptimizelySDK/Utils/Schema.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017, Optimizely 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | using System.IO; 18 | using System.Reflection; 19 | 20 | namespace OptimizelySDK.Utils 21 | { 22 | internal class Schema 23 | { 24 | private static string cache = null; 25 | 26 | public static string GetSchemaJson() 27 | { 28 | if (cache != null) 29 | { 30 | return cache; 31 | } 32 | #if NET35 || NET40 33 | var assembly = Assembly.GetExecutingAssembly(); 34 | #else 35 | var assembly = typeof(Schema).GetTypeInfo().Assembly; 36 | #endif 37 | const string resourceName = "OptimizelySDK.Utils.schema.json"; 38 | 39 | using (var stream = assembly.GetManifestResourceStream(resourceName)) 40 | using (var reader = new StreamReader(stream)) 41 | { 42 | return cache = reader.ReadToEnd(); 43 | } 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /OptimizelySDK/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /docs/readme-sync/sdk-reference-guides/csharp-sdk/010 - install-sdk-csharp.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Install SDK" 3 | slug: "install-sdk-csharp" 4 | hidden: false 5 | createdAt: "2019-09-11T13:55:51.015Z" 6 | updatedAt: "2019-09-11T13:58:07.201Z" 7 | --- 8 | 9 | The C# SDK is distributed through NuGet. 10 | 11 | For Windows, to install, run the command `Install-Package Optimizely.SDK` in the Package Manager Console: 12 | 13 | ```shell 14 | PM> Install-Package Optimizely.SDK -Version 3.0.0 15 | ``` 16 | The package is on NuGet at https://www.nuget.org/packages/Optimizely.SDK. The full source code is at https://github.com/optimizely/csharp-sdk. 17 | -------------------------------------------------------------------------------- /docs/readme-sync/sdk-reference-guides/csharp-sdk/010 -install-sdk-csharp.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Install SDK" 3 | slug: "install-sdk-csharp" 4 | hidden: false 5 | createdAt: "2019-09-11T13:55:51.015Z" 6 | updatedAt: "2019-09-11T13:58:07.201Z" 7 | --- 8 | 9 | The C# SDK is distributed through NuGet. 10 | 11 | For Windows, to install, run the command `Install-Package Optimizely.SDK` in the Package Manager Console: 12 | 13 | ```shell 14 | PM> Install-Package Optimizely.SDK -Version 3.0.0 15 | ``` 16 | The package is on NuGet at https://www.nuget.org/packages/Optimizely.SDK. The full source code is at https://github.com/optimizely/csharp-sdk. 17 | 18 | -------------------------------------------------------------------------------- /docs/readme-sync/sdk-reference-guides/csharp-sdk/030 - example-usage-csharp.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Example usage" 3 | slug: "example-usage-csharp" 4 | hidden: false 5 | createdAt: "2019-09-11T22:26:38.446Z" 6 | updatedAt: "2019-09-12T20:28:26.570Z" 7 | --- 8 | Once you've installed the C# SDK, import the Optimizely library into your code, get your Optimizely project's datafile, and instantiate a client. Then, you can use the client to evaluate feature flags, activate an A/B test, or feature test. 9 | 10 | This example demonstrates the basic usage of each of these concepts. This example shows how to: 11 | 1. Evaluate a feature with the key `price_filter` and check a configuration variable on it called `min_price`. The SDK evaluates your feature test and rollouts to determine whether the feature is enabled for a particular user, and which minimum price they should see if so. 12 | 13 | 2. Run an A/B test called `app_redesign`. This experiment has two variations, `control` and `treatment`. It uses the `activate` method to assign the user to a variation, returning its key. As a side effect, the activate function also sends an impression event to Optimizely to record that the current user has been exposed to the experiment. 14 | 15 | 3. Use event tracking to track an event called `purchased`. This conversion event measures the impact of an experiment. Using the track method, the purchase is automatically attributed back to the running A/B and feature tests we've activated, and the SDK sends a network request to Optimizely via the customizable event dispatcher so we can count it in your results page. 16 | ```csharp 17 | // Import Optimizely SDK 18 | using OptimizelySDK; 19 | 20 | // Instantiate an Optimizely client 21 | var optimizelyClient = new Optimizely(datafile); 22 | 23 | // Evaluate a feature flag and a variable 24 | bool isFeatureEnabled = optimizelyClient.IsFeatureEnabled("price_filter", userId); 25 | int? min_price = optimizelyClient.GetFeatureVariableInteger("price_filter", "min_price", userId); 26 | 27 | // Activate an A/B test 28 | var variation = optimizelyClient.Activate("app_redesign", userId); 29 | 30 | if (variation != null && !string.IsNullOrEmpty(variation.Key)) 31 | { 32 | if (variation.Key == "control") 33 | { 34 | // Execute code for variation A 35 | } 36 | else if (variation.Key == "treatment") 37 | { 38 | // Execute code for variation B 39 | } 40 | } 41 | else 42 | { 43 | // Execute code for your users who don’t qualify for the experiment 44 | } 45 | 46 | // Track an event 47 | optimizelyClient.Track("purchased", userId); 48 | 49 | ``` -------------------------------------------------------------------------------- /docs/readme-sync/sdk-reference-guides/csharp-sdk/090 - customize-error-handler-csharp.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Customize error handler" 3 | slug: "customize-error-handler-csharp" 4 | hidden: false 5 | createdAt: "2019-09-12T13:44:18.412Z" 6 | updatedAt: "2019-09-12T13:48:38.080Z" 7 | --- 8 | 9 | You can provide your own custom **error handler** logic to standardize across your production environment. 10 | 11 | This error handler is called when the SDK is not executed as expected, which may be due to arguments provided to the SDK or running in an environment where network or other disruptions occur. 12 | 13 | See the code example below. If the error handler is not overridden, a no-op error handler is used by default. 14 | 15 | ```csharp 16 | using System; 17 | using OptimizelySDK.ErrorHandler; 18 | 19 | /** 20 | * Creates a CustomErrorHandler and calls HandleError when an exception is raised by the SDK. 21 | **/ 22 | /** CustomErrorHandler should be inherited by IErrorHandler, a namespace of OptimizelySDK.ErrorHandler. 23 | **/ 24 | public class CustomErrorHandler : IErrorHandler 25 | { 26 | /// 27 | /// Handle exceptions when raised by the SDK. 28 | /// 29 | /// object of Exception raised by the SDK. 30 | public void HandleError(Exception exception) 31 | { 32 | throw new NotImplementedException(); 33 | } 34 | } 35 | ``` -------------------------------------------------------------------------------- /docs/readme-sync/sdk-reference-guides/csharp-sdk/100 - pass-in-audience-attributes-csharp.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Pass in audience attributes" 3 | slug: "pass-in-audience-attributes-csharp" 4 | hidden: false 5 | createdAt: "2019-09-12T13:44:29.855Z" 6 | updatedAt: "2019-09-12T20:30:05.154Z" 7 | --- 8 | 9 | You can pass strings, numbers, Booleans, and null as user attribute values. The example below shows how to pass in attributes. 10 | 11 | ```csharp 12 | UserAttributes attributes = new UserAttributes 13 | { 14 | { "DEVICE", "iPhone" }, 15 | { "AD_SOURCE", "my_campaign" } 16 | }; 17 | 18 | bool enabled = OptimizelyClient.IsFeatureEnabled("new_feature", "user123", attributes); 19 | ``` 20 | > **Important** 21 | > During audience evaluation, note that if you don't pass a valid attribute value for a given audience condition—for example, if you pass a string when the audience condition requires a Boolean, or if you simply forget to pass a value—then that condition will be skipped. The [SDK logs](doc:customize-logger-csharp) will include warnings when this occurs. 22 | -------------------------------------------------------------------------------- /docs/readme-sync/sdk-reference-guides/csharp-sdk/130 - get-enabled-features-csharp.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Get Enabled Features" 3 | slug: "get-enabled-features-csharp" 4 | hidden: false 5 | createdAt: "2019-09-12T13:53:46.225Z" 6 | updatedAt: "2019-09-12T20:33:07.026Z" 7 | --- 8 | 9 | Retrieves a list of features that are enabled for the user. Invoking this method is equivalent to running [Is Feature Enabled](doc:is-feature-enabled-csharp) for each feature in the datafile sequentially. 10 | 11 | This method takes into account the user `attributes` passed in, to determine if the user is part of the audience that qualifies for the experiment. 12 | 13 | ## Version 14 | 15 | SDK v3.0 16 | 17 | ## Description 18 | This method iterates through all feature flags and for each feature flag invokes [Is Feature Enabled](doc:is-feature-enabled-csharp). If a feature is enabled, this method adds the feature’s key to the return list. 19 | ## Parameters 20 | 21 | The table below lists the required and optional parameters in C#. 22 | 23 | | Parameter | Type | Description | 24 | |------------------|--------|----------------------------------------------------------------------------------------------------------| 25 | | **userId**
*required* | string | The ID of the user to check. | 26 | | **userAttributes**
*optional* | map | A map of custom key-value string pairs specifying attributes for the user that are used for audience targeting. Non-string values are only supported in the 3.0 SDK and above. | 27 | 28 | ## Returns 29 | 30 | A list of the feature keys that are enabled for the user, or an empty list if no features could be found for the specified user. 31 | 32 | ## Examples 33 | 34 | This section shows a simple example of how you can use the method. 35 | 36 | ```csharp 37 | var actualFeaturesList = OptimizelyMock.Object.GetEnabledFeatures(TestUserId, userAttributes); 38 | 39 | ``` 40 | ## Source files 41 | 42 | The language/platform source files containing the implementation for C# is [Optimizely.cs](https://github.com/optimizely/csharp-sdk/blob/master/OptimizelySDK/Optimizely.cs). 43 | -------------------------------------------------------------------------------- /docs/readme-sync/sdk-reference-guides/csharp-sdk/150 - get-forced-variation-csharp.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Get Forced Variation" 3 | slug: "get-forced-variation-csharp" 4 | hidden: false 5 | createdAt: "2019-09-12T13:51:51.169Z" 6 | updatedAt: "2019-09-12T20:34:30.074Z" 7 | --- 8 | 9 | Returns the forced variation set by [Set Forced Variation](doc:set-forced-variation-csharp), or `null` if no variation was forced. 10 | 11 | A user can be forced into a variation for a given experiment for the lifetime of the Optimizely client. This method gets the variation that the user has been forced into. The forced variation value is runtime only and does not persist across application launches. 12 | 13 | ## Version 14 | 15 | SDK v3.0, v3.1 16 | 17 | ## Description 18 | 19 | Forced bucketing variations take precedence over whitelisted variations, variations saved in a User Profile Service (if one exists), and the normal bucketed variation. Variations are overwritten when [Set Forced Variation](doc:set-forced-variation-csharp) is invoked. 20 | 21 | > **Note** 22 | > A forced variation only persists for the lifetime of an Optimizely client. 23 | 24 | ## Parameters 25 | 26 | This table lists the required and optional parameters for the C# SDK. 27 | 28 | | Parameter | Type | Description | 29 | |-------------------|--------|---------------------------------------------| 30 | | **experimentKey**
*required* | string | The key of the experiment to retrieve the forced variation. | 31 | | **userId**
*required* | string | The ID of the user in the forced variation. | 32 | 33 | ## Returns 34 | 35 | `null|string`: The variation key. 36 | 37 | ## Example 38 | 39 | ```csharp 40 | var variation = optimizelyClient.GetForcedVariation("my_experiment_key", "user_123"); 41 | ``` 42 | ## Source files 43 | 44 | The language/platform source files containing the implementation for C# is [Optimizely.cs](https://github.com/optimizely/csharp-sdk/blob/master/OptimizelySDK/Optimizely.cs). 45 | -------------------------------------------------------------------------------- /docs/readme-sync/sdk-reference-guides/csharp-sdk/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "C# SDK" 3 | slug: "csharp-sdk" 4 | hidden: false 5 | metadata: 6 | title: "Optimizely C# SDK" 7 | createdAt: {} 8 | updatedAt: "2020-05-22T20:03:21.212Z" 9 | --- 10 | 11 | This reference guide describes how to use the Optimizely C# SDK. Refer to the left-hand navigation for all sections in this reference guide. 12 | 13 | The Optimizely C# SDK is currently at version 3.4.1. 14 | 15 | You can also use the [C# SDK quickstart](doc:c-sharp) or review the [C# SDK repo](https://github.com/optimizely/csharp-sdk) and [changelog](https://github.com/optimizely/csharp-sdk/blob/master/CHANGELOG.md). 16 | -------------------------------------------------------------------------------- /install_mono.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | sudo apt install gnupg ca-certificates 4 | sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 3FA7E0328081BFF6A14DA29AA6A19B38D3D831EF 5 | echo "deb https://download.mono-project.com/repo/ubuntu stable-bionic main" | sudo tee /etc/apt/sources.list.d/mono-official-stable.list 6 | sudo apt update 7 | sudo apt install mono-devel 8 | -------------------------------------------------------------------------------- /keypair.snk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/optimizely/csharp-sdk/282b7cf7577d1adf2fedaad33625dab34aea5fa6/keypair.snk -------------------------------------------------------------------------------- /pull_request_template.md: -------------------------------------------------------------------------------- 1 | ## Summary 2 | - The "what"; a concise description of each logical change 3 | - Another change 4 | 5 | The "why", or other context. 6 | 7 | ## Test plan 8 | 9 | ## Issues 10 | - "THING-1234" or "Fixes #123" 11 | --------------------------------------------------------------------------------