public interface IConfigService { void Set(); Config Get(); } public class ConfigService: IConfigService { private readonly IConsole _console; private readonly string _directoryName; private readonly string _fileName; public ConfigService(IConsole console) { _console = console; _directoryName = ".api-cli"; _fileName = "config.json"; } public void Set() { var directory = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), _directoryName); if (!Directory.Exists(directory)) { Directory.CreateDirectory(directory); } var config = new Config { //弹出交互框,让用户输入,设置默认值为:5000/ Endpoint = Prompt.GetString("Specify the endpoint:", "http://localhost:5000/") }; if (!config.Endpoint.EndsWith("https://www.jb51.net/")) { config.Endpoint += "https://www.jb51.net/"; } var filePath = Path.Combine(directory, _fileName); using (var outputFile = new StreamWriter(filePath, false, Encoding.UTF8)) { outputFile.WriteLine(JsonConvert.SerializeObject(config, Formatting.Indented)); } _console.WriteLine($"Config saved in {filePath}."); } public Config Get() { var filePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), _directoryName, _fileName); if (File.Exists(filePath)) { var content = File.ReadAllText(filePath); try { var config = JsonConvert.DeserializeObject<Config>(content); return config; } catch { _console.WriteLine("The config is invalid, please use 'config set' command to reset one."); } } else { _console.WriteLine("Config is not existed, please use 'config set' command to set one."); } return null; } }
4.ItemClient - 调用Web Api的具体实现,使用的方式
public interface IItemClient { Task<string> Create(ItemForm form); Task<string> Get(string id); Task<string> List(); Task<string> Delete(string id); } public class ItemClient : IItemClient { public HttpClient Client { get; } public ItemClient(HttpClient client, IConfigService configService) { var config = configService.Get(); if (config == null) { return; } client.BaseAddress = new Uri(config.Endpoint); Client = client; } public async Task<string> Create(ItemForm form) { var content = new StringContent(JsonConvert.SerializeObject(form), Encoding.UTF8, "application/json"); var result = await Client.PostAsync("/api/items", content); if (result.IsSuccessStatusCode) { var stream = await result.Content.ReadAsStreamAsync(); var item = Deserialize<Item>(stream); return $"Item created, info:{item}"; } return "Error occur, please again later."; } public async Task<string> Get(string id) { var result = await Client.GetAsync($"/api/items/{id}"); if (result.IsSuccessStatusCode) { var stream = await result.Content.ReadAsStreamAsync(); var item = Deserialize<Item>(stream); var response = new StringBuilder(); response.AppendLine($"{"Id".PadRight(40, ' ')}{"Name".PadRight(20, ' ')}Age"); response.AppendLine($"{item.Id.PadRight(40, ' ')}{item.Name.PadRight(20, ' ')}{item.Age}"); return response.ToString(); } return "Error occur, please again later."; } public async Task<string> List() { var result = await Client.GetAsync($"/api/items"); if (result.IsSuccessStatusCode) { var stream = await result.Content.ReadAsStreamAsync(); var items = Deserialize<List<Item>>(stream); var response = new StringBuilder(); response.AppendLine($"{"Id".PadRight(40, ' ')}{"Name".PadRight(20, ' ')}Age"); if (items != null && items.Count > 0) { foreach (var item in items) { response.AppendLine($"{item.Id.PadRight(40, ' ')}{item.Name.PadRight(20, ' ')}{item.Age}"); } } return response.ToString(); } return "Error occur, please again later."; } public async Task<string> Delete(string id) { var result = await Client.DeleteAsync($"/api/items/{id}"); if (result.IsSuccessStatusCode) { return $"Item {id} deleted."; } if (result.StatusCode == HttpStatusCode.NotFound) { return $"Item {id} not found."; } return "Error occur, please again later."; } private static T Deserialize<T>(Stream stream) { using var reader = new JsonTextReader(new StreamReader(stream)); var serializer = new JsonSerializer(); return (T)serializer.Deserialize(reader, typeof(T)); } }
如何发布
在项目文件中设置发布程序的名称(AssemblyName):
<PropertyGroup> <OutputType>Exe</OutputType> <TargetFramework>netcoreapp3.1</TargetFramework> <AssemblyName>api-cli</AssemblyName> </PropertyGroup>
进入控制台程序目录:
cd src/NetCoreCLI
发布Linux使用版本:
dotnet publish -c Release -r linux-x64 /p:PublishSingleFile=true
发布Windows使用版本:
dotnet publish -c Release -r win-x64 /p:PublishSingleFile=true
发布MAC使用版本:
dotnet publish -c Release -r osx-x64 /p:PublishSingleFile=true
使用示例
这里使用Linux作为示例环境。
1. 以docker的方式启动web api
2. 虚拟机上没有安装.net core的环境
3. 把编译好的CLI工具拷贝到虚拟机上,授权并移动到PATH中(如果不移动,可以通过./api-cli的方式调用)
sudo chmod +x api-cli #授权 sudo mv ./api-cli /usr/local/bin/api-cli #移动到PATH
4. 设置配置文件:api-cli config set
5. 查看配置文件:api-cli config get
6. 创建条目:api-cli item create
7. 条目列表:api-cli item list
8. 获取条目:api-cli item get
9. 删除条目:api-cli item delete
10. 指令帮助:api-cli -h, api-cli config -h, api-cli item -h
11. 错误指令:api-cli xxx
源码地址
https://github.com/ErikXu/NetCoreCLI
参考资料