|
2 | 2 |
|
3 | 3 | In this section, you'll use GitHub Copilot's code completion to implement API endpoints. |
4 | 4 |
|
5 | | -> [!IMPORTANT] |
6 | | -> For this exercise, **DO NOT** copy and paste the code snippet provided, but rather type it manually. This will allow you to experience code completion as you would if you were coding back at your desk. You'll likely see you only have to type a few characters before GitHub Copilot begins suggesting the rest. |
| 5 | +> IMPORTANT: For this exercise, **DO NOT** copy and paste the code snippet provided, but rather type it manually. This will allow you to experience code completion as you would if you were coding back at your desk. You'll likely see you only have to type a few characters before GitHub Copilot begins suggesting the rest. |
7 | 6 |
|
8 | | -1. [] Open **ProductEndpoints.cs** in the Products project under **Endpoints** - it should be empty or contain minimal code. |
9 | | -2. [] Begin typing a comment to describe what you want to implement: |
| 7 | +1. [] Stop debugging the appliaction if it is currently running. |
| 8 | + |
| 9 | +1. [] In the Solution Explorer, in the **Products** project, open **Endpoints/ProductEndpoints.cs** - it will have a single endpoint implemented. |
| 10 | + |
| 11 | + > Note: GitHub Copilot will not give code suggestions when debugging. |
| 12 | + |
| 13 | +1. [] Let's implement a new **MapGet** to get product details for a specific **id**. Move our cursor and click on line 20 under the existing **/** endpoint. Text suggestion may apprear or type: |
10 | 14 | ```csharp |
11 | | - group.MapGet( |
| 15 | + g |
12 | 16 | ``` |
13 | | -3. [] Wait for the ghost text suggestions to appear (gray text). |
14 | | - |
| 17 | +1. [] Wait for the ghost text suggestions to appear (gray text). |
| 18 | +; |
15 | 19 |  |
16 | 20 |
|
17 | | -4. [] Press Tab to accept the suggestion or continue typing to get more specific suggestions. |
| 21 | +1. [] Press Tab to accept the suggestion or continue typing to get more specific suggestions. |
18 | 22 |
|
19 | | -5. [] From there Next Edit Suggetions (NES) or addtional Ghost Text suggestions will appear. |
| 23 | +1. [] From there Next Edit Suggetions (NES) or addtional Ghost Text suggestions will appear. |
20 | 24 |
|
21 | 25 |  |
22 | 26 |
|
23 | | -6. [] Implement the following endpoints using GitHub Copilot's suggestions: |
24 | | - - GET product by ID |
| 27 | +1. [] We now can implement the following endpoints using GitHub Copilot: |
25 | 28 | - POST to create a new product |
26 | 29 | - PUT to update a product |
27 | 30 | - DELETE to remove a product |
28 | 31 |
|
29 | | - The end code sould look similar to: |
| 32 | + - We can continue to use suggestions OR we could open GitHub Copilot Chat and work with Agent mode: |
| 33 | + - Open GitHub Copilot Chat in the top-right corner of Visual Studio and select **Open Chat Window** or press `Ctrl+\+C` if Copilot chat isn't open. |
| 34 | + - Switch to **Agent** mode. |
| 35 | + - ] |
| 36 | + - Ask the agent: `Can you implement the rest of the endpoints for the Product API and also implement the ProductService to call these new endpoints in the Store project?` |
| 37 | + |
| 38 | + The end code in **ProductEndpoints.cs** sould look similar to: |
30 | 39 |
|
31 | 40 | ```csharp |
32 | 41 | group.MapGet("/", async (ProductDataContext db) => |
@@ -88,20 +97,83 @@ In this section, you'll use GitHub Copilot's code completion to implement API en |
88 | 97 | .Produces(StatusCodes.Status404NotFound); |
89 | 98 | ``` |
90 | 99 |
|
91 | | - > [!IMPORTANT] |
92 | | - >Because LLMs are probabilistic, not deterministic, the exact code generated can vary. The above is a representative example. If your code is different, that's just fine as long as it works! |
| 100 | + In the **Store** project in the solution explorer open **Services/ProductService.cs**, the code sould look similar to: |
93 | 101 |
|
94 | | -7. [] Try changing the variable name of **id** to `productId` in the new **MapGet** method and see Next Edit Suggestions help out. |
| 102 | + ```cs |
| 103 | + using DataEntities; |
| 104 | + using System.Text.Json; |
| 105 | + |
| 106 | + namespace Store.Services; |
| 107 | + |
| 108 | + public class ProductService |
| 109 | + { |
| 110 | + HttpClient httpClient; |
| 111 | + public ProductService(HttpClient httpClient) |
| 112 | + { |
| 113 | + this.httpClient = httpClient; |
| 114 | + } |
| 115 | + public async Task<List<Product>> GetProducts() |
| 116 | + { |
| 117 | + List<Product>? products = null; |
| 118 | + var response = await httpClient.GetAsync("/api/Product"); |
| 119 | + if (response.IsSuccessStatusCode) |
| 120 | + { |
| 121 | + var options = new JsonSerializerOptions |
| 122 | + { |
| 123 | + PropertyNameCaseInsensitive = true |
| 124 | + }; |
| 125 | + |
| 126 | + products = await response.Content.ReadFromJsonAsync(ProductSerializerContext.Default.ListProduct); |
| 127 | + } |
| 128 | + |
| 129 | + return products ?? new List<Product>(); |
| 130 | + } |
| 131 | + |
| 132 | + public async Task<Product?> GetProductById(int id) |
| 133 | + { |
| 134 | + var response = await httpClient.GetAsync($"/api/Product/{id}"); |
| 135 | + if (response.IsSuccessStatusCode) |
| 136 | + { |
| 137 | + return await response.Content.ReadFromJsonAsync<Product>(ProductSerializerContext.Default.Product); |
| 138 | + } |
| 139 | + return null; |
| 140 | + } |
| 141 | + |
| 142 | + public async Task<bool> CreateProduct(Product product) |
| 143 | + { |
| 144 | + var response = await httpClient.PostAsJsonAsync("/api/Product", product, ProductSerializerContext.Default.Product); |
| 145 | + return response.IsSuccessStatusCode; |
| 146 | + } |
| 147 | + |
| 148 | + public async Task<bool> UpdateProduct(int id, Product product) |
| 149 | + { |
| 150 | + var response = await httpClient.PutAsJsonAsync($"/api/Product/{id}", product, ProductSerializerContext.Default.Product); |
| 151 | + return response.IsSuccessStatusCode; |
| 152 | + } |
| 153 | + |
| 154 | + public async Task<bool> DeleteProduct(int id) |
| 155 | + { |
| 156 | + var response = await httpClient.DeleteAsync($"/api/Product/{id}"); |
| 157 | + return response.IsSuccessStatusCode; |
| 158 | + } |
| 159 | + } |
| 160 | + ``` |
| 161 | + |
| 162 | + > NOTE: Because LLMs are probabilistic, not deterministic, the exact code generated can vary. The above is a representative example. If your code is different, that's just fine as long as it works! |
| 163 | +
|
| 164 | +1. [] Go back to **ProductEndpoints.cs**, and try changing the variable name of **id** to `productId` in the new **MapGet** method and see Next Edit Suggestions help out. |
95 | 165 |
|
96 | 166 |  |
97 | 167 |
|
98 | | -8. [] Try using documentation generation: |
| 168 | +1. [] Try using documentation generation: |
99 | 169 | - Type `///` above a method to generate XML documentation on the **MapProductEndpoints** this can also be brought up with `Alt+/` for inline and then entering **/** which will bring up a list of commands. |
100 | 170 |
|
101 | 171 |  |
102 | 172 |
|
103 | | -9. [] Test your implementation: |
| 173 | +1. [] Test your implementation: |
104 | 174 | - Run the AppHost project. |
105 | | - - Test your new endpoints. |
| 175 | + - Test your new endpoints by going to **https://localhost:7130/api/Product/1** |
| 176 | + |
| 177 | +1. [] Stop debugging and close the application |
106 | 178 |
|
107 | 179 | **Key Takeaway**: GitHub Copilot can generate complete API implementations based on your comments or partial code, significantly speeding up development. |
0 commit comments