Adding support for flowing compilation errors to Diagnostics middleware

Fixes #872
This commit is contained in:
Pranav K 2014-12-19 16:19:49 -08:00
parent 62b6ab8721
commit b7d44666b8
23 changed files with 398 additions and 95 deletions

15
Mvc.sln
View File

@ -118,6 +118,8 @@ Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "ActionResultsWebSite", "tes
EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "LoggingWebSite", "test\WebSites\LoggingWebSite\LoggingWebSite.kproj", "{0AD78AB5-D67C-49BC-81B1-0C51BFA82B5E}"
EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "ErrorPageMiddlewareWebSite", "test\WebSites\ErrorPageMiddlewareWebSite\ErrorPageMiddlewareWebSite.kproj", "{AD545A5B-2BA5-4314-88AC-FC2ACF2CC718}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -650,6 +652,18 @@ Global
{0AD78AB5-D67C-49BC-81B1-0C51BFA82B5E}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{0AD78AB5-D67C-49BC-81B1-0C51BFA82B5E}.Release|x86.ActiveCfg = Release|Any CPU
{0AD78AB5-D67C-49BC-81B1-0C51BFA82B5E}.Release|x86.Build.0 = Release|Any CPU
{AD545A5B-2BA5-4314-88AC-FC2ACF2CC718}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{AD545A5B-2BA5-4314-88AC-FC2ACF2CC718}.Debug|Any CPU.Build.0 = Debug|Any CPU
{AD545A5B-2BA5-4314-88AC-FC2ACF2CC718}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{AD545A5B-2BA5-4314-88AC-FC2ACF2CC718}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{AD545A5B-2BA5-4314-88AC-FC2ACF2CC718}.Debug|x86.ActiveCfg = Debug|Any CPU
{AD545A5B-2BA5-4314-88AC-FC2ACF2CC718}.Debug|x86.Build.0 = Debug|Any CPU
{AD545A5B-2BA5-4314-88AC-FC2ACF2CC718}.Release|Any CPU.ActiveCfg = Release|Any CPU
{AD545A5B-2BA5-4314-88AC-FC2ACF2CC718}.Release|Any CPU.Build.0 = Release|Any CPU
{AD545A5B-2BA5-4314-88AC-FC2ACF2CC718}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{AD545A5B-2BA5-4314-88AC-FC2ACF2CC718}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{AD545A5B-2BA5-4314-88AC-FC2ACF2CC718}.Release|x86.ActiveCfg = Release|Any CPU
{AD545A5B-2BA5-4314-88AC-FC2ACF2CC718}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -707,5 +721,6 @@ Global
{920F8A0E-6F7D-4BBE-84FF-840B89099BE6} = {16703B76-C9F7-4C75-AE6C-53D92E308E3C}
{0A6BB4C0-48D3-4E7F-952B-B8917345E075} = {16703B76-C9F7-4C75-AE6C-53D92E308E3C}
{0AD78AB5-D67C-49BC-81B1-0C51BFA82B5E} = {16703B76-C9F7-4C75-AE6C-53D92E308E3C}
{AD545A5B-2BA5-4314-88AC-FC2ACF2CC718} = {16703B76-C9F7-4C75-AE6C-53D92E308E3C}
EndGlobalSection
EndGlobal

View File

