This commit is contained in:
Tommy Parnell
2015-11-15 09:26:30 -05:00
parent 932995d3b8
commit b3b92d3d59
29 changed files with 25816 additions and 2 deletions

2
.gitignore vendored
View File

@@ -24,7 +24,7 @@ bld/
# Visual Studo 2015 cache/options directory
.vs/
wwwroot/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*

View File

@@ -0,0 +1,47 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14
VisualStudioVersion = 14.0.23107.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{C054D790-3899-4B62-97FA-0053C7437FA5}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{A424946D-7019-4CA7-A1F0-05B616CD3A49}"
ProjectSection(SolutionItems) = preProject
global.json = global.json
NuGet.Config = NuGet.Config
EndProjectSection
EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "AzureTableStorageCache", "src\AzureTableStorageCache\AzureTableStorageCache.xproj", "{4220710A-3EC2-4449-BC86-B75F0A58D003}"
EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "AzureTableStorageCache.Sample", "src\AzureTableStorageCache.Sample\AzureTableStorageCache.Sample.xproj", "{902E5295-C074-45B3-ADD2-7DCF289C24A8}"
EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "AzureTableStorageCacheSample", "src\AzureTableStorageCacheSample\AzureTableStorageCacheSample.xproj", "{D2C11E75-BAC6-4619-930E-CCA94474365E}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{4220710A-3EC2-4449-BC86-B75F0A58D003}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4220710A-3EC2-4449-BC86-B75F0A58D003}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4220710A-3EC2-4449-BC86-B75F0A58D003}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4220710A-3EC2-4449-BC86-B75F0A58D003}.Release|Any CPU.Build.0 = Release|Any CPU
{902E5295-C074-45B3-ADD2-7DCF289C24A8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{902E5295-C074-45B3-ADD2-7DCF289C24A8}.Debug|Any CPU.Build.0 = Debug|Any CPU
{902E5295-C074-45B3-ADD2-7DCF289C24A8}.Release|Any CPU.ActiveCfg = Release|Any CPU
{902E5295-C074-45B3-ADD2-7DCF289C24A8}.Release|Any CPU.Build.0 = Release|Any CPU
{D2C11E75-BAC6-4619-930E-CCA94474365E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D2C11E75-BAC6-4619-930E-CCA94474365E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D2C11E75-BAC6-4619-930E-CCA94474365E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D2C11E75-BAC6-4619-930E-CCA94474365E}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{4220710A-3EC2-4449-BC86-B75F0A58D003} = {C054D790-3899-4B62-97FA-0053C7437FA5}
{902E5295-C074-45B3-ADD2-7DCF289C24A8} = {C054D790-3899-4B62-97FA-0053C7437FA5}
{D2C11E75-BAC6-4619-930E-CCA94474365E} = {C054D790-3899-4B62-97FA-0053C7437FA5}
EndGlobalSection
EndGlobal

8
NuGet.Config Normal file
View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
<!--To inherit the global NuGet package sources remove the <clear/> line below -->
<clear />
<add key="api.nuget.org" value="https://api.nuget.org/v3/index.json" />
</packageSources>
</configuration>

View File

@@ -1,2 +1,4 @@
# AspNetCache-AzureTableStorage
Use azure table storage for AspNet 5 Distributed Cache (save money on redis in azure)
Use azure table storage for AspNet 5 Distributed Cache.
Azure Table Storage is a very cheap, super fast key value store, and its much cheaper than the redis cluster in azure. This is not a true replacement for redis, and redis should be used if people have money, but this is designed to get people a very cheap cache in azure.

6
global.json Normal file
View File

@@ -0,0 +1,6 @@
{
"projects": [ "src", "test" ],
"sdk": {
"version": "1.0.0-beta8"
}
}

View File

@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion>
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
</PropertyGroup>
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.Props" Condition="'$(VSToolsPath)' != ''" />
<PropertyGroup Label="Globals">
<ProjectGuid>4220710a-3ec2-4449-bc86-b75f0a58d003</ProjectGuid>
<RootNamespace>AzureTableStorageCache</RootNamespace>
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">..\..\artifacts\obj\$(MSBuildProjectName)</BaseIntermediateOutputPath>
<OutputPath Condition="'$(OutputPath)'=='' ">..\..\artifacts\bin\$(MSBuildProjectName)\</OutputPath>
</PropertyGroup>
<PropertyGroup>
<SchemaVersion>2.0</SchemaVersion>
</PropertyGroup>
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.targets" Condition="'$(VSToolsPath)' != ''" />
</Project>

View File

@@ -0,0 +1,80 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Framework.Caching.Distributed;
using Microsoft.Framework.DependencyInjection;
using AzureTableStorageCache;
namespace Microsoft.AspNet.Builder
{
public static class AzureTableStorageCacheExtensions
{
/// <summary>
/// Add azure table storage cache as an IDistributedCache to the service container
/// </summary>
/// <param name="services"></param>
/// <param name="connectionString">The connection string of your account (can be found in the preview portal)</param>
/// <param name="tableName">the name of the table you wish to use. If the table doesn't exist it will be created.</param>
/// <param name="partitionKey">the partition key you would like to use</param>
/// <returns></returns>
public static IServiceCollection AddAzureTableStorageCache(this IServiceCollection services, string connectionString, string tableName, string partitionKey)
{
if(string.IsNullOrWhiteSpace(connectionString))
{
throw new ArgumentNullException("connectionString must not be null");
}
if(services == null)
{
throw new ArgumentNullException(nameof(services));
}
//services.AddSingleton<Azure>
services.Add(ServiceDescriptor.Singleton<IDistributedCache, AzureTableStorageCacheHandler>(a=> new AzureTableStorageCacheHandler(connectionString, tableName, partitionKey)));
return services;
}
/// <summary>
/// Add azure table storage cache as an IDistributedCache to the service container
/// </summary>
/// <param name="services"></param>
/// <param name="accountName">the name of your storage account</param>
/// <param name="accountKey">the key of your storage account</param>
/// <param name="tableName">the name of the table you wish to use. If the table doesn't exist it will be created.</param>
/// <param name="partitionKey">the partition key you would like to use</param>
/// <returns></returns>
public static IServiceCollection AddAzureTableStorageCache(this IServiceCollection services, string accountName, string accountKey, string tableName, string partitionKey)
{
if(string.IsNullOrWhiteSpace(accountName))
{
throw new ArgumentNullException("accountName must not be null");
}
if(string.IsNullOrWhiteSpace(accountKey))
{
throw new ArgumentNullException("accountKey must not be null");
}
if(services == null)
{
throw new ArgumentNullException(nameof(services));
}
//services.AddSingleton<Azure>
services.Add(ServiceDescriptor.Singleton<IDistributedCache, AzureTableStorageCacheHandler>(a =>
new AzureTableStorageCacheHandler(accountName, accountKey, tableName, partitionKey)));
return services;
}
private static void checkTableData(string tableName, string partitionkey)
{
if(string.IsNullOrWhiteSpace(tableName))
{
throw new ArgumentNullException("tableName must not be null");
}
if(string.IsNullOrWhiteSpace(partitionkey))
{
throw new ArgumentNullException("partitionkey must not be null");
}
}
}
}

View File

@@ -0,0 +1,182 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using AzureTableStorageCache.Model;
using Microsoft.Framework.Caching.Distributed;
using Microsoft.Framework.Internal;
using Microsoft.WindowsAzure.Storage;
using Microsoft.WindowsAzure.Storage.Auth;
using Microsoft.WindowsAzure.Storage.Table;
namespace AzureTableStorageCache
{
// This project can output the Class library as a NuGet Package.
// To enable this option, right-click on the project and select the Properties menu item. In the Build tab select "Produce outputs on build".
public class AzureTableStorageCacheHandler : IDistributedCache
{
private readonly string partitionKey;
private readonly string accountKey;
private readonly string accountName;
private readonly string connectionString;
private CloudTableClient client;
private CloudTable azuretable;
private AzureTableStorageCacheHandler(string tableName, string partitionKey)
{
if(string.IsNullOrWhiteSpace(tableName))
{
throw new ArgumentNullException("tableName cannot be null or empty");
}
if(string.IsNullOrWhiteSpace(partitionKey))
{
throw new ArgumentNullException("partitionKey cannot be null or empty");
}
this.tableName = tableName;
this.partitionKey = partitionKey;
Connect();
}
public AzureTableStorageCacheHandler(string accountName, string accountKey, string tableName, string partitionKey)
:this(tableName, partitionKey)
{
if(string.IsNullOrWhiteSpace(accountName))
{
throw new ArgumentNullException("accountName cannot be null or empty");
}
if(string.IsNullOrWhiteSpace(accountKey))
{
throw new ArgumentNullException("accountKey cannot be null or empty");
}
this.accountName = accountName;
this.accountKey = accountKey;
}
private readonly string tableName;
public AzureTableStorageCacheHandler(string connectionString, string tableName, string partitionKey)
:this(tableName, partitionKey)
{
if(string.IsNullOrWhiteSpace(connectionString))
{
throw new ArgumentNullException("Connection string cannot be null or empty");
}
this.connectionString = connectionString;
}
public void Connect()
{
ConnectAsync().Wait();
}
public async Task ConnectAsync()
{
if(client == null)
{
if(string.IsNullOrWhiteSpace(connectionString))
{
var creds = new StorageCredentials(accountKey, accountKey);
client = new CloudStorageAccount(creds, true).CreateCloudTableClient();
}
else
{
client = CloudStorageAccount.Parse(connectionString).CreateCloudTableClient();
}
}
if(azuretable == null)
{
this.azuretable = client.GetTableReference(this.tableName);
await this.azuretable.CreateIfNotExistsAsync();
}
}
public byte[] Get(string key)
{
return GetAsync(key).Result;
}
public async Task<byte[]> GetAsync(string key)
{
var op = TableOperation.Retrieve(partitionKey, key);
var result = await azuretable.ExecuteAsync(op);
return (result?.Result as CachedItem)?.Data;
}
public void Refresh(string key)
{
this.RefreshAsync(key).Wait();
}
public async Task RefreshAsync(string key)
{
var op = TableOperation.Retrieve(partitionKey, key);
var result = await azuretable.ExecuteAsync(op);
var data = result?.Result as CachedItem;
if(data != null)
{
if(ShouldDelete(data))
{
await RemoveAsync(key);
return;
}
}
}
private bool ShouldDelete(CachedItem data)
{
var currentTime = DateTimeOffset.UtcNow;
if(data.AbsolutExperiation != null && data.AbsolutExperiation.Value <= currentTime)
{
return true;
}
if(data.SlidingExperiation.HasValue && data.LastAccessTime.HasValue && data.LastAccessTime <= currentTime.Add(data.SlidingExperiation.Value))
{
return true;
}
return false;
}
public void Remove(string key)
{
this.RemoveAsync(key).Wait();
}
public Task RemoveAsync(string key)
{
var op = TableOperation.Delete(new CachedItem(partitionKey, key));
return azuretable.ExecuteAsync(op);
}
public void Set(string key, byte[] value, DistributedCacheEntryOptions options)
{
this.SetAsync(key, value, options).Wait();
}
public Task SetAsync(string key, byte[] value, DistributedCacheEntryOptions options)
{
DateTimeOffset? absoluteExpiration = null;
var currentTime = DateTimeOffset.UtcNow;
if(options.AbsoluteExpirationRelativeToNow.HasValue)
{
absoluteExpiration = currentTime.Add(options.AbsoluteExpirationRelativeToNow.Value);
}
else if(options.AbsoluteExpiration.HasValue)
{
if(options.AbsoluteExpiration.Value <= currentTime)
{
throw new ArgumentOutOfRangeException(
nameof(options.AbsoluteExpiration),
options.AbsoluteExpiration.Value,
"The absolute expiration value must be in the future.");
}
absoluteExpiration = options.AbsoluteExpiration;
}
var item = new CachedItem(partitionKey, key, value) { LastAccessTime = currentTime };
var op = TableOperation.InsertOrReplace(item);
return this.azuretable.ExecuteAsync(op);
}
}
}

View File

@@ -0,0 +1,23 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.WindowsAzure.Storage.Table;
namespace AzureTableStorageCache.Model
{
public class CachedItem : TableEntity
{
public CachedItem() { }
public CachedItem(string partitionKey, string rowKey, byte[] data = null)
:base(partitionKey, rowKey)
{
this.Data = data;
}
public byte[] Data { get; set; }
public TimeSpan? SlidingExperiation { get; set; }
public DateTimeOffset? AbsolutExperiation { get; set; }
public DateTimeOffset? LastAccessTime { get; set; }
}
}

View File

@@ -0,0 +1,23 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("AzureTableStorageCache")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("AzureTableStorageCache")]
[assembly: AssemblyCopyright("Copyright © 2015")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("4220710a-3ec2-4449-bc86-b75f0a58d003")]

