Refine service reference warnings and errors

- #12792
- client:
  - add error if OpenAPI file does not exist
  - separate unsupported TFM case from targets being called when disabled
- server:
  - generalize multi-targeting handling in Microsoft.Extensions.ApiDescription.Server
    - add `$(_OpenApiGenerateDocumentsTFM)`, the TFM used when invoking inner build
    - default `$(OpenApiGenerateDocuments)` to 'true' only when a supported TFM exists
  - add separate error for non-existent cache file in `OpenApiGetDocuments` target
  - add error in `GetDocumentInsider` if no documents are found
    - make `<Warning />` in the targets file an `<Error />`
    - add more text to existing `ServiceNotFound` error
- both:
  - write errors to `stderr`
  - clean up top-level output for `Exception`s
    - stop writing the `Message` twice

* Correct "Open API" mentions; should be "OpenAPI"
  - change package tags and comments

* Add service reference projects to MvcNoDeps.slnf

nits:
- add "service reference" tag in Microsoft.Extensions.ApiDescription.* packages
- add "document generation" tag in Microsoft.Extensions.ApiDescription.Server package
- `.Trim()` TFM properties because `<TargetFrameworks>;netcoreapp3.0;;</TargetFrameworks>` is allowed
- don't use bold black for verbose messages
- reorder MSBuild property settings for readability
This commit is contained in:
Doug Bunting 2019-08-14 08:36:21 -07:00
parent aafb0813e6
commit c0d5248fb4
13 changed files with 151 additions and 122 deletions

View File

@ -7,7 +7,7 @@
<IncludeBuildOutput>false</IncludeBuildOutput> <IncludeBuildOutput>false</IncludeBuildOutput>
<NuspecFile>$(MSBuildProjectName).nuspec</NuspecFile> <NuspecFile>$(MSBuildProjectName).nuspec</NuspecFile>
<PackageId>$(MSBuildProjectName)</PackageId> <PackageId>$(MSBuildProjectName)</PackageId>
<PackageTags>Build Tasks;MSBuild;Swagger;Open API;code generation; Web API client</PackageTags> <PackageTags>Build Tasks;MSBuild;Swagger;OpenAPI;code generation;Web API client;service reference</PackageTags>
<IsShippingPackage>true</IsShippingPackage> <IsShippingPackage>true</IsShippingPackage>
<TargetFrameworks>netstandard2.0;net461</TargetFrameworks> <TargetFrameworks>netstandard2.0;net461</TargetFrameworks>
<DevelopmentDependency>true</DevelopmentDependency> <DevelopmentDependency>true</DevelopmentDependency>

View File

@ -39,7 +39,7 @@
<!-- <!--
If 'true' (the default), build projects referenced in @(OpenApiProjectReference) items before retrieving that If 'true' (the default), build projects referenced in @(OpenApiProjectReference) items before retrieving that
project's Open API documents list (or generating code). If 'false', ensure the referenced projects build before project's OpenAPI documents list (or generating code). If 'false', ensure the referenced projects build before
this one in the solution or through other means. IDEs may be confused about the project dependency graph in this this one in the solution or through other means. IDEs may be confused about the project dependency graph in this
case. case.
--> -->
@ -47,7 +47,7 @@
Condition="'$(OpenApiBuildReferencedProjects)' == ''">true</OpenApiBuildReferencedProjects> Condition="'$(OpenApiBuildReferencedProjects)' == ''">true</OpenApiBuildReferencedProjects>
<!-- <!--
Default folder to place code generated from Open API documents. Value is interpreted relative to the project Default folder to place code generated from OpenAPI documents. Value is interpreted relative to the project
folder, unless already an absolute path. Part of the default %(OutputPath) metadata of @(OpenApiReference) and folder, unless already an absolute path. Part of the default %(OutputPath) metadata of @(OpenApiReference) and
@(OpenApiProjectReference) items. @(OpenApiProjectReference) items.
--> -->

View File

@ -87,6 +87,8 @@
Condition="$(OpenApiGenerateCodeAtDesignTime) OR ('$(DesignTimeBuild)' != 'true' AND '$(BuildingProject)' == 'true')" Condition="$(OpenApiGenerateCodeAtDesignTime) OR ('$(DesignTimeBuild)' != 'true' AND '$(BuildingProject)' == 'true')"
Inputs="@(OpenApiReference)" Inputs="@(OpenApiReference)"
Outputs="%(OutputPath)"> Outputs="%(OutputPath)">
<Error Condition="!Exists('%(OpenApiReference.FullPath)')" Text="Input OpenAPI file %(Identity) does not exist." />
<MSBuild Projects="$(MSBuildProjectFullPath)" <MSBuild Projects="$(MSBuildProjectFullPath)"
BuildInParallel="$(BuildInParallel)" BuildInParallel="$(BuildInParallel)"
Properties="GeneratorTargetPath=%(OpenApiReference.OutputPath);GeneratorTarget=Generate%(CodeGenerator);GeneratorMetadata=%(SerializedMetadata)" Properties="GeneratorTargetPath=%(OpenApiReference.OutputPath);GeneratorTarget=Generate%(CodeGenerator);GeneratorMetadata=%(SerializedMetadata)"