@ -3,70 +3,28 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.AspNet.Diagnostics;
namespace Microsoft.AspNet.Mvc.Razor
{
/// <summary>
/// An exception thrown when accessing the result of a failed compilation.
/// </summary>
public class CompilationFailedException : Exception
public class CompilationFailedException : Exception, ICompilationException
{
/// <summary>
/// Instantiates a new instance of <see cref="CompilationFailedException"/>.
/// </summary>
/// <param name="filePath">The path of the Razor source file that was compiled.</param>
/// <param name="fileContent">The contents of the Razor source file.</param>
/// <param name="compiledContent">The generated C# content that was compiled.</param>
/// <param name="messages">A sequence of <see cref="CompilationMessage"/> encountered
/// during compilation.</param>
/// <param name="compilationFailure">The <see cref="ICompilationFailure"/> instance containing
/// details of the compilation failure.</param>
public CompilationFailedException(
[NotNull] string filePath,
[NotNull] string fileContent,
[NotNull] string compiledContent,
[NotNull] IEnumerable<CompilationMessage> messages)
: base(FormatMessage(messages))
[NotNull] ICompilationFailure compilationFailure)
: base(Resources.FormatCompilationFailed(compilationFailure.SourceFilePath))
{
FilePath = filePath;
FileContent = fileContent;
CompiledContent = compiledContent;
Messages = messages.ToList();
CompilationFailures = new[] { compilationFailure };
}
/// <summary>
/// Gets the path of the Razor source file that produced the compilation failure.
/// </summary>
public string FilePath { get; private set; }
/// <summary>
/// Gets a sequence of <see cref="CompilationMessage"/> instances encountered during compilation.
/// </summary>
public IEnumerable<CompilationMessage> Messages { get; private set; }
/// <summary>
/// Gets the content of the Razor source file.
/// </summary>
public string FileContent { get; private set; }
/// <summary>
/// Gets the generated C# content that was compiled.
/// </summary>
public string CompiledContent { get; private set; }
/// <inheritdoc />
public override string Message
{
get
{
return Resources.FormatCompilationFailed(FilePath) +
Environment.NewLine +
FormatMessage(Messages);
}
}
private static string FormatMessage(IEnumerable<CompilationMessage> messages)
{
return string.Join(Environment.NewLine, messages);
}
public IEnumerable<ICompilationFailure> CompilationFailures { get; }
}
}

View File

@ -0,0 +1,52 @@
// Copyright (c) Microsoft Open Technologies, Inc. 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;
using Microsoft.AspNet.Diagnostics;
namespace Microsoft.AspNet.Mvc.Razor
{
/// <summary>
/// Default implementation of <see cref="ICompilationFailure"/>.
/// </summary>
public class CompilationFailure : ICompilationFailure
{
/// <summary>Initializes a new instance of <see cref="CompilationFailure"/>.</summary>
/// <param name="filePath">The path of the Razor source file that was compiled.</param>
/// <param name="fileContent">The contents of the Razor source file.</param>
/// <param name="compiledContent">The generated C# content that was compiled.</param>
/// <param name="messages">A sequence of <see cref="ICompilationMessage"/> encountered
/// during compilation.</param>
public CompilationFailure(
[NotNull] string filePath,
[NotNull] string fileContent,
[NotNull] string compiledContent,
[NotNull] IEnumerable<ICompilationMessage> messages)
{
SourceFilePath = filePath;
SourceFileContent = fileContent;
Messages = messages;
CompiledContent = compiledContent;
}
/// <summary>
/// Gets the path of the Razor source file that produced the compilation failure.
/// </summary>
public string SourceFilePath { get; }
/// <summary>
/// Gets the content of the Razor source file.
/// </summary>
public string SourceFileContent { get; }
/// <summary>
/// Gets the generated C# content that was compiled.
/// </summary>
public string CompiledContent { get; }
/// <summary>
/// Gets a sequence of <see cref="ICompilationMessage"/> instances encountered during compilation.
/// </summary>
public IEnumerable<ICompilationMessage> Messages { get; }
}
}

View File