View File

@@ -0,0 +1,25 @@
{
"version": "1.0.0-*",
"description": "AzureTableStorageCache Class Library",
"authors": [ "parne" ],
"tags": [ "" ],
"projectUrl": "",
"licenseUrl": "",
"dependencies": {
"WindowsAzure.Storage": "6.1.1-preview",
"Microsoft.Framework.Caching.Abstractions": "1.0.0-beta8",
"Microsoft.Framework.DependencyInjection": "1.0.0-beta8"
},
"frameworks": {
"net45": { },
"dnxcore50": {
"dependencies": {
"Microsoft.CSharp": "4.0.1-beta-23409",
"System.Collections": "4.0.11-beta-23409",
"System.Linq": "4.0.1-beta-23409",
"System.Runtime": "4.0.21-beta-23409",
"System.Threading": "4.0.11-beta-23409"
}
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,3 @@
{
"directory": "wwwroot/lib"
}

View File

@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion>
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
</PropertyGroup>
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.Props" Condition="'$(VSToolsPath)' != ''" />
<PropertyGroup Label="Globals">
<ProjectGuid>d2c11e75-bac6-4619-930e-cca94474365e</ProjectGuid>
<RootNamespace>AzureTableStorageCacheSample</RootNamespace>
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">..\..\artifacts\obj\$(MSBuildProjectName)</BaseIntermediateOutputPath>
<OutputPath Condition="'$(OutputPath)'=='' ">..\..\artifacts\bin\$(MSBuildProjectName)\</OutputPath>
</PropertyGroup>
<PropertyGroup>
<SchemaVersion>2.0</SchemaVersion>
<DevelopmentServerPort>50593</DevelopmentServerPort>
</PropertyGroup>
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.targets" Condition="'$(VSToolsPath)' != ''" />
</Project>

View File

@@ -0,0 +1,51 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNet.Mvc;
using Microsoft.Framework.Caching.Distributed;
namespace AzureTableStorageCache.Sample.Controllers
{
public class HomeController : Controller
{
private readonly IDistributedCache cacheMechanism;
public HomeController(IDistributedCache cacheMechanism)
{
this.cacheMechanism = cacheMechanism;
}
public async Task<IActionResult> Index()
{
var data = await cacheMechanism.GetAsync("awesomeRecord");
var result = string.Empty;
if(data != null)
{
result = Encoding.UTF32.GetString(data);
}
return View(result);
}
public async Task<IActionResult> AddCache()
{
cacheMechanism.SetAsync("awesomeRecord", Encoding.UTF32.GetBytes("Im Awesome"));
ViewData["Message"] = "Your application description page.";
return RedirectToAction("Index");
}
public IActionResult Contact()
{
ViewData["Message"] = "Your contact page.";
return View();
}
public IActionResult Error()
{
return View("~/Views/Shared/Error.cshtml");
}
}
}

View File

@@ -0,0 +1,203 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Welcome to ASP.NET 5</title>
<style>
html {
background: #f1f1f1;
height: 100%;
}
body {
background: #fff;
color: #505050;
font: 14px 'Segoe UI', tahoma, arial, helvetica, sans-serif;
margin: 1%;
min-height: 95.5%;
border: 1px solid silver;
position: relative;
}
#header {
padding: 0;
}
#header h1 {
font-size: 44px;
font-weight: normal;
margin: 0;
padding: 10px 30px 10px 30px;
}
#header span {
margin: 0;
padding: 0 30px;
display: block;
}
#header p {
font-size: 20px;
color: #fff;
background: #007acc;
padding: 0 30px;
line-height: 50px;
margin-top: 25px;
}
#header p a {
color: #fff;
text-decoration: underline;
font-weight: bold;
padding-right: 35px;
background: no-repeat right bottom url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABcAAAAWCAMAAAAcqPc3AAAANlBMVEUAAAAAeswfitI9mthXp91us+KCvuaTx+mjz+2x1u+83PLH4vTR5/ba7Pjj8Pns9fv1+v3////wy3dWAAAAAXRSTlMAQObYZgAAAHxJREFUeNp9kVcSwCAIRMHUYoH7XzaxOxJ9P8oyQ1uIqNPwh3s2aLmIM2YtqrLcQIeQEylhuCeUOlhgve5yoBCfWmlnlgkN4H8ykbpaE7gR03AbUHiwoOxUH9Xp+ubd41p1HF3mBPrfC87BHeTdaB3ceeKL9HGpcvX9zu6+DdMWT9KQPvYAAAAASUVORK5CYII=);
}
#main {
padding: 5px 30px;
clear: both;
}
.section {
width: 21.7%;
float: left;
margin: 0 0 0 4%;
}
.section h2 {
font-size: 13px;
text-transform: uppercase;
margin: 0;
border-bottom: 1px solid silver;
padding-bottom: 12px;
margin-bottom: 8px;
}
.section.first {
margin-left: 0;
}
.section.first h2 {
font-size: 24px;
text-transform: none;
margin-bottom: 25px;
border: none;
}
.section.first li {
border-top: 1px solid silver;
padding: 8px 0;
}
.section.last {
margin-right: 0;
}
ul {
list-style: none;
padding: 0;
margin: 0;
line-height: 20px;
}
li {
padding: 4px 0;
}
a {
color: #267cb2;
text-decoration: none;
}
a:hover {
text-decoration: underline;
}
#footer {
clear: both;
padding-top: 50px;
}
#footer p {
position: absolute;
bottom: 10px;
}
</style>
</head>
<body>
<div id="header">
<h1>Welcome to ASP.NET 5 Preview</h1>
<span>
We've made some big updates in this release, so its <b>important</b> that you spend
a few minutes to learn whats new.
<br /><br />
ASP.NET 5 has been rearchitected to make it <b>lean</b> and <b>composable</b>. It's fully
<b>open source</b> and available on <a href="http://go.microsoft.com/fwlink/?LinkID=517854">GitHub</a>.
<br />
Your new project automatically takes advantage of modern client-side utilities
like <a href="http://go.microsoft.com/fwlink/?LinkId=518004">Bower</a> and <a href="http://go.microsoft.com/fwlink/?LinkId=518005">npm</a>
(to add client-side libraries) and <a href="http://go.microsoft.com/fwlink/?LinkId=518007">Gulp</a> (for client-side build and automation tasks).
<br /><br />
We hope you enjoy the new capabilities in ASP.NET 5 and Visual Studio 2015.
<br />
The ASP.NET Team
</span>
<p>You've created a new ASP.NET 5 project. <a href="http://go.microsoft.com/fwlink/?LinkId=518016">Learn what's new</a></p>
</div>
<div id="main">
<div class="section first">
<h2>This application consists of:</h2>
<ul>
<li>Sample pages using ASP.NET MVC 6</li>
<li><a href="http://go.microsoft.com/fwlink/?LinkId=518007">Gulp</a> and <a href="http://go.microsoft.com/fwlink/?LinkId=518004">Bower</a> for managing client-side resources</li>
<li>Theming using <a href="http://go.microsoft.com/fwlink/?LinkID=398939">Bootstrap</a></li>
</ul>
</div>
<div class="section">
<h2>New concepts</h2>
<ul>
<li><a href="http://go.microsoft.com/fwlink/?LinkId=518008">The 'wwwroot' explained</a></li>
<li><a href="http://go.microsoft.com/fwlink/?LinkId=518012">Configuration in ASP.NET 5</a></li>
<li><a href="http://go.microsoft.com/fwlink/?LinkId=518013">Dependency Injection</a></li>
<li><a href="http://go.microsoft.com/fwlink/?LinkId=518014">Razor TagHelpers</a></li>
<li><a href="http://go.microsoft.com/fwlink/?LinkID=517849">Manage client tasks using Gulp</a></li>
<li><a href="http://go.microsoft.com/fwlink/?LinkID=517850">Develop on different platforms</a></li>
</ul>
</div>
<div class="section">
<h2>Customize app</h2>
<ul>
<li><a href="http://go.microsoft.com/fwlink/?LinkID=398600">Add Controllers and Views</a></li>
<li><a href="http://go.microsoft.com/fwlink/?LinkID=398602">Add Data using EntityFramework</a></li>
<li><a href="http://go.microsoft.com/fwlink/?LinkID=398603">Add Authentication using Identity</a></li>
<li><a href="http://go.microsoft.com/fwlink/?LinkID=398606">Add real time support using SignalR</a></li>
<li><a href="http://go.microsoft.com/fwlink/?LinkID=398604">Add Class library</a></li>
<li><a href="http://go.microsoft.com/fwlink/?LinkId=518009">Add Web APIs with MVC 6</a></li>
<li><a href="http://go.microsoft.com/fwlink/?LinkID=517848">Add client packages using Bower</a></li>
</ul>
</div>
<div class="section last">
<h2>Deploy</h2>
<ul>
<li><a href="http://go.microsoft.com/fwlink/?LinkID=517851">Run your app locally</a></li>
<li><a href="http://go.microsoft.com/fwlink/?LinkID=517852">Run your app on ASP.NET Core 5</a></li>
<li><a href="http://go.microsoft.com/fwlink/?LinkID=517853">Run commands in your project.json</a></li>
<li><a href="http://go.microsoft.com/fwlink/?LinkID=398609">Publish to Microsoft Azure Web Sites</a></li>
<li><a href="http://go.microsoft.com/fwlink/?LinkId=518019">Publish to the file system</a></li>
</ul>
</div>
<div id="footer">
<p>We would love to hear your <a href="http://go.microsoft.com/fwlink/?LinkId=518015">feedback</a></p>
</div>
</div>
</body>
</html>