View File

@ -10,7 +10,7 @@
<HasReferenceAssembly>false</HasReferenceAssembly> <HasReferenceAssembly>false</HasReferenceAssembly>
<NuspecFile>$(MSBuildProjectName).nuspec</NuspecFile> <NuspecFile>$(MSBuildProjectName).nuspec</NuspecFile>
<PackageId>$(MSBuildProjectName)</PackageId> <PackageId>$(MSBuildProjectName)</PackageId>
<PackageTags>MSBuild;Swagger;Open API;code generation;Web API</PackageTags> <PackageTags>MSBuild;Swagger;OpenAPI;code generation;Web API;service reference;document generation</PackageTags>
<IsShippingPackage>true</IsShippingPackage> <IsShippingPackage>true</IsShippingPackage>
<DevelopmentDependency>true</DevelopmentDependency> <DevelopmentDependency>true</DevelopmentDependency>

View File

@ -5,13 +5,13 @@
--> -->
<PropertyGroup> <PropertyGroup>
<!-- <!--
Options added to the Open API document generation tool ('dotnet-getdocument') command line. Available options Options added to the OpenAPI document generation tool ('dotnet-getdocument') command line. Available options
control console output: 'no-color', 'prefix-output' and 'verbose'. All require a double-dash prefix. control console output: 'no-color', 'prefix-output' and 'verbose'. All require a double-dash prefix.
--> -->
<OpenApiGenerateDocumentsOptions Condition=" '$(OpenApiGenerateDocumentsOptions)' == '' " /> <OpenApiGenerateDocumentsOptions Condition=" '$(OpenApiGenerateDocumentsOptions)' == '' " />
<!-- <!--
If 'true' (the default when targeting .NET Framework or .NET Core 2.1 and later), enable generation of Open API If 'true' (the default when targeting .NET Framework or .NET Core 2.1 and later), enable generation of OpenAPI
documents. Otherwise, this feature is completely disabled. This controls whether the 'OpenApiGenerateDocuments' documents. Otherwise, this feature is completely disabled. This controls whether the 'OpenApiGenerateDocuments'
project capability is visible, enables / disables the 'GenerateOpenApiDocuments' target and provides the project capability is visible, enables / disables the 'GenerateOpenApiDocuments' target and provides the
$(OpenApiGenerateDocumentsOnBuild) default. $(OpenApiGenerateDocumentsOnBuild) default.
@ -19,13 +19,13 @@
<OpenApiGenerateDocuments Condition=" '$(OpenApiGenerateDocuments)' == '' " /> <OpenApiGenerateDocuments Condition=" '$(OpenApiGenerateDocuments)' == '' " />
<!-- <!--
If 'true' (the default if $(OpenApiGenerateDocuments) is 'true'), will generate Open API documents after every If 'true' (the default if $(OpenApiGenerateDocuments) is 'true'), will generate OpenAPI documents after every
build. Set to 'false' when targets are invoked from the command line or tied to another target. build. Set to 'false' when targets are invoked from the command line or tied to another target.
--> -->
<OpenApiGenerateDocumentsOnBuild Condition=" '$(OpenApiGenerateDocumentsOnBuild)' == '' " /> <OpenApiGenerateDocumentsOnBuild Condition=" '$(OpenApiGenerateDocumentsOnBuild)' == '' " />
<!-- <!--
Where to place Open API documents generated from the application. Value is interpreted relative to the project Where to place OpenAPI documents generated from the application. Value is interpreted relative to the project
folder, unless already an absolute path. folder, unless already an absolute path.
--> -->
<OpenApiDocumentsDirectory <OpenApiDocumentsDirectory

View File

@ -1,14 +1,15 @@
<?xml version="1.0" encoding="utf-8" standalone="no"?> <?xml version="1.0" encoding="utf-8" standalone="no"?>
<Project> <Project>
<PropertyGroup Condition=" '$(OpenApiGenerateDocuments)' == '' "> <PropertyGroup Condition=" '$(OpenApiGenerateDocuments)' == '' ">
<OpenApiGenerateDocuments>true</OpenApiGenerateDocuments>
<OpenApiGenerateDocuments <OpenApiGenerateDocuments
Condition=" '$(TargetFrameworkIdentifier)' == '.NETCoreApp' AND '$(TargetFrameworkVersion.TrimStart(&quot;vV&quot;))' &lt; '2.1' ">false</OpenApiGenerateDocuments> Condition=" '$(TargetFrameworkIdentifier)' == '.NETCoreApp' AND '$(TargetFrameworkVersion.TrimStart(&quot;vV&quot;))' &lt; '2.1' " />
<OpenApiGenerateDocuments Condition=" '$(OpenApiGenerateDocuments)' == '' ">true</OpenApiGenerateDocuments> </PropertyGroup>
<PropertyGroup Condition=" '$(OpenApiGenerateDocumentsOnBuild)' == '' ">
<OpenApiGenerateDocumentsOnBuild>$(OpenApiGenerateDocuments)</OpenApiGenerateDocumentsOnBuild>
</PropertyGroup> </PropertyGroup>
<PropertyGroup> <PropertyGroup>
<_OpenApiDocumentsCache>$(BaseIntermediateOutputPath)$(MSBuildProjectName).OpenApiFiles.cache</_OpenApiDocumentsCache> <_OpenApiDocumentsCache>$(BaseIntermediateOutputPath)$(MSBuildProjectName).OpenApiFiles.cache</_OpenApiDocumentsCache>
<OpenApiGenerateDocumentsOnBuild
Condition=" '$(OpenApiGenerateDocumentsOnBuild)' == '' ">$(OpenApiGenerateDocuments)</OpenApiGenerateDocumentsOnBuild>
</PropertyGroup> </PropertyGroup>
<ItemGroup Condition=" '$(OpenApiGenerateDocuments)' == 'true' "> <ItemGroup Condition=" '$(OpenApiGenerateDocuments)' == 'true' ">
@ -16,23 +17,34 @@
</ItemGroup> </ItemGroup>
<Target Name="OpenApiGetDocuments" Returns="@(_OpenApiProjectDocuments)"> <Target Name="OpenApiGetDocuments" Returns="@(_OpenApiProjectDocuments)">
<Error Text="OpenAPI document generation is disabled. Add '&lt;OpenApiGenerateDocuments>true&lt;/OpenApiGenerateDocuments>' to the project." <!-- E.g. a client project has @(OpenApiProjectReference) item for project that does not support doc generation. -->
Condition=" '$(OpenApiGenerateDocuments)' != 'true' " /> <Error Condition=" '$(OpenApiGenerateDocuments)' != 'true' "
Text="OpenAPI document generation is disabled. Add '&lt;OpenApiGenerateDocuments>true&lt;/OpenApiGenerateDocuments>' to the project." />
<!-- E.g. project set $(OpenApiGenerateDocuments) to 'true' but TFM is not supported. -->
<Error
Condition=" '$(TargetFrameworkIdentifier)' == '.NETCoreApp' AND '$(TargetFrameworkVersion.TrimStart(&quot;vV&quot;))' &lt; '2.1' "
Text="OpenAPI document generation is not supported when targeting netcoreapp2.0 or earlier. Disable the feature or move to a later target framework." />
<!-- E.g. project set $(OpenApiGenerateDocumentsOnBuild) to 'false' but did not invoke GenerateOpenApiDocuments. -->
<Error Condition=" !Exists('$(_OpenApiDocumentsCache)' )"
Text="$(_OpenApiDocumentsCache) file does not exist. Add '&lt;OpenApiGenerateDocumentsOnBuild>true&lt;/OpenApiGenerateDocumentsOnBuild>' to the project or call the GenerateOpenApiDocuments target." />
<ReadLinesFromFile File="$(_OpenApiDocumentsCache)"> <ReadLinesFromFile File="$(_OpenApiDocumentsCache)">
<Output TaskParameter="Lines" ItemName="_OpenApiProjectDocuments" /> <Output TaskParameter="Lines" ItemName="_OpenApiProjectDocuments" />
</ReadLinesFromFile> </ReadLinesFromFile>
<Warning Text="Application does not have any registered documents. Update its 'Startup' class to register a document." <!-- Fallback error in case something slips through the insider's error checking. -->
Condition=" '@(_OpenApiProjectDocuments)' == '' " /> <Error Condition=" '@(_OpenApiProjectDocuments)' == '' "
Text="Application does not have any registered documents. Update its 'Startup' class to register a document." />
</Target> </Target>
<Target Name="GenerateOpenApiDocuments" <Target Name="GenerateOpenApiDocuments" Inputs="$(TargetPath)" Outputs="$(_OpenApiDocumentsCache)">
Condition=" '$(OpenApiGenerateDocuments)' == 'true' " <!-- E.g. project sets $(OpenApiGenerateDocumentsOnBuild) to 'true' but $(OpenApiGenerateDocuments) is 'false'. -->
Inputs="$(TargetPath)" <Error Condition=" '$(OpenApiGenerateDocuments)' != 'true' "
Outputs="$(_OpenApiDocumentsCache)"> Text="OpenAPI document generation is disabled. Add '&lt;OpenApiGenerateDocuments>true&lt;/OpenApiGenerateDocuments>' to the project." />
<Error Text="OpenAPI document generation is not supported when targeting netcoreapp2.0 or earlier. Disable the feature or move to a later target framework." <!-- E.g. project sets $(OpenApiGenerateDocuments) to 'true' but TFM is not supported. -->
Condition=" '$(TargetFrameworkIdentifier)' == '.NETCoreApp' AND '$(TargetFrameworkVersion.TrimStart(&quot;vV&quot;))' &lt; '2.1' " /> <Error
Condition=" '$(TargetFrameworkIdentifier)' == '.NETCoreApp' AND '$(TargetFrameworkVersion.TrimStart(&quot;vV&quot;))' &lt; '2.1' "
Text="OpenAPI document generation is not supported when targeting netcoreapp2.0 or earlier. Disable the feature or move to a later target framework." />
<PropertyGroup> <PropertyGroup>
<_Command>dotnet "$(MSBuildThisFileDirectory)/../tools/dotnet-getdocument.dll" --assembly "$(TargetPath)"</_Command> <_Command>dotnet "$(MSBuildThisFileDirectory)/../tools/dotnet-getdocument.dll" --assembly "$(TargetPath)"</_Command>
@ -47,7 +59,7 @@
<Message Importance="high" Text="%0AGenerateOpenApiDocuments:" /> <Message Importance="high" Text="%0AGenerateOpenApiDocuments:" />
<Message Importance="high" Text=" $(_Command)" /> <Message Importance="high" Text=" $(_Command)" />
<Exec Command="$(_Command)" /> <Exec Command="$(_Command)" LogStandardErrorAsError="true" />
</Target> </Target>
<!-- Unless this is an inner build or default timing is disabled, tie document retrieval into the build. --> <!-- Unless this is an inner build or default timing is disabled, tie document retrieval into the build. -->