@ -1,26 +1,48 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.AspNet.Diagnostics;
namespace Microsoft.AspNet.Mvc.Razor
{
/// <summary>
/// Represents a message encountered during compilation.
/// </summary>
public class CompilationMessage
public class CompilationMessage : ICompilationMessage
{
/// <summary>
/// Initializes a <see cref="CompilationMessage"/> with the specified message.
/// </summary>
/// <param name="message">A message <see cref="string"/> produced from compilation.</param>
public CompilationMessage(string message)
public CompilationMessage(string message,
int startColumn,
int startLine,
int endColumn,
int endLine)
{
Message = message;
StartColumn = startColumn;
StartLine = startLine;
EndColumn = endColumn;
EndLine = endLine;
}
/// <summary>
/// Gets a message produced from compilation.
/// </summary>
public string Message { get; private set; }
public string Message { get; }
/// <inheritdoc />
public int StartColumn { get; }
/// <inheritdoc />
public int StartLine { get; }
/// <inheritdoc />
public int EndColumn { get; }
/// <inheritdoc />
public int EndLine { get; }
/// <summary>
/// Returns a <see cref="string"/> representation of this instance of <see cref="CompilationMessage"/>.

View File

@ -105,7 +105,8 @@ namespace Microsoft.AspNet.Mvc.Razor
private CompilationFailedException CreateCompilationFailedException()
{
var fileContent = ReadContent(File);
return new CompilationFailedException(FilePath, fileContent, CompiledContent, Messages);
var compilationFailure = new CompilationFailure(FilePath, fileContent, CompiledContent, Messages);
return new CompilationFailedException(compilationFailure);
}
private static string ReadContent(IFileInfo file)

View File

@ -197,7 +197,12 @@ namespace Microsoft.AspNet.Mvc.Razor
private static CompilationMessage GetCompilationMessage(DiagnosticFormatter formatter, Diagnostic diagnostic)
{
return new CompilationMessage(formatter.Format(diagnostic));
var lineSpan = diagnostic.Location.GetMappedLineSpan();
return new CompilationMessage(formatter.Format(diagnostic),
startColumn: lineSpan.StartLinePosition.Character,
startLine: lineSpan.StartLinePosition.Line,
endColumn: lineSpan.EndLinePosition.Character,
endLine: lineSpan.EndLinePosition.Line);
}
private static bool IsError(Diagnostic diagnostic)

View File

@ -0,0 +1,20 @@
// Copyright (c) Microsoft Open Technologies, Inc. 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;
using Microsoft.Framework.Runtime;
namespace Microsoft.AspNet.Diagnostics
{
/// <summary>
/// Specifies the contract for an exception representing compilation failure.
/// </summary>
[AssemblyNeutral]
public interface ICompilationException
{
/// <summary>
/// Gets a sequence of <see cref="ICompilationFailure"/> with compilation failures.
/// </summary>
IEnumerable<ICompilationFailure> CompilationFailures { get; }
}
}

View File

@ -0,0 +1,40 @@
// Copyright (c) Microsoft Open Technologies, Inc. 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;
using Microsoft.Framework.Runtime;
namespace Microsoft.AspNet.Diagnostics
{
/// <summary>
/// Specifies the contract for a file that fails compilation.
/// </summary>
[AssemblyNeutral]
public interface ICompilationFailure
{
/// <summary>
/// Path of the file that produced the compilation exception.
/// </summary>
string SourceFilePath { get; }
/// <summary>
/// Contents of the file.
/// </summary>
string SourceFileContent { get; }
/// <summary>
/// Contents being compiled.
/// </summary>
/// <remarks>
/// For templated files, the <see cref="SourceFileContent"/> represents the original content and
/// <see cref="CompiledContent"/> represents the transformed content. This property can be null if
/// the exception is encountered during transformation.
/// </remarks>
string CompiledContent { get; }
/// <summary>
/// Gets a sequence of <see cref="ICompilationMessage"/> produced as a result of compilation.
/// </summary>
IEnumerable<ICompilationMessage> Messages { get; }
}
}

View File

@ -0,0 +1,40 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.Framework.Runtime;
namespace Microsoft.AspNet.Diagnostics
{
/// <summary>
/// Specifies the contract for diagnostic messages produced as result of compiling an instance
/// of <see cref="ICompilationFailure"/>.
/// </summary>
[AssemblyNeutral]
public interface ICompilationMessage
{
/// <summary>
/// Gets the error message.
/// </summary>
string Message { get; }
/// <summary>
/// Gets the zero-based line index for the start of the compilation error.
/// </summary>
int StartLine { get; }
/// <summary>
/// Gets the zero-based column index for the start of the compilation error.
/// </summary>
int StartColumn { get; }
/// <summary>
/// Gets the zero-based line index for the end of the compilation error.
/// </summary>
int EndLine { get; }
/// <summary>
/// Gets the zero-based column index for the end of the compilation error.
/// </summary>
int EndColumn { get; }
}
}

View File

@ -27,7 +27,7 @@ namespace Microsoft.AspNet.Mvc.Razor
}
/// <summary>
/// Compilation for '{0}' failed:
/// Error compiling page at '{0}'.
/// </summary>
internal static string CompilationFailed
{
@ -35,7 +35,7 @@ namespace Microsoft.AspNet.Mvc.Razor
}
/// <summary>
/// Compilation for '{0}' failed:
/// Error compiling page at '{0}'.
/// </summary>
internal static string FormatCompilationFailed(object p0)
{

View File

@ -33,7 +33,13 @@ namespace Microsoft.AspNet.Mvc.Razor
if (!results.Success)
{
var messages = results.ParserErrors.Select(e => new CompilationMessage(e.Message));
var messages = results.ParserErrors
.Select(parseError =>
new CompilationMessage(parseError.Message,
parseError.Location.CharacterIndex,
parseError.Location.LineIndex,
parseError.Location.CharacterIndex + parseError.Length,
parseError.Location.LineIndex));
return CompilationResult.Failed(file.FileInfo, results.GeneratedCode, messages);
}

View File

@ -1,17 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
@ -26,36 +26,36 @@
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
@ -121,7 +121,7 @@
<value>Value cannot be null or empty.</value>
</data>
<data name="CompilationFailed" xml:space="preserve">
<value>Compilation for '{0}' failed:</value>
<value>Error compiling page at '{0}'.</value>
</data>
<data name="FlushPointCannotBeInvoked" xml:space="preserve">
<value>'{0}' cannot be invoked when a Layout page is set to be executed.</value>

View File

@ -0,0 +1,49 @@
// Copyright (c) Microsoft Open Technologies, Inc. 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.Net;
using System.Net.Http.Headers;
using System.Reflection;
using System.Threading.Tasks;
using ErrorPageMiddlewareWebSite;
using Microsoft.AspNet.Builder;
using Microsoft.AspNet.TestHost;
using Xunit;
namespace Microsoft.AspNet.Mvc.FunctionalTests
{
/// <summary>
/// Functional test to verify the error reporting of Razor compilation by diagnostic middleware.
/// </summary>
public class ErrorPageTests
{
private readonly IServiceProvider _provider = TestHelper.CreateServices(nameof(ErrorPageMiddlewareWebSite));
private readonly Action<IApplicationBuilder> _app = new Startup().Configure;
private readonly Assembly _resourcesAssembly = typeof(ErrorPageTests).GetTypeInfo().Assembly;
[Theory]
[InlineData("CompilationFailure", "/Views/ErrorPageMiddleware/CompilationFailure.cshtml(2,16): error CS0029:" +
" Cannot implicitly convert type &#39;int&#39; to &#39;string&#39;")]
[InlineData("ParserError", "The code block is missing a closing &quot;}&quot; character. Make sure you " +
"have a matching &quot;}&quot; character for all the &quot;{&quot; characters " +
"within this block, and that none of the &quot;}&quot; characters are being " +
"interpreted as markup.")]
public async Task CompilationFailuresAreListedByErrorPageMiddleware(string action, string expected)
{
// Arrange
var server = TestServer.Create(_provider, _app);
var client = server.CreateClient();
var expectedMediaType = MediaTypeHeaderValue.Parse("text/html");
// Act
var response = await client.GetAsync("http://localhost/" + action);
// Assert
Assert.Equal(HttpStatusCode.InternalServerError, response.StatusCode);
Assert.Equal(expectedMediaType, response.Content.Headers.ContentType);
var content = await response.Content.ReadAsStringAsync();
Assert.Contains(expected, content);
}
}
}

View File

@ -12,6 +12,7 @@
"BasicWebSite": "1.0.0",
"CompositeViewEngineWebSite": "1.0.0",
"ConnegWebSite": "1.0.0",
"ErrorPageMiddlewareWebSite": "1.0.0",
"FilesWebSite": "1.0.0",
"FiltersWebSite": "1.0.0",
"FormatterWebSite": "1.0.0",
@ -49,6 +50,6 @@
"AutofacWebSite": "1.0.0"
}
},
"aspnetcore50": {}
"aspnetcore50": { }
}
}