View File

@@ -0,0 +1,23 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("AzureTableStorageCacheSample")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("AzureTableStorageCacheSample")]
[assembly: AssemblyCopyright("Copyright © 2015")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("d2c11e75-bac6-4619-930e-cca94474365e")]

View File

@@ -0,0 +1,80 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNet.Builder;
using Microsoft.AspNet.Hosting;
using Microsoft.Dnx.Runtime;
using Microsoft.Framework.Configuration;
using Microsoft.Framework.DependencyInjection;
using Microsoft.Framework.Logging;
namespace AzureTableStorageCacheSample
{
public class Startup
{
public Startup(IHostingEnvironment env, IApplicationEnvironment appEnv)
{
// Setup configuration sources.
var builder = new ConfigurationBuilder()
.SetBasePath(appEnv.ApplicationBasePath)
.AddJsonFile("appsettings.json")
.AddEnvironmentVariables();
Configuration = builder.Build();
}
public IConfigurationRoot Configuration { get; set; }
// This method gets called by the runtime.
public void ConfigureServices(IServiceCollection services)
{
services.AddAzureTableStorageCache("!!!CONNECTIONSTRINGHERE!!!", "awesomeTable", "cachedDataKey");
// Add MVC services to the services container.
services.AddMvc();
// Uncomment the following line to add Web API services which makes it easier to port Web API 2 controllers.
// You will also need to add the Microsoft.AspNet.Mvc.WebApiCompatShim package to the 'dependencies' section of project.json.
// services.AddWebApiConventions();
}
// Configure is called after ConfigureServices is called.
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
loggerFactory.MinimumLevel = LogLevel.Information;
loggerFactory.AddConsole();
loggerFactory.AddDebug();
// Configure the HTTP request pipeline.
// Add the following to the request pipeline only in development environment.
if (env.IsDevelopment())
{
app.UseBrowserLink();
app.UseDeveloperExceptionPage();
}
else
{
// Add Error handling middleware which catches all application specific errors and
// send the request to the following path or controller action.
app.UseExceptionHandler("/Home/Error");
}
// Add the platform handler to the request pipeline.
app.UseIISPlatformHandler();
// Add static files to the request pipeline.
app.UseStaticFiles();
// Add MVC to the request pipeline.
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
// Uncomment the following line to add a route for porting Web API 2 controllers.
// routes.MapWebApiRoute("DefaultApi", "api/{controller}/{id?}");
});
}
}
}