View File

@ -1,9 +1,25 @@
<?xml version="1.0" encoding="utf-8" standalone="no"?> <?xml version="1.0" encoding="utf-8" standalone="no"?>
<Project> <Project>
<ItemGroup>
<_OpenApiGenerateDocumentsTFMs Remove="@(_OpenApiGenerateDocumentsTFMs)" />
<_OpenApiGenerateDocumentsTFMs Include="$(TargetFrameworks)" Exclude="netcoreapp1.0;netcoreapp1.1;netcoreapp2.0" />
</ItemGroup>
<PropertyGroup> <PropertyGroup>
<OpenApiGenerateDocuments Condition=" '$(OpenApiGenerateDocuments)' == '' ">true</OpenApiGenerateDocuments> <!-- Default value may lead to an inner build error if $(OpenApiGenerateDocuments) is explicitly set to 'true'. -->
<_OpenApiGenerateDocumentsTFM>$(TargetFrameworks.Trim(';').Split(';')[0])</_OpenApiGenerateDocumentsTFM>
<!-- Prefer first TFM of those the tool supports. -->
<_Temporary>$(@(_OpenApiGenerateDocumentsTFMs).Trim(';'))</_Temporary>
<_OpenApiGenerateDocumentsTFM
Condition=" '$(_Temporary)' != '' ">$(_Temporary.Split(';')[0])</_OpenApiGenerateDocumentsTFM>
<OpenApiGenerateDocuments
Condition=" '$(OpenApiGenerateDocuments)' == '' AND '$(_Temporary)' != '' ">true</OpenApiGenerateDocuments>
<OpenApiGenerateDocumentsOnBuild <OpenApiGenerateDocumentsOnBuild
Condition=" '$(OpenApiGenerateDocumentsOnBuild)' == '' ">$(OpenApiGenerateDocuments)</OpenApiGenerateDocumentsOnBuild> Condition=" '$(OpenApiGenerateDocumentsOnBuild)' == '' ">$(OpenApiGenerateDocuments)</OpenApiGenerateDocumentsOnBuild>
<_Temporary />
</PropertyGroup> </PropertyGroup>
<ItemGroup Condition=" '$(OpenApiGenerateDocuments)' == 'true' "> <ItemGroup Condition=" '$(OpenApiGenerateDocuments)' == 'true' ">
@ -13,7 +29,7 @@
<Target Name="GenerateOpenApiDocuments"> <Target Name="GenerateOpenApiDocuments">
<MSBuild Projects="$(MSBuildProjectFile)" <MSBuild Projects="$(MSBuildProjectFile)"
Targets="GenerateOpenApiDocuments" Targets="GenerateOpenApiDocuments"
Properties="TargetFramework=$(TargetFrameworks.Split(';')[0])" Properties="TargetFramework=$(_OpenApiGenerateDocumentsTFM)"
RemoveProperties="RuntimeIdentifier" /> RemoveProperties="RuntimeIdentifier" />
</Target> </Target>
@ -23,27 +39,11 @@
DependsOnTargets="GenerateOpenApiDocuments" /> DependsOnTargets="GenerateOpenApiDocuments" />
<Target Name="OpenApiGetDocuments" Returns="@(_OpenApiProjectDocuments)"> <Target Name="OpenApiGetDocuments" Returns="@(_OpenApiProjectDocuments)">
<ItemGroup>
<_Temporary Remove="@(_Temporary)" />
<_Temporary Include="$(TargetFrameworks)" Exclude="netcoreapp1.0;netcoreapp1.1;netcoreapp2.0" />
</ItemGroup>
<PropertyGroup>
<_Temporary>@(_Temporary)</_Temporary>
</PropertyGroup>
<MSBuild Projects="$(MSBuildProjectFile)" <MSBuild Projects="$(MSBuildProjectFile)"
Targets="OpenApiGetDocuments" Targets="OpenApiGetDocuments"
Condition=" '$(_Temporary)' != '' " Properties="TargetFramework=$(_OpenApiGenerateDocumentsTFM)"
Properties="TargetFramework=$(_Temporary.Split(';')[0])"
RemoveProperties="RuntimeIdentifier"> RemoveProperties="RuntimeIdentifier">
<Output TaskParameter="TargetOutputs" ItemName="_OpenApiProjectDocuments" /> <Output TaskParameter="TargetOutputs" ItemName="_OpenApiProjectDocuments" />
</MSBuild> </MSBuild>
<ItemGroup>
<_Temporary Remove="@(_Temporary)" />
</ItemGroup>
<PropertyGroup>
<_Temporary />
</PropertyGroup>
</Target> </Target>
</Project> </Project>

