Reacting to the cache package rename and few misc changes

1. Setting expiry time for cached items.
2. Some other misc changes.
This commit is contained in:
Praburaj 2014-09-12 17:09:39 -07:00
parent 8c1bf38211
commit 39ee3e714a
12 changed files with 166 additions and 128 deletions

View File

@ -7,7 +7,8 @@ using MusicStore.Models;
using System.Linq; using System.Linq;
using MusicStore.Hubs; using MusicStore.Hubs;
using MusicStore.ViewModels; using MusicStore.ViewModels;
using Microsoft.AspNet.MemoryCache; using Microsoft.Framework.Cache.Memory;
using System;
namespace MusicStore.Areas.Admin.Controllers namespace MusicStore.Areas.Admin.Controllers
{ {
@ -66,14 +67,16 @@ namespace MusicStore.Areas.Admin.Controllers
string cacheId = string.Format("album_{0}", id); string cacheId = string.Format("album_{0}", id);
var album = cache.GetOrAdd(cacheId, context => var album = cache.GetOrAdd(cacheId, context =>
{ {
//Remove it from cache if not retrieved in last 10 minutes
context.SetSlidingExpiraiton(TimeSpan.FromMinutes(10));
//If this returns null how do we prevent the cache to store this. //If this returns null how do we prevent the cache to store this.
return db.Albums.Single(a => a.AlbumId == id); return db.Albums.Where(a => a.AlbumId == id).FirstOrDefault();
}); });
if (album == null) if (album == null)
{ {
cache.Remove(cacheId); cache.Remove(cacheId);
return HttpNotFound(); return View(album);
} }
// TODO [EF] We don't query related data as yet. We have to populate this until we do automatically. // TODO [EF] We don't query related data as yet. We have to populate this until we do automatically.
@ -101,6 +104,7 @@ namespace MusicStore.Areas.Admin.Controllers
db.Albums.Add(album); db.Albums.Add(album);
db.SaveChanges(); db.SaveChanges();
annoucementHub.Clients.All.announcement(new AlbumData() { Title = album.Title, Url = Url.Action("Details", "Store", new { id = album.AlbumId }) }); annoucementHub.Clients.All.announcement(new AlbumData() { Title = album.Title, Url = Url.Action("Details", "Store", new { id = album.AlbumId }) });
cache.Remove("latestAlbum");
return RedirectToAction("Index"); return RedirectToAction("Index");
} }
@ -113,11 +117,11 @@ namespace MusicStore.Areas.Admin.Controllers
// GET: /StoreManager/Edit/5 // GET: /StoreManager/Edit/5
public IActionResult Edit(int id) public IActionResult Edit(int id)
{ {
Album album = db.Albums.Single(a => a.AlbumId == id); Album album = db.Albums.Where(a => a.AlbumId == id).FirstOrDefault();
if (album == null) if (album == null)
{ {
return HttpNotFound(); return View(album);
} }
ViewBag.GenreId = new SelectList(db.Genres, "GenreId", "Name", album.GenreId); ViewBag.GenreId = new SelectList(db.Genres, "GenreId", "Name", album.GenreId);
@ -149,11 +153,7 @@ namespace MusicStore.Areas.Admin.Controllers
// GET: /StoreManager/RemoveAlbum/5 // GET: /StoreManager/RemoveAlbum/5
public IActionResult RemoveAlbum(int id) public IActionResult RemoveAlbum(int id)
{ {
Album album = db.Albums.Single(a => a.AlbumId == id); Album album = db.Albums.Where(a => a.AlbumId == id).FirstOrDefault();
if (album == null)
{
return HttpNotFound();
}
return View(album); return View(album);
} }
@ -162,11 +162,16 @@ namespace MusicStore.Areas.Admin.Controllers
[HttpPost, ActionName("RemoveAlbum")] [HttpPost, ActionName("RemoveAlbum")]
public IActionResult RemoveAlbumConfirmed(int id) public IActionResult RemoveAlbumConfirmed(int id)
{ {
Album album = db.Albums.Single(a => a.AlbumId == id); Album album = db.Albums.Where(a => a.AlbumId == id).FirstOrDefault();
db.Albums.Remove(album);
db.SaveChanges(); if (album != null)
//Remove the cache entry as it is removed {
cache.Remove(string.Format("album_{0}", id)); db.Albums.Remove(album);
db.SaveChanges();
//Remove the cache entry as it is removed
cache.Remove(string.Format("album_{0}", id));
}
return RedirectToAction("Index"); return RedirectToAction("Index");
} }

View File

@ -4,54 +4,61 @@
ViewBag.Title = "Details"; ViewBag.Title = "Details";
} }
<h2>Details</h2> @if (Model != null)
{
<h2>Details</h2>
<div> <div>
<h4>Album</h4> <h4>Album</h4>
<hr /> <hr />
<dl class="dl-horizontal"> <dl class="dl-horizontal">
<dt> <dt>
@Html.DisplayNameFor(model => model.Artist.Name) @Html.DisplayNameFor(model => model.Artist.Name)
</dt> </dt>
<dd> <dd>
@Html.DisplayFor(model => model.Artist.Name) @Html.DisplayFor(model => model.Artist.Name)
</dd> </dd>
<dt> <dt>
@Html.DisplayNameFor(model => model.Genre.Name) @Html.DisplayNameFor(model => model.Genre.Name)
</dt> </dt>
<dd> <dd>
@Html.DisplayFor(model => model.Genre.Name) @Html.DisplayFor(model => model.Genre.Name)
</dd> </dd>
<dt> <dt>
@Html.DisplayNameFor(model => model.Title) @Html.DisplayNameFor(model => model.Title)
</dt> </dt>
<dd> <dd>
@Html.DisplayFor(model => model.Title) @Html.DisplayFor(model => model.Title)
</dd> </dd>
<dt> <dt>
@Html.DisplayNameFor(model => model.Price) @Html.DisplayNameFor(model => model.Price)
</dt> </dt>
<dd> <dd>
@Html.DisplayFor(model => model.Price) @Html.DisplayFor(model => model.Price)
</dd> </dd>
<dt> <dt>
@Html.DisplayNameFor(model => model.AlbumArtUrl) @Html.DisplayNameFor(model => model.AlbumArtUrl)
</dt> </dt>
<dd> <dd>
@Html.DisplayFor(model => model.AlbumArtUrl) @Html.DisplayFor(model => model.AlbumArtUrl)
</dd> </dd>
</dl> </dl>
</div> </div>
}
else
{
@Html.Label(null, "Unable to locate the album")
}
<p> <p>
@Html.ActionLink("Edit", "Edit", new { id = Model.AlbumId }) | @Html.ActionLink("Edit", "Edit", new { id = Model.AlbumId }) |
@Html.ActionLink("Back to List", "Index") @Html.ActionLink("Back to List", "Index")

