From 7adcfcb552c25d58a15e9864d39209b0d6ce2bee Mon Sep 17 00:00:00 2001 From: Justin Topham Date: Sat, 13 Apr 2019 23:48:37 +0100 Subject: [PATCH 1/2] XML Doc Consolidation (embedded in API feature) --- src/Stratis.Bitcoin.Features.Api/Startup.cs | 130 +++++++++++++++++- ...Stratis.Bitcoin.Features.BlockStore.csproj | 2 +- .../Stratis.Bitcoin.Features.Consensus.csproj | 2 +- ...Stratis.Bitcoin.Features.MemoryPool.csproj | 2 +- .../Stratis.Bitcoin.Features.RPC.csproj | 2 +- .../Stratis.Bitcoin.Features.Wallet.csproj | 2 +- src/Stratis.Bitcoin/Stratis.Bitcoin.csproj | 2 +- 7 files changed, 134 insertions(+), 8 deletions(-) diff --git a/src/Stratis.Bitcoin.Features.Api/Startup.cs b/src/Stratis.Bitcoin.Features.Api/Startup.cs index f548950a149..33ca2eaa092 100644 --- a/src/Stratis.Bitcoin.Features.Api/Startup.cs +++ b/src/Stratis.Bitcoin.Features.Api/Startup.cs @@ -1,4 +1,6 @@ -using System.IO; +using System; +using System.IO; +using System.Xml; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Configuration; @@ -11,6 +13,8 @@ namespace Stratis.Bitcoin.Features.Api { public class Startup { + private const string consolidatedXmlFilename = "Stratis.Bitcoin.Api.xml"; + public Startup(IHostingEnvironment env) { IConfigurationBuilder builder = new ConfigurationBuilder() @@ -72,7 +76,10 @@ public void ConfigureServices(IServiceCollection services) //Set the comments path for the swagger json and ui. string basePath = PlatformServices.Default.Application.ApplicationBasePath; - string apiXmlPath = Path.Combine(basePath, "Stratis.Bitcoin.Api.xml"); + + BuildConsolidatedXmlFile(basePath); + + string apiXmlPath = Path.Combine(basePath, consolidatedXmlFilename); string walletXmlPath = Path.Combine(basePath, "Stratis.Bitcoin.LightWallet.xml"); if (File.Exists(apiXmlPath)) @@ -89,6 +96,125 @@ public void ConfigureServices(IServiceCollection services) }); } + // Individual C# projects can output their documentation in an XML format, which can be picked up and then + // displayed by Swagger. However, this presents a problem in multi-project solutions, which generate + // multiple XML files. The following four functions consolidate XML produced for the Full Node projects + // containing documentation relevant for the Swagger API. + // + // Usefully, building the Full Node solution will result in the project XML files also being produced + // in the binary folder of any project that references them. Each time a daemon that uses the API feature + // runs, the code below consolidates XML files (from projects the daemon references) into a single file. + // + // Projects by default do not produce XML documentation, and the option must be explicitly set in the project options. + // + // If you find a project with documentation you need to see in the Swagger API, make the change in the project + // options, and the documentation will appear in the Swagger API. + private void BuildConsolidatedXmlFile(string basePath) + { + DirectoryInfo xmlDir; + + try + { + xmlDir = new DirectoryInfo(basePath); + } + catch (Exception e) + { + Console.WriteLine("Exception occurred: {0}", e.ToString()); + return; + } + + Console.WriteLine("Searching for XML files created by Full Node projects..."); + FileInfo[] xmlFiles = xmlDir.GetFiles("*.xml"); + foreach (FileInfo file in xmlFiles) + { + Console.WriteLine("\tFound " + file.Name); + } + + // Note: No need to delete any existing instance of the consolidated Xml file as the + // XML writer overwrites it anyway. + + XmlWriter consolidatedXmlWriter = BeginConsildatedXmlFile(basePath + "/" + consolidatedXmlFilename); + if (consolidatedXmlWriter != null) + { + Console.WriteLine("Consolidating XML files created by Full Node projects..."); + if (ReadAndAddMemberElementsFromGeneratedXml(basePath, xmlFiles, consolidatedXmlWriter)) + { + FinalizeConsolidatedXmlFile(consolidatedXmlWriter); + } + } + } + + private XmlWriter BeginConsildatedXmlFile(string consolidatedXmlFileFullPath) + { + XmlWriterSettings settings = new XmlWriterSettings(); + settings.Indent = true; + settings.OmitXmlDeclaration = false; + try + { + XmlWriter consolidatedXmlWriter = XmlWriter.Create(consolidatedXmlFileFullPath, settings); + + consolidatedXmlWriter.WriteStartElement("doc"); + consolidatedXmlWriter.WriteStartElement("assembly"); + consolidatedXmlWriter.WriteStartElement("name"); + consolidatedXmlWriter.WriteString("Stratis.Bitcoin"); + consolidatedXmlWriter.WriteEndElement(); + consolidatedXmlWriter.WriteEndElement(); + consolidatedXmlWriter.WriteStartElement("members"); + + return consolidatedXmlWriter; + } + catch (Exception e) + { + Console.WriteLine("Exception occurred: {0}", e.ToString()); + return null; + } + } + + private bool ReadAndAddMemberElementsFromGeneratedXml(string xmlDirPath, FileInfo[] generatedXmlFiles, XmlWriter consolidatedXmlWriter) + { + foreach (FileInfo file in generatedXmlFiles) + { + XmlReaderSettings settings = new XmlReaderSettings(); + string xmlFileFullPath = xmlDirPath + "/" + file.Name; + try + { + XmlReader reader = XmlReader.Create(xmlFileFullPath, settings); + bool alreadyInPosition = false; + + reader.MoveToContent(); // positions the XML reader at the doc element. + + while (alreadyInPosition || reader.Read()) // if not in position, read the next node. + { + alreadyInPosition = false; + if (reader.NodeType == XmlNodeType.Element && reader.Name == "member") + { + consolidatedXmlWriter.WriteNode(reader, false); + // Calling WriteNode() moves the position to the next member element, + // which is exactly what is required. + alreadyInPosition = true; + } + } + Console.WriteLine("\tConsolidated " + file.Name); + } + catch (Exception e) + { + Console.WriteLine("Exception occurred: {0}", e.ToString()); + return false; + } + } + + return true; + } + + private void FinalizeConsolidatedXmlFile(XmlWriter consolidatedXmlWriter) + { + consolidatedXmlWriter.WriteEndElement(); + consolidatedXmlWriter.WriteEndElement(); + consolidatedXmlWriter.Close(); + + Console.WriteLine(consolidatedXmlFilename + " finalized and ready for use!"); + } + // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) { diff --git a/src/Stratis.Bitcoin.Features.BlockStore/Stratis.Bitcoin.Features.BlockStore.csproj b/src/Stratis.Bitcoin.Features.BlockStore/Stratis.Bitcoin.Features.BlockStore.csproj index faabe7e741e..f29e9f4fddd 100644 --- a/src/Stratis.Bitcoin.Features.BlockStore/Stratis.Bitcoin.Features.BlockStore.csproj +++ b/src/Stratis.Bitcoin.Features.BlockStore/Stratis.Bitcoin.Features.BlockStore.csproj @@ -42,7 +42,7 @@ 1701;1702;1705;IDE0008; - + bin\Debug\netstandard2.0\Stratis.Bitcoin.Features.BlockStore.xml diff --git a/src/Stratis.Bitcoin.Features.Consensus/Stratis.Bitcoin.Features.Consensus.csproj b/src/Stratis.Bitcoin.Features.Consensus/Stratis.Bitcoin.Features.Consensus.csproj index 31e98746cad..a97d7fe9fb1 100644 --- a/src/Stratis.Bitcoin.Features.Consensus/Stratis.Bitcoin.Features.Consensus.csproj +++ b/src/Stratis.Bitcoin.Features.Consensus/Stratis.Bitcoin.Features.Consensus.csproj @@ -39,7 +39,7 @@ 1701;1702;1705;IDE0008; - + bin\Debug\netstandard2.0\Stratis.Bitcoin.Features.Consensus.xml diff --git a/src/Stratis.Bitcoin.Features.MemoryPool/Stratis.Bitcoin.Features.MemoryPool.csproj b/src/Stratis.Bitcoin.Features.MemoryPool/Stratis.Bitcoin.Features.MemoryPool.csproj index 8c18de4f76d..21c230731a6 100644 --- a/src/Stratis.Bitcoin.Features.MemoryPool/Stratis.Bitcoin.Features.MemoryPool.csproj +++ b/src/Stratis.Bitcoin.Features.MemoryPool/Stratis.Bitcoin.Features.MemoryPool.csproj @@ -45,7 +45,7 @@ 1701;1702;1705;IDE0008; - + bin\Debug\netstandard2.0\Stratis.Bitcoin.Features.MemoryPool.xml diff --git a/src/Stratis.Bitcoin.Features.RPC/Stratis.Bitcoin.Features.RPC.csproj b/src/Stratis.Bitcoin.Features.RPC/Stratis.Bitcoin.Features.RPC.csproj index fc496187898..0e0492d4117 100644 --- a/src/Stratis.Bitcoin.Features.RPC/Stratis.Bitcoin.Features.RPC.csproj +++ b/src/Stratis.Bitcoin.Features.RPC/Stratis.Bitcoin.Features.RPC.csproj @@ -46,7 +46,7 @@ 1701;1702;1705;IDE0008; - + bin\Debug\netstandard2.0\Stratis.Bitcoin.Features.RPC.xml diff --git a/src/Stratis.Bitcoin.Features.Wallet/Stratis.Bitcoin.Features.Wallet.csproj b/src/Stratis.Bitcoin.Features.Wallet/Stratis.Bitcoin.Features.Wallet.csproj index 8abfd0ab798..e024b141c48 100644 --- a/src/Stratis.Bitcoin.Features.Wallet/Stratis.Bitcoin.Features.Wallet.csproj +++ b/src/Stratis.Bitcoin.Features.Wallet/Stratis.Bitcoin.Features.Wallet.csproj @@ -48,7 +48,7 @@ 1701;1702;1705;IDE0008; - + bin\Debug\netstandard2.0\Stratis.Bitcoin.Features.Wallet.xml diff --git a/src/Stratis.Bitcoin/Stratis.Bitcoin.csproj b/src/Stratis.Bitcoin/Stratis.Bitcoin.csproj index 80e58218a02..0cb9381d942 100644 --- a/src/Stratis.Bitcoin/Stratis.Bitcoin.csproj +++ b/src/Stratis.Bitcoin/Stratis.Bitcoin.csproj @@ -78,7 +78,7 @@ 1701;1702;1705;IDE0008; - + bin\Debug\netstandard2.0\Stratis.Bitcoin.xml From c5f20651badbf57fd5010cd29373e5fbf7e15be6 Mon Sep 17 00:00:00 2001 From: Justin Topham Date: Sun, 14 Apr 2019 00:21:27 +0100 Subject: [PATCH 2/2] Minor API doc fix --- .../MempoolController.cs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/Stratis.Bitcoin.Features.MemoryPool/MempoolController.cs b/src/Stratis.Bitcoin.Features.MemoryPool/MempoolController.cs index 24591b54eec..56addb8c95a 100644 --- a/src/Stratis.Bitcoin.Features.MemoryPool/MempoolController.cs +++ b/src/Stratis.Bitcoin.Features.MemoryPool/MempoolController.cs @@ -14,6 +14,7 @@ namespace Stratis.Bitcoin.Features.MemoryPool /// /// Controller providing operations on the Mempool. /// + [Route("api/[controller]")] public class MempoolController : FeatureController { public MempoolManager MempoolManager { get; private set; } @@ -36,12 +37,10 @@ public Task> GetRawMempool() } /// - /// Gets a hash of each transaction in the memory pool. In other words, a list of the TX IDs for all the transactions in the mempool are retrieved. - /// - /// + /// Gets a hash of each transaction in the memory pool. In other words, a list of the TX IDs for all the transactions in the mempool are retrieved. /// - /// Json formatted "/> containing the memory pool contents. Returns formatted error if fails. - [Route("api/[controller]/getrawmempool")] + /// A Json formatted list of hashes from the memory pool. Returns formatted error if fails. + [Route("getrawmempool")] [HttpGet] public async Task GetRawMempoolAsync() {