Rough outline of middleware, sample, and test projects.
This commit is contained in:
parent
ed9f238eda
commit
a14bb69d6a
|
|
@ -23,4 +23,5 @@ nuget.exe
|
|||
*DS_Store
|
||||
*.ncrunchsolution
|
||||
*.*sdf
|
||||
*.ipch
|
||||
*.ipch
|
||||
project.lock.json
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 14
|
||||
VisualStudioVersion = 14.0.22823.1
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.AspNet.ResponseCaching", "src\Microsoft.AspNet.ResponseCaching\Microsoft.AspNet.ResponseCaching.xproj", "{D1031270-DBD3-4F02-A3DC-3E7DADE8EBE6}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{367AABAF-E03C-4491-A9A7-BDDE8903D1B4}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "samples", "samples", "{C51DF5BD-B53D-4795-BC01-A9AB066BF286}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{89A50974-E9D4-4F87-ACF2-6A6005E64931}"
|
||||
EndProject
|
||||
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "ResponseCachingSample", "samples\ResponseCachingSample\ResponseCachingSample.xproj", "{1139BDEE-FA15-474D-8855-0AB91F23CF26}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{F787A492-C2FF-4569-A663-F8F24B900657}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
global.json = global.json
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.AspNet.ResponseCaching.Tests", "test\Microsoft.AspNet.ResponseCaching.Tests\Microsoft.AspNet.ResponseCaching.Tests.xproj", "{151B2027-3936-44B9-A4A0-E1E5902125AB}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{D1031270-DBD3-4F02-A3DC-3E7DADE8EBE6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{D1031270-DBD3-4F02-A3DC-3E7DADE8EBE6}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{D1031270-DBD3-4F02-A3DC-3E7DADE8EBE6}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{D1031270-DBD3-4F02-A3DC-3E7DADE8EBE6}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{1139BDEE-FA15-474D-8855-0AB91F23CF26}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{1139BDEE-FA15-474D-8855-0AB91F23CF26}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{1139BDEE-FA15-474D-8855-0AB91F23CF26}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{1139BDEE-FA15-474D-8855-0AB91F23CF26}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{151B2027-3936-44B9-A4A0-E1E5902125AB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{151B2027-3936-44B9-A4A0-E1E5902125AB}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{151B2027-3936-44B9-A4A0-E1E5902125AB}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{151B2027-3936-44B9-A4A0-E1E5902125AB}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(NestedProjects) = preSolution
|
||||
{D1031270-DBD3-4F02-A3DC-3E7DADE8EBE6} = {367AABAF-E03C-4491-A9A7-BDDE8903D1B4}
|
||||
{1139BDEE-FA15-474D-8855-0AB91F23CF26} = {C51DF5BD-B53D-4795-BC01-A9AB066BF286}
|
||||
{151B2027-3936-44B9-A4A0-E1E5902125AB} = {89A50974-E9D4-4F87-ACF2-6A6005E64931}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"projects": ["src"]
|
||||
}
|
||||
|
|
@ -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>1139bdee-fa15-474d-8855-0ab91f23cf26</ProjectGuid>
|
||||
<RootNamespace>ResponseCachingSample</RootNamespace>
|
||||
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">..\..\artifacts\obj\$(MSBuildProjectName)</BaseIntermediateOutputPath>
|
||||
<OutputPath Condition="'$(OutputPath)'=='' ">..\..\artifacts\bin\$(MSBuildProjectName)\</OutputPath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<DevelopmentServerPort>2931</DevelopmentServerPort>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.targets" Condition="'$(VSToolsPath)' != ''" />
|
||||
</Project>
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using Microsoft.AspNet.Builder;
|
||||
using Microsoft.AspNet.Http;
|
||||
using Microsoft.Framework.DependencyInjection;
|
||||
using Microsoft.Net.Http.Headers;
|
||||
|
||||
namespace ResponseCachingSample
|
||||
{
|
||||
public class Startup
|
||||
{
|
||||
public void ConfigureServices(IServiceCollection services)
|
||||
{
|
||||
services.AddCaching();
|
||||
}
|
||||
|
||||
public void Configure(IApplicationBuilder app)
|
||||
{
|
||||
app.UseResponseCaching();
|
||||
app.Run(async (context) =>
|
||||
{
|
||||
context.Response.GetTypedHeaders().CacheControl = new CacheControlHeaderValue()
|
||||
{
|
||||
Public = true,
|
||||
MaxAge = TimeSpan.FromSeconds(10)
|
||||
};
|
||||
await context.Response.WriteAsync("Hello World! " + DateTime.UtcNow);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
{
|
||||
"webroot": "wwwroot",
|
||||
"version": "1.0.0-*",
|
||||
|
||||
"dependencies": {
|
||||
"Microsoft.AspNet.ResponseCaching": "1.0.0-*",
|
||||
"Microsoft.AspNet.Server.IIS": "1.0.0-*",
|
||||
"Microsoft.AspNet.Server.WebListener": "1.0.0-*",
|
||||
"Microsoft.Framework.Caching.Memory": "1.0.0-*"
|
||||
},
|
||||
|
||||
"commands": {
|
||||
"web": "Microsoft.AspNet.Hosting --server Microsoft.AspNet.Server.WebListener --server.urls http://localhost:5000"
|
||||
},
|
||||
|
||||
"frameworks": {
|
||||
"dnx451": { },
|
||||
"dnxcore50": { }
|
||||
},
|
||||
|
||||
"publishExclude": [
|
||||
"node_modules",
|
||||
"bower_components",
|
||||
"**.xproj",
|
||||
"**.user",
|
||||
"**.vspscc"
|
||||
],
|
||||
"exclude": [
|
||||
"wwwroot",
|
||||
"node_modules",
|
||||
"bower_components"
|
||||
]
|
||||
}
|
||||
|
|
@ -0,0 +1,143 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNet.Http;
|
||||
using Microsoft.Framework.Caching.Memory;
|
||||
|
||||
namespace Microsoft.AspNet.ResponseCaching
|
||||
{
|
||||
internal class CachingContext
|
||||
{
|
||||
private string _cacheKey;
|
||||
|
||||
public CachingContext(HttpContext httpContext, IMemoryCache cache)
|
||||
{
|
||||
HttpContext = httpContext;
|
||||
Cache = cache;
|
||||
}
|
||||
|
||||
private HttpContext HttpContext { get; }
|
||||
|
||||
private IMemoryCache Cache { get; }
|
||||
|
||||
private Stream OriginalResponseStream { get; set; }
|
||||
|
||||
private MemoryStream Buffer { get; set; }
|
||||
|
||||
internal bool ResponseStarted { get; set; }
|
||||
|
||||
private bool CacheResponse { get; set; }
|
||||
|
||||
internal bool CheckRequestAllowsCaching()
|
||||
{
|
||||
// Verify the method
|
||||
// TODO: What other methods should be supported?
|
||||
if (!string.Equals("GET", HttpContext.Request.Method, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Verify the request headers do not opt-out of caching
|
||||
// TODO:
|
||||
return true;
|
||||
}
|
||||
|
||||
// Only QueryString is treated as case sensitive
|
||||
// GET;HTTP://MYDOMAIN.COM:80/PATHBASE/PATH?QueryString
|
||||
private string CreateCacheKey()
|
||||
{
|
||||
var request = HttpContext.Request;
|
||||
return request.Method.ToUpperInvariant()
|
||||
+ ";"
|
||||
+ request.Scheme.ToUpperInvariant()
|
||||
+ "://"
|
||||
+ request.Host.Value.ToUpperInvariant()
|
||||
+ request.PathBase.Value.ToUpperInvariant()
|
||||
+ request.Path.Value.ToUpperInvariant()
|
||||
+ request.QueryString;
|
||||
}
|
||||
|
||||
internal async Task<bool> TryServeFromCacheAsync()
|
||||
{
|
||||
_cacheKey = CreateCacheKey();
|
||||
ResponseCacheEntry cacheEntry;
|
||||
if (Cache.TryGetValue(_cacheKey, out cacheEntry))
|
||||
{
|
||||
// TODO: Compare cached request headers
|
||||
|
||||
// TODO: Evaluate Vary-By and select the most appropriate response
|
||||
|
||||
// TODO: Content negotiation if there are multiple cached response formats?
|
||||
|
||||
// TODO: Verify content freshness, or else re-validate the data?
|
||||
|
||||
var response = HttpContext.Response;
|
||||
// Copy the cached status code and response headers
|
||||
response.StatusCode = cacheEntry.StatusCode;
|
||||
foreach (var pair in cacheEntry.Headers)
|
||||
{
|
||||
response.Headers.SetValues(pair.Key, pair.Value);
|
||||
}
|
||||
|
||||
// TODO: Update cache headers (Age)
|
||||
response.Headers["Served_From_Cache"] = DateTime.Now.ToString();
|
||||
|
||||
// Copy the cached response body
|
||||
var body = cacheEntry.Body;
|
||||
if (body.Length > 0)
|
||||
{
|
||||
await response.Body.WriteAsync(body, 0, body.Length);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
internal void HookResponseStream()
|
||||
{
|
||||
// TODO: Use a wrapper stream to listen for writes (e.g. the start of the response),
|
||||
// check the headers, and verify if we should cache the response.
|
||||
// Then we should stream data out to the client at the same time as we buffer for the cache.
|
||||
// For now we'll just buffer everything in memory before checking the response headers.
|
||||
// TODO: Consider caching large responses on disk and serving them from there.
|
||||
OriginalResponseStream = HttpContext.Response.Body;
|
||||
Buffer = new MemoryStream();
|
||||
HttpContext.Response.Body = Buffer;
|
||||
}
|
||||
|
||||
internal bool OnResponseStarting()
|
||||
{
|
||||
// Evaluate the response headers, see if we should buffer and cache
|
||||
CacheResponse = true; // TODO:
|
||||
return CacheResponse;
|
||||
}
|
||||
|
||||
internal void FinalizeCaching()
|
||||
{
|
||||
if (CacheResponse)
|
||||
{
|
||||
// Store the buffer to cache
|
||||
var cacheEntry = new ResponseCacheEntry();
|
||||
cacheEntry.StatusCode = HttpContext.Response.StatusCode;
|
||||
cacheEntry.Headers = HttpContext.Response.Headers.ToList();
|
||||
cacheEntry.Body = Buffer.ToArray();
|
||||
Cache.Set(_cacheKey, cacheEntry); // TODO: Timeouts
|
||||
}
|
||||
|
||||
// TODO: TEMP, flush the buffer to the client
|
||||
Buffer.Seek(0, SeekOrigin.Begin);
|
||||
Buffer.CopyTo(OriginalResponseStream);
|
||||
}
|
||||
|
||||
internal void UnhookResponseStream()
|
||||
{
|
||||
// Unhook the response stream.
|
||||
HttpContext.Response.Body = OriginalResponseStream;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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>d1031270-dbd3-4f02-a3dc-3e7dade8ebe6</ProjectGuid>
|
||||
<RootNamespace>Microsoft.AspNet.ResponseCaching</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>
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
[assembly: InternalsVisibleTo("Microsoft.AspNet.ResponseCaching.Tests")]
|
||||
[assembly: AssemblyMetadata("Serviceable", "True")]
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Microsoft.AspNet.ResponseCaching
|
||||
{
|
||||
internal class ResponseCacheEntry
|
||||
{
|
||||
public int StatusCode { get; set; }
|
||||
internal IEnumerable<KeyValuePair<string, string[]>> Headers { get; set; }
|
||||
internal byte[] Body { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using Microsoft.AspNet.ResponseCaching;
|
||||
|
||||
namespace Microsoft.AspNet.Builder
|
||||
{
|
||||
public static class ResponseCachingExtensions
|
||||
{
|
||||
public static IApplicationBuilder UseResponseCaching(this IApplicationBuilder app)
|
||||
{
|
||||
return app.UseMiddleware<ResponseCachingMiddleware>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNet.Builder;
|
||||
using Microsoft.AspNet.Http;
|
||||
using Microsoft.Framework.Caching.Memory;
|
||||
|
||||
namespace Microsoft.AspNet.ResponseCaching
|
||||
{
|
||||
// http://tools.ietf.org/html/rfc7234
|
||||
public class ResponseCachingMiddleware
|
||||
{
|
||||
private readonly RequestDelegate _next;
|
||||
private readonly IMemoryCache _cache;
|
||||
|
||||
public ResponseCachingMiddleware(RequestDelegate next, IMemoryCache cache)
|
||||
{
|
||||
_next = next;
|
||||
_cache = cache;
|
||||
}
|
||||
|
||||
public async Task Invoke(HttpContext context)
|
||||
{
|
||||
var cachingContext = new CachingContext(context, _cache);
|
||||
// Should we attempt any caching logic?
|
||||
if (cachingContext.CheckRequestAllowsCaching())
|
||||
{
|
||||
// Can this request be served from cache?
|
||||
if (await cachingContext.TryServeFromCacheAsync())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Hook up to listen to the response stream
|
||||
cachingContext.HookResponseStream();
|
||||
|
||||
try
|
||||
{
|
||||
await _next(context);
|
||||
|
||||
// If there was no response body, check the response headers now. We can cache things like redirects.
|
||||
if (!cachingContext.ResponseStarted)
|
||||
{
|
||||
cachingContext.OnResponseStarting();
|
||||
}
|
||||
// Finalize the cache entry
|
||||
cachingContext.FinalizeCaching();
|
||||
}
|
||||
finally
|
||||
{
|
||||
cachingContext.UnhookResponseStream();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
await _next(context);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
{
|
||||
"version": "1.0.0-*",
|
||||
"description": "Middleare that automatically caches HTTP responses on the server.",
|
||||
"dependencies": {
|
||||
"Microsoft.AspNet.Http.Abstractions": "1.0.0-*",
|
||||
"Microsoft.Framework.Caching.Abstractions": "1.0.0-*"
|
||||
},
|
||||
"frameworks" : {
|
||||
"dnx451": { },
|
||||
"dnxcore50" : {
|
||||
"dependencies": {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using Microsoft.AspNet.Http.Internal;
|
||||
using Microsoft.Framework.Caching.Memory;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNet.ResponseCaching
|
||||
{
|
||||
public class CachingContextTests
|
||||
{
|
||||
[Fact]
|
||||
public void CheckRequestAllowsCaching_Method_GET_Allowed()
|
||||
{
|
||||
var httpContext = new DefaultHttpContext();
|
||||
httpContext.Request.Method = "GET";
|
||||
var context = new CachingContext(httpContext, new MemoryCache(new MemoryCacheOptions()));
|
||||
|
||||
Assert.True(context.CheckRequestAllowsCaching());
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("POST")]
|
||||
public void CheckRequestAllowsCaching_Method_Unsafe_NotAllowed(string method)
|
||||
{
|
||||
var httpContext = new DefaultHttpContext();
|
||||
httpContext.Request.Method = method;
|
||||
var context = new CachingContext(httpContext, new MemoryCache(new MemoryCacheOptions()));
|
||||
|
||||
Assert.False(context.CheckRequestAllowsCaching());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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>151b2027-3936-44b9-a4a0-e1e5902125ab</ProjectGuid>
|
||||
<RootNamespace>Microsoft.AspNet.ResponseCaching.Tests</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>
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
{
|
||||
"dependencies": {
|
||||
"Microsoft.AspNet.ResponseCaching": "1.0.0-*",
|
||||
"xunit.runner.aspnet": "2.0.0-aspnet-*",
|
||||
"Microsoft.AspNet.Http": "1.0.0-beta5-11528",
|
||||
"Microsoft.Framework.Caching.Memory": "1.0.0-beta5-11395"
|
||||
},
|
||||
"commands": {
|
||||
"test": "xunit.runner.aspnet"
|
||||
},
|
||||
"frameworks": {
|
||||
"dnx451": { },
|
||||
"dnxcore50": { }
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue