diff --git a/.gitignore b/.gitignore index f55bd13..2c03faa 100644 --- a/.gitignore +++ b/.gitignore @@ -354,3 +354,4 @@ MigrationBackup/ /VWOSdk.DemoApp/logs.txt .DS_STORE +/VWOSdk.DemoApp/Resources/SettingsFile.json diff --git a/LICENSE b/LICENSE index 2e09927..e4f891b 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2019-2020 Wingify Software Pvt. Ltd. +Copyright (c) 2019-2021 Wingify Software Pvt. Ltd. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: diff --git a/README.md b/README.md index 8d52bc8..d64cb7f 100644 --- a/README.md +++ b/README.md @@ -10,16 +10,17 @@ This repository provides a basic demo of how FullStack works with VWO NetStandar ### Documentation -Refer [VWO Official FullStack Documentation](https://developers.vwo.com/reference#fullstack-introduction) +Refer [VWO Official FullStack Documentation](https://developers.vwo.com/docs/fullstack-overview) ### Scripts 1. Install dependencies ``` -dotnet restore +cd VWOSdk.DemoApp; +dotnet restore; ``` -2. Update your app with essential params inside `VWOConfig.cs` +2. Update your app with essential params inside `VWOSdk.DemoApp/VWOConfig.cs` ```c# using System.Collections.Generic; @@ -73,7 +74,7 @@ dotnet run --project VWOSdk.DemoApp/VWOSdk.DemoApp.csproj ```text MIT License - Copyright (c) 2019 Wingify Software Pvt. Ltd. + Copyright (c) 2019-2021 Wingify Software Pvt. Ltd. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/VWOSdk.DemoApp/Controllers/HomeController.cs b/VWOSdk.DemoApp/Controllers/HomeController.cs index 083f356..f48e45e 100644 --- a/VWOSdk.DemoApp/Controllers/HomeController.cs +++ b/VWOSdk.DemoApp/Controllers/HomeController.cs @@ -2,9 +2,13 @@ using System.Collections.Generic; using Microsoft.AspNetCore.Mvc; using VWOSdk.DemoApp.Models; +using System.IO; +using System.Text; +using System.Threading.Tasks; namespace VWOSdk.DemoApp.Controllers { + public class HomeController : Controller { private static string GetRandomName() @@ -24,14 +28,26 @@ private static List Names }; private static Settings SettingsFile { get; set; } - private static IVWOClient VWOClient { get; } - + private static IVWOClient VWOClient { get; set; } static HomeController() { VWO.Configure(LogLevel.DEBUG); VWO.Configure(new CustomLogger()); + CustomLogger logger = new CustomLogger(); SettingsFile = SettingsProvider.GetSettingsFile(VWOConfig.SDK.AccountId, VWOConfig.SDK.SdkKey); - VWOClient = VWO.Launch(SettingsFile, isDevelopmentMode: false, userStorageService: new UserStorageService()); + BatchEventData _batchData = new BatchEventData(); + _batchData.EventsPerRequest = Defaults.EventsPerRequest; + _batchData.RequestTimeInterval = Defaults.RequestTimeInterval; + _batchData.FlushCallback = new FlushCallback(); + //logger.WriteLog(LogLevel.DEBUG, "BatchEventData : EventsPerRequest-" + Defaults.EventsPerRequest.ToString() +", RequestTimeInterval:" + Defaults.RequestTimeInterval); + //VWOClient = VWO.Launch(SettingsFile, batchData: _batchData); + + //logger.WriteLog(LogLevel.DEBUG, "HookManager : IntegrationEventListener onEvent requested "); + //VWOClient = VWO.Launch(SettingsFile, batchData: _batchData, integrations: new HookManager(){HookCallback = new HookCallback()}); + + logger.WriteLog(LogLevel.DEBUG, "BatchEventData,userStorageService,isDevelopmentMode,integrations,shouldTrackReturningUser passed in SDK"); + VWOClient = VWO.Launch(SettingsFile, batchData: _batchData, userStorageService: new UserStorageService(), + isDevelopmentMode: false, integrations: new HookManager() { HookCallback = new HookCallback() }, shouldTrackReturningUser: false); } [HttpGet] @@ -39,7 +55,6 @@ public IActionResult Index([FromQuery] string user) { return View(); } - [HttpGet] public IActionResult Ab([FromQuery] string user) { @@ -49,8 +64,10 @@ public IActionResult Ab([FromQuery] string user) var options = VWOConfig.ABCampaignSettings.Options; string activateResponse = null, getVariationResponse = null; bool trackResponse = false; + if (VWOClient != null) { + activateResponse = VWOClient.Activate(CampaignKey, userId, options); getVariationResponse = string.IsNullOrEmpty(activateResponse) ? activateResponse : VWOClient.GetVariationName(CampaignKey, userId, options); // Track all campaigns - @@ -58,10 +75,12 @@ public IActionResult Ab([FromQuery] string user) // Track multiple campaigns - // VWOClient.Track(new List(){ CampaignKey, "Test2" }, userId, goalIdentifier, options); + trackResponse = string.IsNullOrEmpty(activateResponse) ? false : VWOClient.Track(CampaignKey, userId, goalIdentifier, options); } var json = new ViewModel(SettingsFile, userId, CampaignKey, goalIdentifier, activateResponse, getVariationResponse, trackResponse, options); return View(json); + } @@ -102,8 +121,9 @@ public IActionResult FeatureTest([FromQuery] string user) { activateResponse = VWOClient.IsFeatureEnabled(CampaignKey, userId, options); - if (activateResponse) { - VWOClient.Track(CampaignKey, userId, goalIdentifier, options); + if (activateResponse) + { + VWOClient.Track(CampaignKey, userId, goalIdentifier, options); } stringVariable = VWOClient.GetFeatureVariableValue(CampaignKey, stringVariableKey, userId, options); integerVariable = VWOClient.GetFeatureVariableValue(CampaignKey, integerVariableKey, userId, options); @@ -128,5 +148,71 @@ public IActionResult Push([FromQuery] string user) var json = new ViewModel(SettingsFile, userId, activateResponse, tagKey, tagValue); return View(json); } + [HttpGet] + public IActionResult Flush() + { + + if (VWOClient != null) + { + CustomLogger logger = new CustomLogger(); + logger.WriteLog(LogLevel.DEBUG, "manual flushEvent called "); + bool response = VWOClient.FlushEvents(); + logger.WriteLog(LogLevel.DEBUG, "flushEvent response: " + response.ToString()); + } + return View("Index"); + } + [Route("/webhook")] + [HttpPost] + public async Task webhook() + { + CustomLogger logger = new CustomLogger(); + string PayLoad; + logger.WriteLog(LogLevel.DEBUG, "Post request from vwo app"); + + using (StreamReader reader = new StreamReader(Request.Body, Encoding.UTF8)) + { + PayLoad = await reader.ReadToEndAsync(); + } + logger.WriteLog(LogLevel.DEBUG, "VWO webhook payload: " + PayLoad); + if (string.IsNullOrEmpty(Defaults.WebhookSecretKey) == false) + { + logger.WriteLog(LogLevel.DEBUG, "WebhookSecretKey exists . VWO webhook authentication Checking."); + + if (Request.Headers["x-vwo-auth"].ToString() != Defaults.WebhookSecretKey) + { + logger.WriteLog(LogLevel.DEBUG, "VWO webhook authentication failed. Please check."); + return "VWO webhook authentication failed. Please check."; + } + + if (VWOClient != null) + { + logger.WriteLog(LogLevel.DEBUG, "Authentication passed and GetAndUpdateSettingsFile function is called"); + await SettingsProvider.GetAndUpdateSettingsFile(VWOConfig.SDK.AccountId, VWOConfig.SDK.SdkKey); + logger.WriteLog(LogLevel.DEBUG, "Setting file has been updated"); + } + + + } + else + { + + + if (VWOClient != null) + { + logger.WriteLog(LogLevel.DEBUG, "GetAndUpdateSettingsFile function called"); + await SettingsProvider.GetAndUpdateSettingsFile(VWOConfig.SDK.AccountId, VWOConfig.SDK.SdkKey); + logger.WriteLog(LogLevel.DEBUG, "Setting file has been updated"); + + } + + + } + + + return ""; + } + } + + } diff --git a/VWOSdk.DemoApp/Controllers/SettingsProvider.cs b/VWOSdk.DemoApp/Controllers/SettingsProvider.cs index a3a7324..1b5a987 100644 --- a/VWOSdk.DemoApp/Controllers/SettingsProvider.cs +++ b/VWOSdk.DemoApp/Controllers/SettingsProvider.cs @@ -1,53 +1,47 @@ using System.IO; using System.Reflection; +using System.Threading.Tasks; + namespace VWOSdk.DemoApp.Controllers { public class SettingsProvider { - public static Settings GetSettingsFile(long accountId, string sdkKey) - { - if (accountId == 123456) - return GetSettingsFile("DemoSettingsFile"); - return VWO.GetSettingsFile(accountId, sdkKey); - } - private static Settings GetSettingsFile(string filename) - { - string json = GetJsonText(filename); - return Newtonsoft.Json.JsonConvert.DeserializeObject(json); + + private static string _SettingsFilePath = Defaults.SettingsFilePath; + public static Settings GetSettingsFile(long accountId, string sdkKey) + { + if (File.Exists(_SettingsFilePath) == false) + { + File.Create(_SettingsFilePath).Close(); + } + Settings SettingsFile = VWO.GetSettingsFile(accountId, sdkKey); + _ = SaveAsync(SettingsFile); + return SettingsFile; } - private static string GetJsonText(string filename) + public static async Task GetAndUpdateSettingsFile(long accountId, string sdkKey) { - string path = null; - - foreach (var resource in Assembly.GetExecutingAssembly().GetManifestResourceNames()) + if (File.Exists(_SettingsFilePath) == false) { - if (resource.Contains("." + filename + ".")) - { - path = resource; - break; - } + File.Create(_SettingsFilePath).Close(); } - - try + Settings SettingsFile = VWO.GetAndUpdateSettingsFile(accountId, sdkKey); + if (SettingsFile != null) { - var _assembly = Assembly.GetExecutingAssembly(); - using (Stream resourceStream = _assembly.GetManifestResourceStream(path)) - { - if (resourceStream == null) - return null; - - using (StreamReader reader = new StreamReader(resourceStream)) - { - return reader.ReadToEnd(); - } - } + await File.WriteAllTextAsync(_SettingsFilePath, Newtonsoft.Json.JsonConvert.SerializeObject(SettingsFile, Newtonsoft.Json.Formatting.Indented)); } - catch { } - - return null; + return GetSettingsFile(); + } + public static async Task SaveAsync(Settings SettingsFile) + { + await File.WriteAllTextAsync(_SettingsFilePath, Newtonsoft.Json.JsonConvert.SerializeObject(SettingsFile, Newtonsoft.Json.Formatting.Indented)); + } + private static Settings GetSettingsFile() + { + string json = File.ReadAllText(_SettingsFilePath); + return Newtonsoft.Json.JsonConvert.DeserializeObject(json); } - } + } } diff --git a/VWOSdk.DemoApp/Models/Default.cs b/VWOSdk.DemoApp/Models/Default.cs index 6a30835..0e7ea8c 100644 --- a/VWOSdk.DemoApp/Models/Default.cs +++ b/VWOSdk.DemoApp/Models/Default.cs @@ -4,11 +4,17 @@ namespace VWOSdk.DemoApp { internal class Defaults { - public readonly static long AccountId = 0; public readonly static string SdkKey = "your-sdk-key"; public readonly static string CampaignKey = "your-campaign-key"; ////Assign actual value; public readonly static string GoalIdentifier = "your-goal-identifier"; ////Assign actual value + //SettingsFile Path + public readonly static string SettingsFilePath = @"Resources/DemoSettingsFile.json"; + //Webhook + public readonly static string WebhookSecretKey = "";//your-Webhook-Secret-Key + //Batch Event + public readonly static int? EventsPerRequest = 6; //default 100 + public readonly static int? RequestTimeInterval = 60; //default:- 10 * 60(secs) = 600 secs i.e. 10 minutes public readonly static Dictionary Options = new Dictionary() { { diff --git a/VWOSdk.DemoApp/Models/FlushCallback.cs b/VWOSdk.DemoApp/Models/FlushCallback.cs new file mode 100644 index 0000000..3132b1f --- /dev/null +++ b/VWOSdk.DemoApp/Models/FlushCallback.cs @@ -0,0 +1,16 @@ +using Newtonsoft.Json; +using System.Collections.Generic; + +namespace VWOSdk.DemoApp +{ + internal class FlushCallback : IFlushInterface + { + public void onFlush(string error, object events) + { + CustomLogger logger = new CustomLogger(); + logger.WriteLog(LogLevel.DEBUG, "OnFlush call from SDK: " + events.ToString()); + + } + + } +} diff --git a/VWOSdk.DemoApp/Models/HookCallback.cs b/VWOSdk.DemoApp/Models/HookCallback.cs new file mode 100644 index 0000000..57f2d17 --- /dev/null +++ b/VWOSdk.DemoApp/Models/HookCallback.cs @@ -0,0 +1,15 @@ +using Newtonsoft.Json; +using System.Collections.Generic; +namespace VWOSdk.DemoApp +{ + internal class HookCallback : IntegrationEventListener + { + public void onEvent(Dictionary properties) + { + string payLoad = JsonConvert.SerializeObject(properties); + CustomLogger logger = new CustomLogger(); + logger.WriteLog(LogLevel.DEBUG, "onEvent call from SDK: " + payLoad); + + } + } +} diff --git a/VWOSdk.DemoApp/VWOSdk.DemoApp.csproj b/VWOSdk.DemoApp/VWOSdk.DemoApp.csproj index 3df66b3..d7b5c46 100644 --- a/VWOSdk.DemoApp/VWOSdk.DemoApp.csproj +++ b/VWOSdk.DemoApp/VWOSdk.DemoApp.csproj @@ -1,27 +1,15 @@ - netcoreapp2.0 - - - - - - - - + - - - - diff --git a/VWOSdk.DemoApp/Views/Home/Index.cshtml b/VWOSdk.DemoApp/Views/Home/Index.cshtml index dce938c..c66428e 100644 --- a/VWOSdk.DemoApp/Views/Home/Index.cshtml +++ b/VWOSdk.DemoApp/Views/Home/Index.cshtml @@ -17,6 +17,7 @@
  • Feature Rollout
  • Feature Test
  • Push Api
  • +
  • Flush Events