View File

@ -15,10 +15,7 @@ namespace Microsoft.AspNet.Mvc.Razor.Test
public void FailedResult_ThrowsWhenAccessingCompiledType()
{
// Arrange
var expected =
@"Compilation for 'myfile' failed:
hello
world";
var expected = @"Error compiling page at 'myfile'.";
var originalContent = "Original file content";
var fileInfo = new Mock<IFileInfo>();
fileInfo.SetupGet(f => f.PhysicalPath)
@ -28,8 +25,8 @@ world";
.Returns(new MemoryStream(contentBytes));
var messages = new[]
{
new CompilationMessage("hello"),
new CompilationMessage("world")
new CompilationMessage("hello", 1, 1, 2, 2),
new CompilationMessage("world", 3, 3, 4, 3)
};
var result = CompilationResult.Failed(fileInfo.Object,
"<h1>hello world</h1>",
@ -38,7 +35,9 @@ world";
// Act and Assert
var ex = Assert.Throws<CompilationFailedException>(() => result.CompiledType);
Assert.Equal(expected, ex.Message);
Assert.Equal(originalContent, ex.FileContent);
var compilationFailure = Assert.Single(ex.CompilationFailures);
Assert.Equal(originalContent, compilationFailure.SourceFileContent);
Assert.Equal(messages, compilationFailure.Messages);
}
}
}