View File

@ -137,6 +137,7 @@ namespace Microsoft.Extensions.ApiDescription.Tool.Commands
} }
// Write out the documents. // Write out the documents.
var found = false;
Directory.CreateDirectory(context.OutputDirectory); Directory.CreateDirectory(context.OutputDirectory);
var filePathList = new List<string>(); var filePathList = new List<string>();
foreach (var documentName in documentNames) foreach (var documentName in documentNames)
@ -153,6 +154,7 @@ namespace Microsoft.Extensions.ApiDescription.Tool.Commands
} }
filePathList.Add(filePath); filePathList.Add(filePath);
found = true;
} }
// Write out the cache file. // Write out the cache file.
@ -160,7 +162,12 @@ namespace Microsoft.Extensions.ApiDescription.Tool.Commands
using var writer = new StreamWriter(stream); using var writer = new StreamWriter(stream);
writer.WriteLine(string.Join(Environment.NewLine, filePathList)); writer.WriteLine(string.Join(Environment.NewLine, filePathList));
return true; if (!found)
{
Reporter.WriteError(Resources.DocumentsNotFound);
}
return found;
} }
private static string GetDocument( private static string GetDocument(

View File

@ -33,15 +33,13 @@ namespace Microsoft.Extensions.ApiDescription.Tool
{ {
if (ex is CommandException || ex is CommandParsingException) if (ex is CommandException || ex is CommandParsingException)
{ {
Reporter.WriteVerbose(ex.ToString()); Reporter.WriteError(ex.Message);
} }
else else
{ {
Reporter.WriteInformation(ex.ToString()); Reporter.WriteError(ex.ToString());
} }
Reporter.WriteError(ex.Message);
return 1; return 1;
} }
} }

View File

@ -9,6 +9,9 @@ namespace Microsoft.Extensions.ApiDescription.Tool
{ {
internal static class Reporter internal static class Reporter
{ {
private static AnsiTextWriter Error = new AnsiTextWriter(Console.Error);
private static AnsiTextWriter Out = new AnsiTextWriter(Console.Out);
public static bool IsVerbose { get; set; } public static bool IsVerbose { get; set; }
public static bool NoColor { get; set; } public static bool NoColor { get; set; }
public static bool PrefixOutput { get; set; } public static bool PrefixOutput { get; set; }
@ -17,7 +20,7 @@ namespace Microsoft.Extensions.ApiDescription.Tool
=> NoColor ? value : colorizeFunc(value); => NoColor ? value : colorizeFunc(value);
public static void WriteError(string message) public static void WriteError(string message)
=> WriteLine(Prefix("error: ", Colorize(message, x => Bold + Red + x + Reset))); => WriteLine(Prefix("error: ", Colorize(message, x => Bold + Red + x + Reset)), isError: true);
public static void WriteWarning(string message) public static void WriteWarning(string message)
=> WriteLine(Prefix("warn: ", Colorize(message, x => Bold + Yellow + x + Reset))); => WriteLine(Prefix("warn: ", Colorize(message, x => Bold + Yellow + x + Reset)));
@ -32,7 +35,7 @@ namespace Microsoft.Extensions.ApiDescription.Tool
{ {
if (IsVerbose) if (IsVerbose)
{ {
WriteLine(Prefix("verbose: ", Colorize(message, x => Bold + Black + x + Reset))); WriteLine(Prefix("verbose: ", Colorize(message, x => Gray + x + Reset)));
} }
} }
@ -43,15 +46,15 @@ namespace Microsoft.Extensions.ApiDescription.Tool
value.Split(new[] { Environment.NewLine }, StringSplitOptions.None).Select(l => prefix + l)) value.Split(new[] { Environment.NewLine }, StringSplitOptions.None).Select(l => prefix + l))
: value; : value;
private static void WriteLine(string value) private static void WriteLine(string value, bool isError = false)
{ {
if (NoColor) if (NoColor)
{ {
Console.WriteLine(value); (isError ? Console.Error : Console.Out).WriteLine(value);
} }
else else
{ {
AnsiConsole.WriteLine(value); (isError ? Error : Out).WriteLine(value);
} }
} }
} }

View File

@ -151,7 +151,8 @@
<value>Method '{0}' not found in type '{1}' with expected signature.</value> <value>Method '{0}' not found in type '{1}' with expected signature.</value>
</data> </data>
<data name="ServiceNotFound" xml:space="preserve"> <data name="ServiceNotFound" xml:space="preserve">
<value>Unable to find service type '{0}' in dependency injection container.</value> <value>Unable to find service type '{0}' in dependency injection container. Update the 'Startup' class to register a document.</value>
<comment>Do not translate 'Startup'</comment>
</data> </data>
<data name="MethodReturnedNull" xml:space="preserve"> <data name="MethodReturnedNull" xml:space="preserve">
<value>Method '{0}' of type '{1}' returned null. Must return a non-null '{2}'.</value> <value>Method '{0}' of type '{1}' returned null. Must return a non-null '{2}'.</value>
@ -186,4 +187,8 @@
<data name="ServiceProviderNotFound" xml:space="preserve"> <data name="ServiceProviderNotFound" xml:space="preserve">
<value>Unable to resolve a non-null '{0}' implementation using method '{1}', '{2}' or '{3}' of type '{4}'.</value> <value>Unable to resolve a non-null '{0}' implementation using method '{1}', '{2}' or '{3}' of type '{4}'.</value>
</data> </data>
<data name="DocumentsNotFound" xml:space="preserve">
<value>Unable to find any registered documents. Update the 'Startup' class to register a document.</value>
<comment>Do not translate 'Startup'</comment>
</data>
</root> </root>

