static void Main(string[] args) { //EntityFrameworkCache.Initialize(new ServiceStackRedisCache(new ServiceStackRedisCacheOptions //{ // Host = "172.16.6.40", // Password = "******" //})); //EntityFrameworkCache.Initialize(new StackExchangeRedisCache(new StackExchangeRedisCacheOptions() //{ // Configuration="172.16.6.40:6379,serviceName=Sky-Redis01-Cluster01,password=SCFLgskjhb9wqdi0weugbfjpsodkf8" //})); EntityFrameworkCache.Initialize(new InMemoryCache()); litlyEntities db = new litlyEntities(); var urls = db.Urls.Where(u => u.CompanyId == 1).Select(u => new { u.ShortUrl, u.LongUrl }).ToList(); db.Urls.Add(new Url { ShortUrl = "test", LongUrl = "test.com", CompanyId = 1, UserId = "54731be8-2b39-4bf7-be15-19ecabbb821e", RegDate = DateTime.Now }); db.SaveChanges(); var url = db.Urls.First(u => u.ShortUrl == "test"); url.Hits = 10; db.SaveChanges(); db.Urls.Remove(url); db.SaveChanges(); urls = db.Urls.Where(u => u.CompanyId == 1).Select(u => new { u.ShortUrl, u.LongUrl }).ToList(); }
public void InMemoryCacheInitialStatisticsAreAllZero() { var cacheWithStatistics = new EntityFrameworkCache(); Assert.AreEqual(0, cacheWithStatistics.Hits); Assert.AreEqual(0, cacheWithStatistics.ItemAdds); Assert.AreEqual(0, cacheWithStatistics.ItemInvalidations); Assert.AreEqual(0, cacheWithStatistics.Misses); }
public void InMemoryCacheCacheMissTests() { var cacheWithStatistics = new EntityFrameworkCache(); object value; Assert.IsFalse(cacheWithStatistics.GetItem("NoSuchItem", out value)); Assert.IsNull(value); Assert.AreEqual(0, cacheWithStatistics.Hits); Assert.AreEqual(1, cacheWithStatistics.Misses); Assert.AreEqual(0, cacheWithStatistics.ItemInvalidations); Assert.AreEqual(0, cacheWithStatistics.ItemAdds); }
public void InMemoryCacheCacheHitTests() { var cacheWithStatistics = new EntityFrameworkCache(); object value; cacheWithStatistics.PutItem("Item1", "someValue", new string[0], TimeSpan.Zero, DateTime.MaxValue); Assert.IsTrue(cacheWithStatistics.GetItem("Item1", out value)); Assert.AreEqual(value, "someValue"); Assert.AreEqual(1, cacheWithStatistics.Hits); Assert.AreEqual(0, cacheWithStatistics.Misses); Assert.AreEqual(0, cacheWithStatistics.ItemInvalidations); Assert.AreEqual(1, cacheWithStatistics.ItemAdds); }
private static void Main() { EntityFrameworkCache.Initialize(new InMemoryCache()); var language = ConfigurationManager.AppSettings["language"]; Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo(language); Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo(language); Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); if (Properties.Settings.Default.firstTime) { Application.Run(new Ar_Eng()); } else { Application.Run(new Loginn()); } }
public void InMemoryCacheCacheExpirationTest1() { var cacheWithStatistics = new EntityFrameworkCache(); object value; // current time is 10:00 cacheWithStatistics.GetCurrentDate = () => new DateTime(2009, 1, 1, 10, 0, 0); // set expiration time to 11:00 cacheWithStatistics.PutItem("Item1", "someValue", new string[0], TimeSpan.Zero, new DateTime(2009, 1, 1, 11, 0, 0)); // make sure the item is still there cacheWithStatistics.GetCurrentDate = () => new DateTime(2009, 1, 1, 10, 59, 59); Assert.IsTrue(cacheWithStatistics.GetItem("Item1", out value)); Assert.AreEqual(value, "someValue"); Assert.AreEqual(0, cacheWithStatistics.ItemInvalidations); // make sure the item gets evicted at 11:00 cacheWithStatistics.GetCurrentDate = () => new DateTime(2009, 1, 1, 11, 00, 00); Assert.IsFalse(cacheWithStatistics.GetItem("Item1", out value)); Assert.AreEqual(1, cacheWithStatistics.ItemInvalidations); }
/// <summary> /// This method gets called by the runtime. Use this method to add services to the container. /// For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940 /// </summary> /// <param name="services"></param> /// <returns></returns> public IServiceProvider ConfigureServices(IServiceCollection services) { services.AddHttpsRedirection(options => { options.HttpsPort = 443; }); services.AddDistributedMemoryCache(); // If environment is localhost, then enable CORS policy, otherwise no cross-origin access services.AddCors(options => { options.AddPolicy("CorsPolicy", builder => builder .AllowAnyOrigin() .AllowAnyHeader() .AllowAnyMethod()); }); // Add framework services // Add functionality to inject IOptions<T> services.AddOptions(); services.Configure <JwtSettings>(_configuration.GetSection("JwtSettings")); // Add our Config object so it can be injected //services.Configure<SecureHeadersMiddlewareConfiguration>( // _configuration.GetSection("SecureHeadersMiddlewareConfiguration")); services.AddLogging(); services.AddRouting(options => options.LowercaseUrls = true); services.AddSession(options => { // Set a short timeout for easy testing. options.IdleTimeout = TimeSpan.FromMinutes(50); options.Cookie.HttpOnly = true; options.Cookie.Name = ApiConstants.ApplicationName; options.Cookie.SecurePolicy = CookieSecurePolicy.SameAsRequest; }); services.AddDbContext <EntityDbContext>(builder => { if (_env.IsDevelopment()) { builder.UseSqlite(_configuration.GetValue <string>("ConnectionStrings:Sqlite")); } else { builder.UseNpgsql( ConnectionStringUrlToResource(_configuration.GetRequiredValue <string>("DATABASE_URL"))); } }); services.AddIdentity <User, UserRole>(opt => opt.User.RequireUniqueEmail = true) .AddRoles <UserRole>() .AddEntityFrameworkStores <EntityDbContext>() .AddDefaultTokenProviders(); if (_env.IsDevelopment()) { EntityFrameworkCache.Initialize(new InMemoryCache()); } else { var redisCacheConfig = ConfigurationOptions.Parse(_configuration.GetValue <string>("REDISTOGO_URL")); redisCacheConfig.AbortOnConnectFail = false; // Needed otherwise redis client will fail EntityFrameworkCache.Initialize(new RedisCache(redisCacheConfig)); } var jwtSetting = _configuration .GetSection("JwtSettings") .Get <JwtSettings>(); services.AddAuthentication(options => { options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; }) .AddJwtBearer(config => { config.RequireHttpsMetadata = false; config.SaveToken = true; config.TokenValidationParameters = new TokenValidationParameters { ValidIssuer = jwtSetting.Issuer, ValidAudience = jwtSetting.Audience, IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtSetting.Key)) }; }); services.AddControllers(opt => { opt.EnableEndpointRouting = false; opt.ModelValidatorProviders.Clear(); // Not need to have https opt.RequireHttpsPermanent = false; // Allow anonymous for localhost if (_env.IsDevelopment()) { opt.Filters.Add <AllowAnonymousFilter>(); } opt.Filters.Add <CustomExceptionFilterAttribute>(); opt.Filters.Add <FileUploadActionFilterAttribute>(); }) .AddNewtonsoftJson(option => option.SerializerSettings.Converters.Add(new StringEnumConverter())); services.Configure <ForwardedHeadersOptions>(options => { options.ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto; options.KnownNetworks.Clear(); options.KnownProxies.Clear(); }); services.AddSwaggerGen(config => { config.SwaggerDoc("v1", new OpenApiInfo { Title = "Contractor-Finder-Api", Description = "Contractor finder service API layer, .NET Core + PostgresSQL" }); // Set the comments path for the Swagger JSON and UI. var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml"; var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile); if (File.Exists(xmlPath)) { config.IncludeXmlComments(xmlPath); } config.OperationFilter <FileUploadOperation>(); config.AddSecurityDefinition("Bearer", // Name the security scheme new OpenApiSecurityScheme { Description = "JWT Authorization header using the Bearer scheme.", Type = SecuritySchemeType.Http, // We set the scheme type to http since we're using bearer authentication Scheme = "bearer" // The name of the HTTP Authorization scheme to be used in the Authorization header. In this case "bearer". }); }); var container = new Container(config => { if (_env.IsDevelopment()) { config.For <IS3Service>().Use <InMemoryS3>().Singleton(); } else { var(accessKeyId, secretAccessKey, url) = ( _configuration.GetRequiredValue <string>("CLOUDCUBE_ACCESS_KEY_ID"), _configuration.GetRequiredValue <string>("CLOUDCUBE_SECRET_ACCESS_KEY"), _configuration.GetRequiredValue <string>("CLOUDCUBE_URL") ); var prefix = new Uri(url).Segments.Skip(1).FirstOrDefault() ?? throw new Exception("S3 url is malformed"); const string bucketName = "cloud-cube"; // Generally bad practice var credentials = new BasicAWSCredentials(accessKeyId, secretAccessKey); // Create S3 client config.For <IAmazonS3>().Use(() => new AmazonS3Client(credentials, RegionEndpoint.USEast1)); config.For <S3ServiceConfig>().Use(new S3ServiceConfig(bucketName, prefix)); } // Register stuff in container, using the StructureMap APIs... config.Scan(_ => { _.AssemblyContainingType(typeof(Startup)); _.Assembly("Logic"); _.Assembly("Dal"); _.WithDefaultConventions(); }); // Populate the container using the service collection config.Populate(services); config.For <IMapper>().Use(ctx => ResolveMapper(ctx, Assembly.Load("Logic"))).Singleton(); }); // container.AssertConfigurationIsValid(); return(container.GetInstance <IServiceProvider>()); }
/// <summary> /// This method gets called by the runtime. Use this method to add services to the container. /// For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940 /// </summary> /// <param name="services"></param> /// <returns></returns> public IServiceProvider ConfigureServices(IServiceCollection services) { var postgresConnectionString = ConnectionStringUrlToResource(_configuration.GetValue <string>("DATABASE_URL") ?? throw new Exception("DATABASE_URL is null")); services.AddOptions(); services.AddLogging(); services.AddRouting(options => { options.LowercaseUrls = true; }); if (_env.IsDevelopment()) { services.AddDistributedMemoryCache(); } else { services.AddStackExchangeRedisCache(x => x.Configuration = _configuration.GetValue <string>("REDISTOGO_URL")); } services.AddSession(options => { // Set a short timeout for easy testing. options.IdleTimeout = TimeSpan.FromMinutes(50); options.Cookie.HttpOnly = true; options.Cookie.Name = ApiConstants.AuthenticationSessionCookieName; options.Cookie.SecurePolicy = CookieSecurePolicy.SameAsRequest; }); services.AddSwaggerGen(c => { c.SwaggerDoc("v1", new OpenApiInfo { Title = "oriental-rug-gallery-API", Version = "v1" }); }); services.AddMvc(x => { x.ModelValidatorProviders.Clear(); // Not need to have https x.RequireHttpsPermanent = false; // Allow anonymous for localhost if (_env.IsDevelopment()) { x.Filters.Add <AllowAnonymousFilter>(); } }).AddNewtonsoftJson(x => { x.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore; x.SerializerSettings.Converters.Add(new StringEnumConverter()); }).AddRazorPagesOptions(x => { x.Conventions.ConfigureFilter(new IgnoreAntiforgeryTokenAttribute()); }); services.AddWebMarkupMin(opt => { opt.AllowMinificationInDevelopmentEnvironment = true; opt.AllowCompressionInDevelopmentEnvironment = true; }) .AddHtmlMinification() .AddHttpCompression(); services.AddDbContext <EntityDbContext>(opt => opt.UseNpgsql(postgresConnectionString)); services.AddIdentity <User, IdentityRole <int> >(x => { x.User.RequireUniqueEmail = true; }) .AddEntityFrameworkStores <EntityDbContext>() .AddRoles <IdentityRole <int> >() .AddDefaultTokenProviders(); // L2 EF cache if (_env.IsDevelopment()) { EntityFrameworkCache.Initialize(new InMemoryCache()); } else { var redisConfigurationOptions = ConfigurationOptions.Parse(_configuration.GetValue <string>("REDISTOGO_URL")); // Important redisConfigurationOptions.AbortOnConnectFail = false; EntityFrameworkCache.Initialize(new RedisCache(redisConfigurationOptions)); } services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme).AddCookie(x => { x.Cookie.MaxAge = TimeSpan.FromMinutes(60); }); // Re-Captcha config services.Configure <RecaptchaSettings>(_configuration.GetSection("RecaptchaSettings")); services.AddTransient <IRecaptchaService, RecaptchaService>(); _container = new Container(config => { config.For <DocumentStore>().Use(DocumentStore.For(y => { // Important as PLV8 is disabled on Heroku y.PLV8Enabled = false; y.Connection(postgresConnectionString); y.AutoCreateSchemaObjects = AutoCreate.CreateOrUpdate; })); var(accessKeyId, secretAccessKey, url) = ( _configuration.GetRequiredValue <string>("CLOUDCUBE_ACCESS_KEY_ID"), _configuration.GetRequiredValue <string>("CLOUDCUBE_SECRET_ACCESS_KEY"), _configuration.GetRequiredValue <string>("CLOUDCUBE_URL") ); var prefix = new Uri(url).Segments.Skip(1).FirstOrDefault() ?? throw new Exception("S3 url is malformed"); const string bucketName = "cloud-cube"; // Generally bad practice var credentials = new BasicAWSCredentials(accessKeyId, secretAccessKey); // Create S3 client config.For <IAmazonS3>().Use(() => new AmazonS3Client(credentials, RegionEndpoint.USEast1)); config.For <S3ServiceConfig>().Use(new S3ServiceConfig(bucketName, prefix)); // Register stuff in container, using the StructureMap APIs... config.Scan(_ => { _.AssemblyContainingType(typeof(Startup)); _.Assembly("Api"); _.Assembly("Logic"); _.Assembly("Dal"); _.WithDefaultConventions(); }); // Populate the container using the service collection config.Populate(services); }); _container.AssertConfigurationIsValid(); return(_container.GetInstance <IServiceProvider>()); }
public void InMemoryCacheCacheExpirationTest2() { var cacheWithStatistics = new EntityFrameworkCache(); object value; // current time is 10:00 cacheWithStatistics.GetCurrentDate = () => new DateTime(2009, 1, 1, 10, 0, 0); // set expiration time to 1 hour from the last access cacheWithStatistics.PutItem("Item1", "someValue", new string[0], TimeSpan.FromHours(1), DateTime.MaxValue); // make sure the item is still there cacheWithStatistics.GetCurrentDate = () => new DateTime(2009, 1, 1, 10, 59, 59); Assert.IsTrue(cacheWithStatistics.GetItem("Item1", out value)); Assert.AreEqual(value, "someValue"); Assert.AreEqual(0, cacheWithStatistics.ItemInvalidations); // make sure the item does not get evicted at 11:00 because we have touched it a second ago cacheWithStatistics.GetCurrentDate = () => new DateTime(2009, 1, 1, 11, 00, 00); Assert.IsTrue(cacheWithStatistics.GetItem("Item1", out value)); Assert.AreEqual(value, "someValue"); Assert.AreEqual(0, cacheWithStatistics.ItemInvalidations); Assert.IsNotNull(cacheWithStatistics.LruChainHead); // make sure the item does not get evicted at 12:00 because we have touched it an hour ago cacheWithStatistics.GetCurrentDate = () => new DateTime(2009, 1, 1, 12, 00, 00); Assert.IsFalse(cacheWithStatistics.GetItem("Item1", out value)); Assert.AreEqual(1, cacheWithStatistics.ItemInvalidations); Assert.IsNull(cacheWithStatistics.LruChainHead); Assert.IsNull(cacheWithStatistics.LruChainTail); }
private static string GetItemKeysInLruOrder(EntityFrameworkCache imc) { var sb = new StringBuilder(); var separator = string.Empty; var visisted = new HashSet<string>(); CacheEntry lastEntry = null; for (var ce = imc.LruChainHead; ce != null; ce = ce.NextEntry) { if (visisted.Contains(ce.Key)) { throw new InvalidOperationException("Cycle in the LRU chain on: " + ce); } if (!Equals(ce.PreviousEntry, lastEntry)) { var message = "Invalid previous pointer on LRU chain: " + ce + " Is: " + ce.PreviousEntry + " expected: " + lastEntry; throw new InvalidOperationException(message); } if (lastEntry != null && ce.LastAccessTime.Subtract(lastEntry.LastAccessTime).TotalMilliseconds > 500) { var message = "Invalid LastAccess time. Current: " + ce.LastAccessTime.Ticks + " previous: " + lastEntry.LastAccessTime.Ticks; throw new InvalidOperationException(message); } sb.Append(separator); sb.Append(ce.Key); separator = "|"; visisted.Add(ce.Key); lastEntry = ce; } Assert.AreSame(lastEntry, imc.LruChainTail); return sb.ToString(); }
public void MicroStressTest() { // Run a bunch of concurrent reads and writes, make sure we get no exceptions var imc = new EntityFrameworkCache(100); const int NumberOfRequestBatches = 50; // will be multiplied by 5 (3 readers + 1 writer + 1 invalidator) const int NumberOfIterationsPerThread = 100; var startEvent = new ManualResetEvent(false); Action writer = () => { startEvent.WaitOne(); var random = new Random(); for (var i = 0; i < NumberOfIterationsPerThread; ++i) { var randomKey = Guid.NewGuid().ToString("N").Substring(0, 4); var randomValue = randomKey + "_V"; var dependentSets = new List<string>(); var numberOfDependencies = random.Next(5); for (var j = 0; j < numberOfDependencies; ++j) { var randomSetName = new string((char)('A' + random.Next(26)), 1); dependentSets.Add(randomSetName); } imc.PutItem(randomKey, randomValue, dependentSets, TimeSpan.Zero, DateTime.MaxValue); } }; Action invalidator = () => { startEvent.WaitOne(); var random = new Random(); for (var i = 0; i < NumberOfIterationsPerThread; ++i) { var dependentSets = new List<string>(); var numberOfDependencies = random.Next(5); for (var j = 0; j < numberOfDependencies; ++j) { var randomSetName = new string((char)('A' + random.Next(26)), 1); dependentSets.Add(randomSetName); } imc.InvalidateSets(dependentSets); } }; Action reader = () => { startEvent.WaitOne(); for (var i = 0; i < NumberOfIterationsPerThread; ++i) { var randomKey = Guid.NewGuid().ToString("N").Substring(0, 4); object value; if (imc.GetItem(randomKey, out value)) { Assert.AreEqual(randomKey + "_V", value); } } }; var threads = new List<Thread>(); for (var i = 0; i < NumberOfRequestBatches; ++i) { threads.Add(new Thread(() => writer())); threads.Add(new Thread(() => invalidator())); threads.Add(new Thread(() => reader())); threads.Add(new Thread(() => reader())); threads.Add(new Thread(() => reader())); } foreach (var t in threads) { t.Start(); } startEvent.Set(); foreach (var t in threads) { t.Join(); } }
public void DependenciesTest4() { var imc = new EntityFrameworkCache(); imc.PutItem("A", "A1", new[] { "set1" }, TimeSpan.Zero, DateTime.MaxValue); imc.PutItem("B", "B1", new[] { "set1", "set2" }, TimeSpan.Zero, DateTime.MaxValue); imc.PutItem("C", "C1", new[] { "set2", "set3" }, TimeSpan.Zero, DateTime.MaxValue); imc.PutItem("D", "D1", new[] { "set3", "set1" }, TimeSpan.Zero, DateTime.MaxValue); Assert.AreEqual("D|C|B|A", GetItemKeysInLruOrder(imc)); imc.PutItem("B", "C1", new[] { "set3" }, TimeSpan.Zero, DateTime.MaxValue); Assert.AreEqual("B|D|C|A", GetItemKeysInLruOrder(imc)); imc.InvalidateSets(new[] { "set3" }); Assert.AreEqual("A", GetItemKeysInLruOrder(imc)); }
public void LruWithLimitTest2() { var imc = new EntityFrameworkCache(3); Assert.AreEqual(3, imc.MaxItems); imc.PutItem("A", "A1", new string[0], TimeSpan.Zero, DateTime.MaxValue); imc.PutItem("B", "B1", new string[0], TimeSpan.Zero, DateTime.MaxValue); imc.PutItem("C", "C1", new string[0], TimeSpan.Zero, DateTime.MaxValue); imc.PutItem("D", "D1", new string[0], TimeSpan.Zero, DateTime.MaxValue); Assert.AreEqual("D|C|B", GetItemKeysInLruOrder(imc)); imc.PutItem("E", "E1", new string[0], TimeSpan.Zero, DateTime.MaxValue); Assert.AreEqual("E|D|C", GetItemKeysInLruOrder(imc)); imc.PutItem("F", "F1", new string[0], TimeSpan.Zero, DateTime.MaxValue); Assert.AreEqual("F|E|D", GetItemKeysInLruOrder(imc)); }
public void LruTest1() { var imc = new EntityFrameworkCache(); Assert.AreEqual(int.MaxValue, imc.MaxItems); imc.PutItem("A", "A1", new string[0], TimeSpan.Zero, DateTime.MaxValue); imc.PutItem("B", "B1", new string[0], TimeSpan.Zero, DateTime.MaxValue); imc.PutItem("C", "C1", new string[0], TimeSpan.Zero, DateTime.MaxValue); imc.PutItem("D", "D1", new string[0], TimeSpan.Zero, DateTime.MaxValue); Assert.AreEqual("D|C|B|A", GetItemKeysInLruOrder(imc)); object value; imc.GetItem("D", out value); Assert.AreEqual("D|C|B|A", GetItemKeysInLruOrder(imc)); imc.GetItem("C", out value); Assert.AreEqual("C|D|B|A", GetItemKeysInLruOrder(imc)); imc.GetItem("D", out value); Assert.AreEqual("D|C|B|A", GetItemKeysInLruOrder(imc)); imc.GetItem("A", out value); Assert.AreEqual("A|D|C|B", GetItemKeysInLruOrder(imc)); imc.GetItem("B", out value); Assert.AreEqual("B|A|D|C", GetItemKeysInLruOrder(imc)); imc.InvalidateItem("B"); Assert.AreEqual("A|D|C", GetItemKeysInLruOrder(imc)); imc.InvalidateItem("C"); Assert.AreEqual("A|D", GetItemKeysInLruOrder(imc)); imc.InvalidateItem("A"); Assert.AreEqual("D", GetItemKeysInLruOrder(imc)); imc.InvalidateItem("D"); Assert.AreEqual(string.Empty, GetItemKeysInLruOrder(imc)); }
public void InMemoryCacheCacheExpirationTest3() { var cacheWithStatistics = new EntityFrameworkCache(); object value; // current time is 10:00 cacheWithStatistics.GetCurrentDate = () => new DateTime(2009, 1, 1, 10, 0, 0); cacheWithStatistics.PutItem("Item1", "someValue", new string[0], TimeSpan.Zero, new DateTime(2009, 1, 1, 10, 0, 0)); cacheWithStatistics.PutItem("Item2", "someValue", new string[0], TimeSpan.Zero, new DateTime(2009, 1, 1, 10, 1, 0)); cacheWithStatistics.PutItem("Item3", "someValue", new string[0], TimeSpan.Zero, new DateTime(2009, 1, 1, 10, 2, 0)); cacheWithStatistics.PutItem("Item4", "someValue", new string[0], TimeSpan.Zero, new DateTime(2009, 1, 1, 10, 3, 0)); cacheWithStatistics.GetCurrentDate = () => new DateTime(2009, 1, 1, 10, 2, 0); // no invalidation happens until we try to get an item Assert.AreEqual("Item4|Item3|Item2|Item1", GetItemKeysInLruOrder(cacheWithStatistics)); Assert.IsFalse(cacheWithStatistics.GetItem("Item1", out value)); Assert.AreEqual("Item4", GetItemKeysInLruOrder(cacheWithStatistics)); }
/// <summary> /// This method gets called by the runtime. Use this method to add services to the container. /// For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940 /// </summary> /// <param name="services"></param> /// <returns></returns> public IServiceProvider ConfigureServices(IServiceCollection services) { // services.AddMiniProfiler(opt => // { // // opt.RouteBasePath = "/profiler"; // opt.ShouldProfile = _ => true; // opt.ShowControls = true; // opt.StackMaxLength = short.MaxValue; // opt.PopupStartHidden = false; // opt.PopupShowTrivial = true; // opt.PopupShowTimeWithChildren = true; // }); services.AddHttpsRedirection(options => options.HttpsPort = 443); // If environment is localhost, then enable CORS policy, otherwise no cross-origin access services.AddCors(options => options.AddPolicy("CorsPolicy", builder => builder .WithOrigins(_configuration.GetSection("TrustedSpaUrls").Get <string[]>()) .AllowAnyHeader() .AllowAnyMethod() .AllowCredentials())); // Add framework services // Add functionality to inject IOptions<T> services.AddOptions(); services.AddResponseCompression(); services.Configure <JwtSettings>(_configuration.GetSection("JwtSettings")); services.AddLogging(); services.AddRouting(options => options.LowercaseUrls = true); if (_env.IsDevelopment()) { services.AddDistributedMemoryCache(); } else { var redisConnectionString = ConnectionStringUrlToRedisResource(_configuration.GetValue <string>("REDISTOGO_URL")); services.AddStackExchangeRedisCache(c => c.Configuration = redisConnectionString); } services.AddSession(options => { // Set a short timeout for easy testing. options.IdleTimeout = TimeSpan.FromMinutes(60); options.Cookie.HttpOnly = true; options.Cookie.Name = ApiConstants.AuthenticationSessionCookieName; options.Cookie.SecurePolicy = CookieSecurePolicy.None; }); services.AddSwaggerGen(c => { c.SwaggerDoc("v1", new OpenApiInfo { Title = "dotnet-template", Version = "v1" }); // Set the comments path for the Swagger JSON and UI. var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml"; var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile); if (File.Exists(xmlPath)) { c.IncludeXmlComments(xmlPath); } c.AddSecurityDefinition("Bearer", // Name the security scheme new OpenApiSecurityScheme { Description = "JWT Authorization header using the Bearer scheme.", Type = SecuritySchemeType.Http, // We set the scheme type to http since we're using bearer authentication Scheme = "bearer" // The name of the HTTP Authorization scheme to be used in the Authorization header. In this case "bearer". }); }); services.AddMvc(x => { x.ModelValidatorProviders.Clear(); // Not need to have https x.RequireHttpsPermanent = false; // Allow anonymous for localhost if (_env.IsDevelopment()) { x.Filters.Add <AllowAnonymousFilter>(); } // Exception filter attribute x.Filters.Add <ExceptionFilterAttribute>(); }).AddNewtonsoftJson(x => { x.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore; }) .AddRazorPagesOptions(x => x.Conventions.ConfigureFilter(new IgnoreAntiforgeryTokenAttribute())); services.AddDbContext <EntityDbContext>(opt => { if (_env.IsDevelopment()) { opt.UseSqlite(_configuration.GetValue <string>("ConnectionStrings:Sqlite")); } else { var postgresConnectionString = ConnectionStringUrlToPgResource(_configuration.GetValue <string>("DATABASE_URL") ?? throw new Exception("DATABASE_URL is null")); opt.UseNpgsql(postgresConnectionString); } }); services.AddIdentity <User, IdentityRole <int> >(x => x.User.RequireUniqueEmail = true) .AddEntityFrameworkStores <EntityDbContext>() .AddRoles <IdentityRole <int> >() .AddDefaultTokenProviders(); // L2 EF cache if (_env.IsDevelopment()) { EntityFrameworkCache.Initialize(new InMemoryCache()); } else { var redisConnectionString = ConnectionStringUrlToRedisResource(_configuration.GetValue <string>("REDISTOGO_URL")); var redisConfigurationOptions = ConfigurationOptions.Parse(redisConnectionString); // Important redisConfigurationOptions.AbortOnConnectFail = false; EntityFrameworkCache.Initialize(new RedisCache(redisConfigurationOptions)); } var jwtSetting = _configuration .GetSection("JwtSettings") .Get <JwtSettings>(); if (_env.IsDevelopment() && string.IsNullOrEmpty(jwtSetting.Key)) { jwtSetting.Key = PasswordGenerator.Generate(length: 100, allowed: Sets.Alphanumerics); IdentityModelEventSource.ShowPII = true; } services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme) .AddCookie(x => x.Cookie.MaxAge = TimeSpan.FromMinutes(60)) .AddJwtBearer(config => { config.RequireHttpsMetadata = false; config.SaveToken = true; config.TokenValidationParameters = new TokenValidationParameters { ValidIssuer = jwtSetting.Issuer, ValidAudience = jwtSetting.Audience, IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtSetting.Key)) }; }); services.AddSingleton <IUserIdProvider, CustomUserIdProvider>(); services.AddSignalR(config => { config.MaximumReceiveMessageSize = 10 * 1024 * 1024; // 10 mega-bytes config.StreamBufferCapacity = 50; config.EnableDetailedErrors = true; }); // Re-Captcha config services.Configure <RecaptchaSettings>(_configuration.GetSection("RecaptchaSettings")); services.AddTransient <IRecaptchaService, RecaptchaService>(); services.AddEfRepository <EntityDbContext>(x => x.Profile(Assembly.Load("Dal"))); var container = new Container(config => { config.For <JwtSettings>().Use(jwtSetting).Singleton(); // If environment is localhost then use mock email service if (_env.IsDevelopment()) { config.For <IS3Service>().Use(new S3Service()).Singleton(); } else { var(accessKeyId, secretAccessKey, url) = ( _configuration.GetRequiredValue <string>("CLOUDCUBE_ACCESS_KEY_ID"), _configuration.GetRequiredValue <string>("CLOUDCUBE_SECRET_ACCESS_KEY"), _configuration.GetRequiredValue <string>("CLOUDCUBE_URL") ); var prefix = new Uri(url).Segments.GetValue(1)?.ToString(); const string bucketName = "cloud-cube"; // Generally bad practice var credentials = new BasicAWSCredentials(accessKeyId, secretAccessKey); // Create S3 client config.For <IAmazonS3>().Use(() => new AmazonS3Client(credentials, RegionEndpoint.USEast1)); config.For <S3ServiceConfig>().Use(new S3ServiceConfig(bucketName, prefix)); config.For <IS3Service>().Use(ctx => new S3Service( ctx.GetInstance <ILogger <S3Service> >(), ctx.GetInstance <IAmazonS3>(), ctx.GetInstance <S3ServiceConfig>() )); } // Register stuff in container, using the StructureMap APIs... config.Scan(_ => { _.AssemblyContainingType(typeof(Startup)); _.Assembly("Api"); _.Assembly("Logic"); _.Assembly("Dal"); _.WithDefaultConventions(); }); // Populate the container using the service collection config.Populate(services); }); container.AssertConfigurationIsValid(); return(container.GetInstance <IServiceProvider>()); }