View File

@ -6,62 +6,69 @@
<h2>Edit</h2> <h2>Edit</h2>
@using (Html.BeginForm()) @if (Model != null)
{ {
@Html.AntiForgeryToken() @using (Html.BeginForm())
{
@Html.AntiForgeryToken()
<div class="form-horizontal"> <div class="form-horizontal">
<h4>Album</h4> <h4>Album</h4>
<hr /> <hr />
@Html.ValidationSummary(true) @Html.ValidationSummary(true)
@Html.HiddenFor(model => model.AlbumId) @Html.HiddenFor(model => model.AlbumId)
<div class="form-group"> <div class="form-group">
@Html.LabelFor(model => model.GenreId, "GenreId", new { @class = "control-label col-md-2" }) @Html.LabelFor(model => model.GenreId, "GenreId", new { @class = "control-label col-md-2" })
<div class="col-md-10"> <div class="col-md-10">
@Html.DropDownList("GenreId", String.Empty) @Html.DropDownList("GenreId", String.Empty)
@Html.ValidationMessageFor(model => model.GenreId) @Html.ValidationMessageFor(model => model.GenreId)
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.ArtistId, "ArtistId", new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.DropDownList("ArtistId", String.Empty)
@Html.ValidationMessageFor(model => model.ArtistId)
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.Title, new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.Title)
@Html.ValidationMessageFor(model => model.Title)
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.Price, new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.Price)
@Html.ValidationMessageFor(model => model.Price)
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.AlbumArtUrl, new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.AlbumArtUrl)
@Html.ValidationMessageFor(model => model.AlbumArtUrl)
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Save" class="btn btn-default" />
</div>
</div> </div>
</div> </div>
}
<div class="form-group"> }
@Html.LabelFor(model => model.ArtistId, "ArtistId", new { @class = "control-label col-md-2" }) else
<div class="col-md-10"> {
@Html.DropDownList("ArtistId", String.Empty) @Html.Label(null, "Unable to locate the album")
@Html.ValidationMessageFor(model => model.ArtistId)
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.Title, new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.Title)
@Html.ValidationMessageFor(model => model.Title)
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.Price, new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.Price)
@Html.ValidationMessageFor(model => model.Price)
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.AlbumArtUrl, new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.AlbumArtUrl)
@Html.ValidationMessageFor(model => model.AlbumArtUrl)
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Save" class="btn btn-default" />
</div>
</div>
</div>
} }
<div> <div>

View File