View File

@ -73,7 +73,9 @@ namespace Microsoft.AspNet.Mvc.Razor.Test
// Assert
var ex = Assert.Throws<CompilationFailedException>(() => result.CompiledType);
Assert.Equal("some message", Assert.Single(ex.Messages).Message);
var failure = Assert.Single(ex.CompilationFailures);
var message = Assert.Single(failure.Messages);
Assert.Equal("some message", message.Message);
host.Verify();
}

View File

@ -0,0 +1,22 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.AspNet.Mvc;
namespace ErrorPageMiddlewareWebSite
{
public class ErrorPageMiddlewareController : Controller
{
[HttpGet("/CompilationFailure")]
public IActionResult CompilationFailure()
{
return View();
}
[HttpGet("/ParserError")]
public IActionResult ParserError()
{
return View();
}
}
}

View File

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="__ToolsVersion__" 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)\AspNet\Microsoft.Web.AspNet.Props" Condition="'$(VSToolsPath)' != ''" />
<PropertyGroup Label="Globals">
<ProjectGuid>ad545a5b-2ba5-4314-88ac-fc2acf2cc718</ProjectGuid>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x86'" Label="Configuration">
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x86'" Label="Configuration">
</PropertyGroup>
<PropertyGroup>
<SchemaVersion>2.0</SchemaVersion>
<DevelopmentServerPort>6288</DevelopmentServerPort>
</PropertyGroup>
<Import Project="$(VSToolsPath)\AspNet\Microsoft.Web.AspNet.targets" Condition="'$(VSToolsPath)' != ''" />
</Project>

View File

@ -0,0 +1,24 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.AspNet.Builder;
using Microsoft.Framework.DependencyInjection;
namespace ErrorPageMiddlewareWebSite
{
public class Startup
{
public void Configure(IApplicationBuilder app)
{
var configuration = app.GetTestConfiguration();
app.UseServices(services =>
{
services.AddMvc(configuration);
});
app.UseErrorPage();
app.UseMvc();
}
}
}

View File

@ -0,0 +1,3 @@
@{
string x = 10;
}

View File

@ -0,0 +1,4 @@
@{
<span>
}
</span>

View File

@ -0,0 +1,20 @@
{
"commands": {
"web": "Microsoft.AspNet.Hosting server=Microsoft.AspNet.Server.WebListener server.urls=http://localhost:5001",
"kestrel": "Microsoft.AspNet.Hosting --server Kestrel --server.urls http://localhost:5000"
},
"dependencies": {
"Kestrel": "1.0.0-*",
"Microsoft.AspNet.Diagnostics": "1.0.0-*",
"Microsoft.AspNet.Mvc": "6.0.0-*",
"Microsoft.AspNet.Mvc.TestConfiguration": "1.0.0",
"Microsoft.AspNet.Server.IIS": "1.0.0-*",
"Microsoft.AspNet.Server.WebListener": "1.0.0-*",
"Microsoft.AspNet.StaticFiles": "1.0.0-*"
},
"frameworks": {
"aspnet50": { },
"aspnetcore50": { }
},
"webroot": "wwwroot"
}