View File

@@ -0,0 +1,17 @@
@model string
@{
ViewData["Title"] = "Home Page";
}
<div class="jumbotron">
@if(string.IsNullOrWhiteSpace(Model))
{
<span>No data found</span>
<a asp-action="AddCache" class="btn btn-primary">Add Item To Cache</a>
}
else
{
<span>Cached Data: @Model</span>
}
</div>

View File

@@ -0,0 +1,6 @@
@{
ViewData["Title"] = "Error";
}
<h1 class="text-danger">Error.</h1>
<h2 class="text-danger">An error occurred while processing your request.</h2>

View File

@@ -0,0 +1,78 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>@ViewData["Title"] - AzureTableStorageCacheSample</title>
<environment names="Development">
<link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.css" />
<link rel="stylesheet" href="~/lib/bootstrap-touch-carousel/dist/css/bootstrap-touch-carousel.css" />
<link rel="stylesheet" href="~/css/site.css" />
</environment>
<environment names="Staging,Production">
<link rel="stylesheet" href="https://ajax.aspnetcdn.com/ajax/bootstrap/3.0.0/css/bootstrap.min.css"
asp-fallback-href="~/lib/bootstrap/dist/css/bootstrap.min.css"
asp-fallback-test-class="hidden" asp-fallback-test-property="visibility" asp-fallback-test-value="hidden" />
<link rel="stylesheet" href="https://ajax.aspnetcdn.com/ajax/bootstrap-touch-carousel/0.8.0/css/bootstrap-touch-carousel.css"
asp-fallback-href="~/lib/bootstrap-touch-carousel/css/bootstrap-touch-carousel.css"
asp-fallback-test-class="carousel-caption" asp-fallback-test-property="display" asp-fallback-test-value="none" />
<link rel="stylesheet" href="~/css/site.css" asp-append-version="true" />
</environment>
</head>
<body>
<div class="navbar navbar-inverse navbar-fixed-top">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a asp-controller="Home" asp-action="Index" class="navbar-brand">AzureTableStorageCacheSample</a>
</div>
<div class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li><a asp-controller="Home" asp-action="Index">Home</a></li>
</ul>
</div>
</div>
</div>
<div class="container body-content">
@RenderBody()
<hr />
<footer>
<p>&copy; 2015 - AzureTableStorageCacheSample</p>
</footer>
</div>
<environment names="Development">
<script src="~/lib/jquery/dist/jquery.js"></script>
<script src="~/lib/bootstrap/dist/js/bootstrap.js"></script>
<script src="~/lib/hammer.js/hammer.js"></script>
<script src="~/lib/bootstrap-touch-carousel/dist/js/bootstrap-touch-carousel.js"></script>
<script src="~/js/site.js" asp-append-version="true"></script>
</environment>
<environment names="Staging,Production">
<script src="https://ajax.aspnetcdn.com/ajax/jquery/jquery-2.1.4.min.js"
asp-fallback-src="~/lib/jquery/dist/jquery.min.js"
asp-fallback-test="window.jQuery">
</script>
<script src="https://ajax.aspnetcdn.com/ajax/bootstrap/3.0.0/bootstrap.min.js"
asp-fallback-src="~/lib/bootstrap/dist/js/bootstrap.min.js"
asp-fallback-test="window.jQuery && window.jQuery.fn && window.jQuery.fn.modal">
</script>
<script src="https://ajax.aspnetcdn.com/ajax/hammer.js/2.0.4/hammer.min.js"
asp-fallback-src="~/lib/hammer.js/hammer.js"
asp-fallback-test="window.Hammer">
</script>
<script src="https://ajax.aspnetcdn.com/ajax/bootstrap-touch-carousel/0.8.0/js/bootstrap-touch-carousel.js"
asp-fallback-src="~/lib/bootstrap-touch-carousel/dist/js/bootstrap-touch-carousel.js"
asp-fallback-test="window.Hammer && window.Hammer.Instance">
</script>
<script src="~/js/site.js" asp-append-version="true"></script>
</environment>
@RenderSection("scripts", required: false)
</body>
</html>