@ -4,20 +4,26 @@
ViewBag.Title = "Delete"; ViewBag.Title = "Delete";
} }
<h2>Delete Confirmation</h2> @if (Model != null)
<p>
Are you sure you want to delete the album titled
<strong>@Model.Title</strong>?
</p>
@using (Html.BeginForm())
{ {
<h2>Delete Confirmation</h2>
<p> <p>
<input type="submit" value="Delete" /> Are you sure you want to delete the album titled
</p> <strong>@Model.Title</strong>?
<p>
@Html.ActionLink("Back to List", "Index")
</p> </p>
@using (Html.BeginForm())
{
<p>
<input type="submit" value="Delete" />
</p>
<p>
@Html.ActionLink("Back to List", "Index")
</p>
}
}
else
{
@Html.Label(null, "Unable to locate the album")
} }

View File

@ -3,7 +3,7 @@ using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNet.Mvc; using Microsoft.AspNet.Mvc;
using MusicStore.Models; using MusicStore.Models;
using Microsoft.AspNet.MemoryCache; using Microsoft.Framework.Cache.Memory;
namespace MusicStore.Components namespace MusicStore.Components
{ {
@ -23,6 +23,7 @@ namespace MusicStore.Components
{ {
var latestAlbum = await cache.GetOrAdd("latestAlbum", async context => var latestAlbum = await cache.GetOrAdd("latestAlbum", async context =>
{ {
context.SetAbsoluteExpiration(TimeSpan.FromMinutes(10));
return await GetLatestAlbum(); return await GetLatestAlbum();
}); });

View File

@ -1,6 +1,7 @@
using Microsoft.AspNet.MemoryCache; using Microsoft.Framework.Cache.Memory;
using Microsoft.AspNet.Mvc; using Microsoft.AspNet.Mvc;
using MusicStore.Models; using MusicStore.Models;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
@ -22,7 +23,13 @@ namespace MusicStore.Controllers
public IActionResult Index() public IActionResult Index()
{ {
// Get most popular albums // Get most popular albums
var albums = cache.GetOrAdd("topselling", (context => GetTopSellingAlbums(6))); var albums = cache.GetOrAdd("topselling", context =>
{
//Refresh it every 10 minutes. Let this be the last item to be removed by cache if cache GC kicks in.
context.SetAbsoluteExpiration(TimeSpan.FromMinutes(10));
context.SetPriority(CachePreservationPriority.High);
return GetTopSellingAlbums(6);
});
return View(albums); return View(albums);
} }

View File

@ -1,6 +1,7 @@
using Microsoft.AspNet.MemoryCache; using Microsoft.Framework.Cache.Memory;
using Microsoft.AspNet.Mvc; using Microsoft.AspNet.Mvc;
using MusicStore.Models; using MusicStore.Models;
using System;
using System.Linq; using System.Linq;
namespace MusicStore.Controllers namespace MusicStore.Controllers
@ -44,6 +45,9 @@ namespace MusicStore.Controllers
{ {
var album = cache.GetOrAdd(string.Format("album_{0}", id), context => var album = cache.GetOrAdd(string.Format("album_{0}", id), context =>
{ {
//Remove it from cache if not retrieved in last 10 minutes
context.SetSlidingExpiraiton(TimeSpan.FromMinutes(10));
var albumData = db.Albums.Single(a => a.AlbumId == id); var albumData = db.Albums.Single(a => a.AlbumId == id);
// TODO [EF] We don't query related data as yet. We have to populate this until we do automatically. // TODO [EF] We don't query related data as yet. We have to populate this until we do automatically.

View File

@ -14,7 +14,7 @@ using Microsoft.AspNet.Security.Google;
using Microsoft.AspNet.Security.Twitter; using Microsoft.AspNet.Security.Twitter;
using Microsoft.AspNet.Security.MicrosoftAccount; using Microsoft.AspNet.Security.MicrosoftAccount;
using Microsoft.AspNet.Security; using Microsoft.AspNet.Security;
using Microsoft.AspNet.MemoryCache; using Microsoft.Framework.Cache.Memory;
using MusicStore.Mocks.Common; using MusicStore.Mocks.Common;
using MusicStore.Mocks.Facebook; using MusicStore.Mocks.Facebook;
using MusicStore.Mocks.Twitter; using MusicStore.Mocks.Twitter;

View File

@ -14,7 +14,7 @@ using Microsoft.AspNet.Security.Google;
using Microsoft.AspNet.Security.Twitter; using Microsoft.AspNet.Security.Twitter;
using Microsoft.AspNet.Security.MicrosoftAccount; using Microsoft.AspNet.Security.MicrosoftAccount;
using Microsoft.AspNet.Security; using Microsoft.AspNet.Security;
using Microsoft.AspNet.MemoryCache; using Microsoft.Framework.Cache.Memory;
namespace MusicStore namespace MusicStore
{ {

View File

@ -10,22 +10,22 @@ using Microsoft.Net.Http.Server;
using Microsoft.AspNet.Server.WebListener; using Microsoft.AspNet.Server.WebListener;
using System.Security.Claims; using System.Security.Claims;
using System.Security.Principal; using System.Security.Principal;
using Microsoft.AspNet.MemoryCache; using Microsoft.Framework.Cache.Memory;
namespace MusicStore namespace MusicStore
{ {
/// <summary> /// <summary>
/// To make runtime to load an environment based startup class, specify the environment by the following ways: /// To make runtime to load an environment based startup class, specify the environment by the following ways:
/// 1. Drop a Microsoft.AspNet.Hosting.ini file in the application folder /// 1. Drop a Microsoft.AspNet.Hosting.ini file in the application folder
/// 2. Add a setting in the ini file named 'env' with value of the format 'Startup[EnvironmentName]'. For example: To load a Startup class named /// 2. Add a setting in the ini file named 'KRE_ENV' with value of the format 'Startup[EnvironmentName]'. For example: To load a Startup class named
/// 'StartupNtlmAuthentication' the value of the env should be 'NtlmAuthentication' (eg. env=NtlmAuthentication). Runtime adds a 'Startup' prefix to this and loads 'StartupNtlmAuthentication'. /// 'StartupNtlmAuthentication' the value of the env should be 'NtlmAuthentication' (eg. KRE_ENV=NtlmAuthentication). Runtime adds a 'Startup' prefix to this and loads 'StartupNtlmAuthentication'.
/// If no environment name is specified the default startup class loaded is 'Startup'. /// If no environment name is specified the default startup class loaded is 'Startup'.
/// https://github.com/aspnet/Helios/issues/53 - Environment based startup class loading is not available on Helios. /// https://github.com/aspnet/Helios/issues/53 - Environment based startup class loading is not available on Helios.
/// Alternative ways to specify environment are: /// Alternative ways to specify environment are:
/// 1. Set the environment variable named SET env=NtlmAuthentication /// 1. Set the environment variable named SET KRE_ENV=NtlmAuthentication
/// 2. For selfhost based servers pass in a command line variable named --env with this value. Eg: /// 2. For selfhost based servers pass in a command line variable named --env with this value. Eg:
/// "commands": { /// "commands": {
/// "WebListener": "Microsoft.AspNet.Hosting --server Microsoft.AspNet.Server.WebListener --server.urls http://localhost:5002 --env NtlmAuthentication", /// "WebListener": "Microsoft.AspNet.Hosting --server Microsoft.AspNet.Server.WebListener --server.urls http://localhost:5002 --KRE_ENV NtlmAuthentication",
/// }, /// },
/// </summary> /// </summary>
public class StartupNtlmAuthentication public class StartupNtlmAuthentication
@ -47,6 +47,7 @@ namespace MusicStore
var identity = (ClaimsIdentity)context.User.Identity; var identity = (ClaimsIdentity)context.User.Identity;
#if ASPNET50 #if ASPNET50
//no WindowsIdentity yet on CoreCLR
if (identity.GetUserName() == Environment.UserDomainName + "\\" + Environment.UserName) if (identity.GetUserName() == Environment.UserDomainName + "\\" + Environment.UserName)
{ {
identity.AddClaim(new Claim("ManageStore", "Allowed")); identity.AddClaim(new Claim("ManageStore", "Allowed"));

View File

@ -22,7 +22,7 @@
//This code block necessary only for NTLM authentication //This code block necessary only for NTLM authentication
<ul class="nav navbar-nav navbar-right"> <ul class="nav navbar-nav navbar-right">
<li> <li>
@Html.ActionLink("Hello " + User.Identity.GetUserName() + "!", null, null, routeValues: null, htmlAttributes: new { title = "Manage" }) <p class="nav navbar-text navbar-right">Hello, @User.Identity.GetUserName()!</p>
</li> </li>
</ul> </ul>
} }

View File

@ -25,7 +25,7 @@
"Microsoft.Framework.ConfigurationModel.Json": "1.0.0-*", "Microsoft.Framework.ConfigurationModel.Json": "1.0.0-*",
"Microsoft.Framework.OptionsModel": "1.0.0-*", "Microsoft.Framework.OptionsModel": "1.0.0-*",
"Microsoft.AspNet.SignalR.Server": "3.0.0-*", "Microsoft.AspNet.SignalR.Server": "3.0.0-*",
"Microsoft.AspNet.MemoryCache": "1.0.0-*" "Microsoft.Framework.Cache.Memory": "1.0.0-*"
}, },
"commands": { "commands": {
"WebListener": "Microsoft.AspNet.Hosting --server Microsoft.AspNet.Server.WebListener --server.urls http://localhost:5002", "WebListener": "Microsoft.AspNet.Hosting --server Microsoft.AspNet.Server.WebListener --server.urls http://localhost:5002",