View File

@ -2,70 +2,74 @@
"solution": { "solution": {
"path": "Mvc.sln", "path": "Mvc.sln",
"projects": [ "projects": [
"test\\WebSites\\BasicWebSite\\BasicWebSite.csproj", "Extensions.ApiDescription.Client\\src\\Microsoft.Extensions.ApiDescription.Client.csproj",
"test\\WebSites\\RoutingWebSite\\Mvc.RoutingWebSite.csproj", "Extensions.ApiDescription.Server\\src\\Microsoft.Extensions.ApiDescription.Server.csproj",
"test\\WebSites\\RazorWebSite\\RazorWebSite.csproj", "GetDocumentInsider\\src\\GetDocumentInsider.csproj",
"test\\WebSites\\FormatterWebSite\\FormatterWebSite.csproj", "Mvc.Abstractions\\src\\Microsoft.AspNetCore.Mvc.Abstractions.csproj",
"test\\WebSites\\ApiExplorerWebSite\\ApiExplorerWebSite.csproj", "Mvc.Abstractions\\test\\Microsoft.AspNetCore.Mvc.Abstractions.Test.csproj",
"test\\WebSites\\VersioningWebSite\\VersioningWebSite.csproj", "Mvc.Analyzers\\src\\Microsoft.AspNetCore.Mvc.Analyzers.csproj",
"test\\WebSites\\TagHelpersWebSite\\TagHelpersWebSite.csproj", "Mvc.Analyzers\\test\\Mvc.Analyzers.Test.csproj",
"test\\WebSites\\FilesWebSite\\FilesWebSite.csproj", "Mvc.Api.Analyzers\\src\\Microsoft.AspNetCore.Mvc.Api.Analyzers.csproj",
"test\\WebSites\\ApplicationModelWebSite\\ApplicationModelWebSite.csproj", "Mvc.Api.Analyzers\\test\\Mvc.Api.Analyzers.Test.csproj",
"test\\WebSites\\HtmlGenerationWebSite\\HtmlGenerationWebSite.csproj", "Mvc.ApiExplorer\\src\\Microsoft.AspNetCore.Mvc.ApiExplorer.csproj",
"test\\WebSites\\ErrorPageMiddlewareWebSite\\ErrorPageMiddlewareWebSite.csproj", "Mvc.ApiExplorer\\test\\Microsoft.AspNetCore.Mvc.ApiExplorer.Test.csproj",
"test\\WebSites\\XmlFormattersWebSite\\XmlFormattersWebSite.csproj", "Mvc.Core\\src\\Microsoft.AspNetCore.Mvc.Core.csproj",
"test\\WebSites\\ControllersFromServicesWebSite\\ControllersFromServicesWebSite.csproj", "Mvc.Core\\test\\Microsoft.AspNetCore.Mvc.Core.Test.csproj",
"test\\WebSites\\ControllersFromServicesClassLibrary\\ControllersFromServicesClassLibrary.csproj", "Mvc.Cors\\src\\Microsoft.AspNetCore.Mvc.Cors.csproj",
"test\\WebSites\\CorsWebSite\\CorsWebSite.csproj", "Mvc.Cors\\test\\Microsoft.AspNetCore.Mvc.Cors.Test.csproj",
"samples\\MvcSandbox\\MvcSandbox.csproj", "Mvc.DataAnnotations\\src\\Microsoft.AspNetCore.Mvc.DataAnnotations.csproj",
"test\\WebSites\\SimpleWebSite\\SimpleWebSite.csproj", "Mvc.DataAnnotations\\test\\Microsoft.AspNetCore.Mvc.DataAnnotations.Test.csproj",
"test\\WebSites\\SecurityWebSite\\SecurityWebSite.csproj", "Mvc.Formatters.Json\\src\\Microsoft.AspNetCore.Mvc.Formatters.Json.csproj",
"test\\WebSites\\RazorPagesWebSite\\RazorPagesWebSite.csproj", "Mvc.Formatters.Xml\\src\\Microsoft.AspNetCore.Mvc.Formatters.Xml.csproj",
"benchmarks\\Microsoft.AspNetCore.Mvc.Performance\\Microsoft.AspNetCore.Mvc.Performance.csproj", "Mvc.Formatters.Xml\\test\\Microsoft.AspNetCore.Mvc.Formatters.Xml.Test.csproj",
"test\\WebSites\\RazorBuildWebSite\\RazorBuildWebSite.csproj", "Mvc.Localization\\src\\Microsoft.AspNetCore.Mvc.Localization.csproj",
"test\\WebSites\\RazorBuildWebSite.Views\\RazorBuildWebSite.Views.csproj", "Mvc.Localization\\test\\Microsoft.AspNetCore.Mvc.Localization.Test.csproj",
"Mvc.Analyzers\\src\\Microsoft.AspNetCore.Mvc.Analyzers.csproj", "Mvc.NewtonsoftJson\\src\\Microsoft.AspNetCore.Mvc.NewtonsoftJson.csproj",
"Mvc.Analyzers\\test\\Mvc.Analyzers.Test.csproj", "Mvc.NewtonsoftJson\\test\\Microsoft.AspNetCore.Mvc.NewtonsoftJson.Test.csproj",
"test\\WebSites\\RazorPagesClassLibrary\\RazorPagesClassLibrary.csproj", "Mvc.Razor.RuntimeCompilation\\src\\Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation.csproj",
"shared\\Mvc.Views.TestCommon\\Microsoft.AspNetCore.Mvc.Views.TestCommon.csproj", "Mvc.Razor.RuntimeCompilation\\test\\Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation.Test.csproj",
"Mvc.Api.Analyzers\\test\\Mvc.Api.Analyzers.Test.csproj", "Mvc.RazorPages\\src\\Microsoft.AspNetCore.Mvc.RazorPages.csproj",
"Mvc.Api.Analyzers\\src\\Microsoft.AspNetCore.Mvc.Api.Analyzers.csproj", "Mvc.RazorPages\\test\\Microsoft.AspNetCore.Mvc.RazorPages.Test.csproj",
"test\\WebSites\\GenericHostWebSite\\GenericHostWebSite.csproj", "Mvc.Razor\\src\\Microsoft.AspNetCore.Mvc.Razor.csproj",
"Mvc\\src\\Microsoft.AspNetCore.Mvc.csproj", "Mvc.Razor\\test\\Microsoft.AspNetCore.Mvc.Razor.Test.csproj",
"Mvc\\test\\Microsoft.AspNetCore.Mvc.Test.csproj", "Mvc.TagHelpers\\src\\Microsoft.AspNetCore.Mvc.TagHelpers.csproj",
"Mvc.Abstractions\\src\\Microsoft.AspNetCore.Mvc.Abstractions.csproj", "Mvc.TagHelpers\\test\\Microsoft.AspNetCore.Mvc.TagHelpers.Test.csproj",
"Mvc.Abstractions\\test\\Microsoft.AspNetCore.Mvc.Abstractions.Test.csproj", "Mvc.Testing\\src\\Microsoft.AspNetCore.Mvc.Testing.csproj",
"Mvc.ApiExplorer\\src\\Microsoft.AspNetCore.Mvc.ApiExplorer.csproj", "Mvc.ViewFeatures\\src\\Microsoft.AspNetCore.Mvc.ViewFeatures.csproj",
"Mvc.ApiExplorer\\test\\Microsoft.AspNetCore.Mvc.ApiExplorer.Test.csproj", "Mvc.ViewFeatures\\test\\Microsoft.AspNetCore.Mvc.ViewFeatures.Test.csproj",
"Mvc.Core\\src\\Microsoft.AspNetCore.Mvc.Core.csproj", "Mvc\\src\\Microsoft.AspNetCore.Mvc.csproj",
"Mvc.Core\\test\\Microsoft.AspNetCore.Mvc.Core.Test.csproj", "Mvc\\test\\Microsoft.AspNetCore.Mvc.Test.csproj",
"Mvc.Cors\\src\\Microsoft.AspNetCore.Mvc.Cors.csproj", "benchmarks\\Microsoft.AspNetCore.Mvc.Performance\\Microsoft.AspNetCore.Mvc.Performance.csproj",
"Mvc.Cors\\test\\Microsoft.AspNetCore.Mvc.Cors.Test.csproj", "dotnet-getdocument\\src\\dotnet-getdocument.csproj",
"Mvc.DataAnnotations\\src\\Microsoft.AspNetCore.Mvc.DataAnnotations.csproj", "samples\\MvcSandbox\\MvcSandbox.csproj",
"Mvc.DataAnnotations\\test\\Microsoft.AspNetCore.Mvc.DataAnnotations.Test.csproj", "shared\\Mvc.Core.TestCommon\\Microsoft.AspNetCore.Mvc.Core.TestCommon.csproj",
"Mvc.Formatters.Json\\src\\Microsoft.AspNetCore.Mvc.Formatters.Json.csproj", "shared\\Mvc.TestDiagnosticListener\\Microsoft.AspNetCore.Mvc.TestDiagnosticListener.csproj",
"Mvc.Formatters.Xml\\src\\Microsoft.AspNetCore.Mvc.Formatters.Xml.csproj", "shared\\Mvc.Views.TestCommon\\Microsoft.AspNetCore.Mvc.Views.TestCommon.csproj",
"Mvc.Formatters.Xml\\test\\Microsoft.AspNetCore.Mvc.Formatters.Xml.Test.csproj", "test\\Mvc.FunctionalTests\\Microsoft.AspNetCore.Mvc.FunctionalTests.csproj",
"Mvc.Localization\\src\\Microsoft.AspNetCore.Mvc.Localization.csproj", "test\\Mvc.IntegrationTests\\Microsoft.AspNetCore.Mvc.IntegrationTests.csproj",
"Mvc.Localization\\test\\Microsoft.AspNetCore.Mvc.Localization.Test.csproj", "test\\WebSites\\ApiExplorerWebSite\\ApiExplorerWebSite.csproj",
"Mvc.Razor\\src\\Microsoft.AspNetCore.Mvc.Razor.csproj", "test\\WebSites\\ApplicationModelWebSite\\ApplicationModelWebSite.csproj",
"Mvc.Razor\\test\\Microsoft.AspNetCore.Mvc.Razor.Test.csproj", "test\\WebSites\\BasicWebSite\\BasicWebSite.csproj",
"Mvc.RazorPages\\src\\Microsoft.AspNetCore.Mvc.RazorPages.csproj", "test\\WebSites\\ControllersFromServicesClassLibrary\\ControllersFromServicesClassLibrary.csproj",
"Mvc.RazorPages\\test\\Microsoft.AspNetCore.Mvc.RazorPages.Test.csproj", "test\\WebSites\\ControllersFromServicesWebSite\\ControllersFromServicesWebSite.csproj",
"Mvc.TagHelpers\\src\\Microsoft.AspNetCore.Mvc.TagHelpers.csproj", "test\\WebSites\\CorsWebSite\\CorsWebSite.csproj",
"Mvc.TagHelpers\\test\\Microsoft.AspNetCore.Mvc.TagHelpers.Test.csproj", "test\\WebSites\\ErrorPageMiddlewareWebSite\\ErrorPageMiddlewareWebSite.csproj",
"Mvc.ViewFeatures\\src\\Microsoft.AspNetCore.Mvc.ViewFeatures.csproj", "test\\WebSites\\FilesWebSite\\FilesWebSite.csproj",
"Mvc.ViewFeatures\\test\\Microsoft.AspNetCore.Mvc.ViewFeatures.Test.csproj", "test\\WebSites\\FormatterWebSite\\FormatterWebSite.csproj",
"test\\Mvc.FunctionalTests\\Microsoft.AspNetCore.Mvc.FunctionalTests.csproj", "test\\WebSites\\GenericHostWebSite\\GenericHostWebSite.csproj",
"test\\Mvc.IntegrationTests\\Microsoft.AspNetCore.Mvc.IntegrationTests.csproj", "test\\WebSites\\HtmlGenerationWebSite\\HtmlGenerationWebSite.csproj",
"shared\\Mvc.TestDiagnosticListener\\Microsoft.AspNetCore.Mvc.TestDiagnosticListener.csproj", "test\\WebSites\\RazorBuildWebSite.PrecompiledViews\\RazorBuildWebSite.PrecompiledViews.csproj",
"Mvc.Testing\\src\\Microsoft.AspNetCore.Mvc.Testing.csproj", "test\\WebSites\\RazorBuildWebSite.Views\\RazorBuildWebSite.Views.csproj",
"shared\\Mvc.Core.TestCommon\\Microsoft.AspNetCore.Mvc.Core.TestCommon.csproj", "test\\WebSites\\RazorBuildWebSite\\RazorBuildWebSite.csproj",
"Mvc.NewtonsoftJson\\src\\Microsoft.AspNetCore.Mvc.NewtonsoftJson.csproj", "test\\WebSites\\RazorPagesClassLibrary\\RazorPagesClassLibrary.csproj",
"Mvc.NewtonsoftJson\\test\\Microsoft.AspNetCore.Mvc.NewtonsoftJson.Test.csproj", "test\\WebSites\\RazorPagesWebSite\\RazorPagesWebSite.csproj",
"Mvc.Razor.RuntimeCompilation\\src\\Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation.csproj", "test\\WebSites\\RazorWebSite\\RazorWebSite.csproj",
"Mvc.Razor.RuntimeCompilation\\test\\Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation.Test.csproj", "test\\WebSites\\RoutingWebSite\\Mvc.RoutingWebSite.csproj",
"test\\WebSites\\RazorBuildWebSite.PrecompiledViews\\RazorBuildWebSite.PrecompiledViews.csproj" "test\\WebSites\\SecurityWebSite\\SecurityWebSite.csproj",
"test\\WebSites\\SimpleWebSite\\SimpleWebSite.csproj",
"test\\WebSites\\TagHelpersWebSite\\TagHelpersWebSite.csproj",
"test\\WebSites\\VersioningWebSite\\VersioningWebSite.csproj",
"test\\WebSites\\XmlFormattersWebSite\\XmlFormattersWebSite.csproj"
] ]
} }
} }

View File

@ -27,15 +27,13 @@ namespace Microsoft.Extensions.ApiDescription.Tool
{ {
if (ex is CommandException || ex is CommandParsingException) if (ex is CommandException || ex is CommandParsingException)
{ {
Reporter.WriteVerbose(ex.ToString()); Reporter.WriteError(ex.Message);
} }
else else
{ {
Reporter.WriteInformation(ex.ToString()); Reporter.WriteError(ex.ToString());
} }
Reporter.WriteError(ex.Message);
return 1; return 1;
} }
} }