View File

@@ -0,0 +1,2 @@
@using AzureTableStorageCacheSample
@addTagHelper "*, Microsoft.AspNet.Mvc.TagHelpers"

View File

@@ -0,0 +1,3 @@
@{
Layout = "_Layout";
}

View File

@@ -0,0 +1 @@
{}

View File

@@ -0,0 +1,12 @@
{
"name": "ASP.NET",
"private": true,
"dependencies": {
"bootstrap": "3.0.0",
"bootstrap-touch-carousel": "0.8.0",
"hammer.js": "2.0.4",
"jquery": "2.1.4",
"jquery-validation": "1.11.1",
"jquery-validation-unobtrusive": "3.2.2"
}
}

View File

@@ -0,0 +1,45 @@
/// <binding Clean='clean' />
var gulp = require("gulp"),
rimraf = require("rimraf"),
concat = require("gulp-concat"),
cssmin = require("gulp-cssmin"),
uglify = require("gulp-uglify"),
project = require("./project.json");
var paths = {
webroot: "./" + project.webroot + "/"
};
paths.js = paths.webroot + "js/**/*.js";
paths.minJs = paths.webroot + "js/**/*.min.js";
paths.css = paths.webroot + "css/**/*.css";
paths.minCss = paths.webroot + "css/**/*.min.css";
paths.concatJsDest = paths.webroot + "js/site.min.js";
paths.concatCssDest = paths.webroot + "css/site.min.css";
gulp.task("clean:js", function (cb) {
rimraf(paths.concatJsDest, cb);
});
gulp.task("clean:css", function (cb) {
rimraf(paths.concatCssDest, cb);
});
gulp.task("clean", ["clean:js", "clean:css"]);
gulp.task("min:js", function () {
gulp.src([paths.js, "!" + paths.minJs], { base: "." })
.pipe(concat(paths.concatJsDest))
.pipe(uglify())
.pipe(gulp.dest("."));
});
gulp.task("min:css", function () {
gulp.src([paths.css, "!" + paths.minCss])
.pipe(concat(paths.concatCssDest))
.pipe(cssmin())
.pipe(gulp.dest("."));
});
gulp.task("min", ["min:js", "min:css"]);

View File

@@ -0,0 +1,11 @@
{
"name": "ASP.NET",
"version": "0.0.0",
"devDependencies": {
"gulp": "3.8.11",
"gulp-concat": "2.5.2",
"gulp-cssmin": "0.1.7",
"gulp-uglify": "1.2.0",
"rimraf": "2.2.8"
}
}

View File

@@ -0,0 +1,41 @@
{
"webroot": "wwwroot",
"version": "1.0.0-*",
"dependencies": {
"Microsoft.AspNet.Diagnostics": "1.0.0-beta8",
"Microsoft.AspNet.IISPlatformHandler": "1.0.0-beta8",
"Microsoft.AspNet.Mvc": "6.0.0-beta8",
"Microsoft.AspNet.Mvc.TagHelpers": "6.0.0-beta8",
"Microsoft.AspNet.Server.Kestrel": "1.0.0-beta8",
"Microsoft.AspNet.StaticFiles": "1.0.0-beta8",
"Microsoft.AspNet.Tooling.Razor": "1.0.0-beta8",
"Microsoft.Framework.Configuration.Json": "1.0.0-beta8",
"Microsoft.Framework.Logging": "1.0.0-beta8",
"Microsoft.Framework.Logging.Console": "1.0.0-beta8",
"Microsoft.Framework.Logging.Debug": "1.0.0-beta8",
"Microsoft.VisualStudio.Web.BrowserLink.Loader": "14.0.0-beta8",
"AzureTableStorageCache": ""
},
"commands": {
"web": "Microsoft.AspNet.Server.Kestrel"
},
"frameworks": {
"dnx451": { },
"dnxcore50": { }
},
"exclude": [
"wwwroot",
"node_modules"
],
"publishExclude": [
"**.user",
"**.vspscc"
],
"scripts": {
"prepublish": [ "npm install", "bower install", "gulp clean", "gulp min" ]
}
}

File diff suppressed because it is too large Load Diff