@code {
diff --git a/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/ChatWithCustomData-CSharp.Web/Components/Pages/Chat/ChatHeader.razor.css b/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/templates/AIChatWeb-CSharp/AIChatWeb-CSharp.Web/Components/Pages/Chat/ChatHeader.razor.css
similarity index 100%
rename from src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/ChatWithCustomData-CSharp.Web/Components/Pages/Chat/ChatHeader.razor.css
rename to src/ProjectTemplates/Microsoft.Extensions.AI.Templates/templates/AIChatWeb-CSharp/AIChatWeb-CSharp.Web/Components/Pages/Chat/ChatHeader.razor.css
diff --git a/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/ChatWithCustomData-CSharp.Web/Components/Pages/Chat/ChatInput.razor b/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/templates/AIChatWeb-CSharp/AIChatWeb-CSharp.Web/Components/Pages/Chat/ChatInput.razor
similarity index 100%
rename from src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/ChatWithCustomData-CSharp.Web/Components/Pages/Chat/ChatInput.razor
rename to src/ProjectTemplates/Microsoft.Extensions.AI.Templates/templates/AIChatWeb-CSharp/AIChatWeb-CSharp.Web/Components/Pages/Chat/ChatInput.razor
diff --git a/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/ChatWithCustomData-CSharp.Web/Components/Pages/Chat/ChatInput.razor.css b/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/templates/AIChatWeb-CSharp/AIChatWeb-CSharp.Web/Components/Pages/Chat/ChatInput.razor.css
similarity index 100%
rename from src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/ChatWithCustomData-CSharp.Web/Components/Pages/Chat/ChatInput.razor.css
rename to src/ProjectTemplates/Microsoft.Extensions.AI.Templates/templates/AIChatWeb-CSharp/AIChatWeb-CSharp.Web/Components/Pages/Chat/ChatInput.razor.css
diff --git a/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/ChatWithCustomData-CSharp.Web/Components/Pages/Chat/ChatInput.razor.js b/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/templates/AIChatWeb-CSharp/AIChatWeb-CSharp.Web/Components/Pages/Chat/ChatInput.razor.js
similarity index 100%
rename from src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/ChatWithCustomData-CSharp.Web/Components/Pages/Chat/ChatInput.razor.js
rename to src/ProjectTemplates/Microsoft.Extensions.AI.Templates/templates/AIChatWeb-CSharp/AIChatWeb-CSharp.Web/Components/Pages/Chat/ChatInput.razor.js
diff --git a/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/ChatWithCustomData-CSharp.Web/Components/Pages/Chat/ChatMessageItem.razor b/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/templates/AIChatWeb-CSharp/AIChatWeb-CSharp.Web/Components/Pages/Chat/ChatMessageItem.razor
similarity index 100%
rename from src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/ChatWithCustomData-CSharp.Web/Components/Pages/Chat/ChatMessageItem.razor
rename to src/ProjectTemplates/Microsoft.Extensions.AI.Templates/templates/AIChatWeb-CSharp/AIChatWeb-CSharp.Web/Components/Pages/Chat/ChatMessageItem.razor
diff --git a/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/ChatWithCustomData-CSharp.Web/Components/Pages/Chat/ChatMessageItem.razor.css b/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/templates/AIChatWeb-CSharp/AIChatWeb-CSharp.Web/Components/Pages/Chat/ChatMessageItem.razor.css
similarity index 100%
rename from src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/ChatWithCustomData-CSharp.Web/Components/Pages/Chat/ChatMessageItem.razor.css
rename to src/ProjectTemplates/Microsoft.Extensions.AI.Templates/templates/AIChatWeb-CSharp/AIChatWeb-CSharp.Web/Components/Pages/Chat/ChatMessageItem.razor.css
diff --git a/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/ChatWithCustomData-CSharp.Web/Components/Pages/Chat/ChatMessageList.razor b/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/templates/AIChatWeb-CSharp/AIChatWeb-CSharp.Web/Components/Pages/Chat/ChatMessageList.razor
similarity index 100%
rename from src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/ChatWithCustomData-CSharp.Web/Components/Pages/Chat/ChatMessageList.razor
rename to src/ProjectTemplates/Microsoft.Extensions.AI.Templates/templates/AIChatWeb-CSharp/AIChatWeb-CSharp.Web/Components/Pages/Chat/ChatMessageList.razor
diff --git a/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/ChatWithCustomData-CSharp.Web/Components/Pages/Chat/ChatMessageList.razor.css b/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/templates/AIChatWeb-CSharp/AIChatWeb-CSharp.Web/Components/Pages/Chat/ChatMessageList.razor.css
similarity index 100%
rename from src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/ChatWithCustomData-CSharp.Web/Components/Pages/Chat/ChatMessageList.razor.css
rename to src/ProjectTemplates/Microsoft.Extensions.AI.Templates/templates/AIChatWeb-CSharp/AIChatWeb-CSharp.Web/Components/Pages/Chat/ChatMessageList.razor.css
diff --git a/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/ChatWithCustomData-CSharp.Web/Components/Pages/Chat/ChatMessageList.razor.js b/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/templates/AIChatWeb-CSharp/AIChatWeb-CSharp.Web/Components/Pages/Chat/ChatMessageList.razor.js
similarity index 100%
rename from src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/ChatWithCustomData-CSharp.Web/Components/Pages/Chat/ChatMessageList.razor.js
rename to src/ProjectTemplates/Microsoft.Extensions.AI.Templates/templates/AIChatWeb-CSharp/AIChatWeb-CSharp.Web/Components/Pages/Chat/ChatMessageList.razor.js
diff --git a/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/ChatWithCustomData-CSharp.Web/Components/Pages/Chat/ChatSuggestions.razor b/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/templates/AIChatWeb-CSharp/AIChatWeb-CSharp.Web/Components/Pages/Chat/ChatSuggestions.razor
similarity index 100%
rename from src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/ChatWithCustomData-CSharp.Web/Components/Pages/Chat/ChatSuggestions.razor
rename to src/ProjectTemplates/Microsoft.Extensions.AI.Templates/templates/AIChatWeb-CSharp/AIChatWeb-CSharp.Web/Components/Pages/Chat/ChatSuggestions.razor
diff --git a/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/ChatWithCustomData-CSharp.Web/Components/Pages/Chat/ChatSuggestions.razor.css b/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/templates/AIChatWeb-CSharp/AIChatWeb-CSharp.Web/Components/Pages/Chat/ChatSuggestions.razor.css
similarity index 100%
rename from src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/ChatWithCustomData-CSharp.Web/Components/Pages/Chat/ChatSuggestions.razor.css
rename to src/ProjectTemplates/Microsoft.Extensions.AI.Templates/templates/AIChatWeb-CSharp/AIChatWeb-CSharp.Web/Components/Pages/Chat/ChatSuggestions.razor.css
diff --git a/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/ChatWithCustomData-CSharp.Web/Components/Pages/Error.razor b/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/templates/AIChatWeb-CSharp/AIChatWeb-CSharp.Web/Components/Pages/Error.razor
similarity index 100%
rename from src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/ChatWithCustomData-CSharp.Web/Components/Pages/Error.razor
rename to src/ProjectTemplates/Microsoft.Extensions.AI.Templates/templates/AIChatWeb-CSharp/AIChatWeb-CSharp.Web/Components/Pages/Error.razor
diff --git a/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/ChatWithCustomData-CSharp.Web/Components/Routes.razor b/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/templates/AIChatWeb-CSharp/AIChatWeb-CSharp.Web/Components/Routes.razor
similarity index 100%
rename from src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/ChatWithCustomData-CSharp.Web/Components/Routes.razor
rename to src/ProjectTemplates/Microsoft.Extensions.AI.Templates/templates/AIChatWeb-CSharp/AIChatWeb-CSharp.Web/Components/Routes.razor
diff --git a/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/ChatWithCustomData-CSharp.Web/Components/_Imports.razor b/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/templates/AIChatWeb-CSharp/AIChatWeb-CSharp.Web/Components/_Imports.razor
similarity index 66%
rename from src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/ChatWithCustomData-CSharp.Web/Components/_Imports.razor
rename to src/ProjectTemplates/Microsoft.Extensions.AI.Templates/templates/AIChatWeb-CSharp/AIChatWeb-CSharp.Web/Components/_Imports.razor
index 9ad55554648..7464a453aee 100644
--- a/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/ChatWithCustomData-CSharp.Web/Components/_Imports.razor
+++ b/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/templates/AIChatWeb-CSharp/AIChatWeb-CSharp.Web/Components/_Imports.razor
@@ -7,7 +7,7 @@
@using Microsoft.AspNetCore.Components.Web.Virtualization
@using Microsoft.Extensions.AI
@using Microsoft.JSInterop
-@using ChatWithCustomData_CSharp.Web
-@using ChatWithCustomData_CSharp.Web.Components
-@using ChatWithCustomData_CSharp.Web.Components.Layout
-@using ChatWithCustomData_CSharp.Web.Services
+@using AIChatWeb_CSharp.Web
+@using AIChatWeb_CSharp.Web.Components
+@using AIChatWeb_CSharp.Web.Components.Layout
+@using AIChatWeb_CSharp.Web.Services
diff --git a/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/ChatWithCustomData-CSharp.Web/OllamaResilienceHandlerExtensions.cs b/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/templates/AIChatWeb-CSharp/AIChatWeb-CSharp.Web/OllamaResilienceHandlerExtensions.cs
similarity index 95%
rename from src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/ChatWithCustomData-CSharp.Web/OllamaResilienceHandlerExtensions.cs
rename to src/ProjectTemplates/Microsoft.Extensions.AI.Templates/templates/AIChatWeb-CSharp/AIChatWeb-CSharp.Web/OllamaResilienceHandlerExtensions.cs
index fed9c91ca93..4454d8a5577 100644
--- a/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/ChatWithCustomData-CSharp.Web/OllamaResilienceHandlerExtensions.cs
+++ b/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/templates/AIChatWeb-CSharp/AIChatWeb-CSharp.Web/OllamaResilienceHandlerExtensions.cs
@@ -1,7 +1,7 @@
using System;
using Microsoft.Extensions.DependencyInjection;
-namespace ChatWithCustomData_CSharp.Web.Services;
+namespace AIChatWeb_CSharp.Web.Services;
public static class OllamaResilienceHandlerExtensions
{
@@ -31,4 +31,3 @@ public static IServiceCollection AddOllamaResilienceHandler(this IServiceCollect
return services;
}
}
-
diff --git a/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/ChatWithCustomData-CSharp.Web/Program.Aspire.cs b/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/templates/AIChatWeb-CSharp/AIChatWeb-CSharp.Web/Program.Aspire.cs
similarity index 94%
rename from src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/ChatWithCustomData-CSharp.Web/Program.Aspire.cs
rename to src/ProjectTemplates/Microsoft.Extensions.AI.Templates/templates/AIChatWeb-CSharp/AIChatWeb-CSharp.Web/Program.Aspire.cs
index 898b61efc53..31442718f1f 100644
--- a/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/ChatWithCustomData-CSharp.Web/Program.Aspire.cs
+++ b/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/templates/AIChatWeb-CSharp/AIChatWeb-CSharp.Web/Program.Aspire.cs
@@ -2,9 +2,9 @@
#if (IsOpenAI || IsGHModels)
using OpenAI;
#endif
-using ChatWithCustomData_CSharp.Web.Components;
-using ChatWithCustomData_CSharp.Web.Services;
-using ChatWithCustomData_CSharp.Web.Services.Ingestion;
+using AIChatWeb_CSharp.Web.Components;
+using AIChatWeb_CSharp.Web.Services;
+using AIChatWeb_CSharp.Web.Services.Ingestion;
var builder = WebApplication.CreateBuilder(args);
builder.AddServiceDefaults();
diff --git a/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/ChatWithCustomData-CSharp.Web/Program.cs b/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/templates/AIChatWeb-CSharp/AIChatWeb-CSharp.Web/Program.cs
similarity index 97%
rename from src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/ChatWithCustomData-CSharp.Web/Program.cs
rename to src/ProjectTemplates/Microsoft.Extensions.AI.Templates/templates/AIChatWeb-CSharp/AIChatWeb-CSharp.Web/Program.cs
index a51a674cf71..4b041f4a15f 100644
--- a/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/ChatWithCustomData-CSharp.Web/Program.cs
+++ b/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/templates/AIChatWeb-CSharp/AIChatWeb-CSharp.Web/Program.cs
@@ -14,9 +14,9 @@
#elif (IsGHModels || IsOpenAI || IsAzureOpenAI)
using OpenAI;
#endif
-using ChatWithCustomData_CSharp.Web.Components;
-using ChatWithCustomData_CSharp.Web.Services;
-using ChatWithCustomData_CSharp.Web.Services.Ingestion;
+using AIChatWeb_CSharp.Web.Components;
+using AIChatWeb_CSharp.Web.Services;
+using AIChatWeb_CSharp.Web.Services.Ingestion;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorComponents().AddInteractiveServerComponents();
diff --git a/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/ChatWithCustomData-CSharp.Web/Properties/launchSettings.json b/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/templates/AIChatWeb-CSharp/AIChatWeb-CSharp.Web/Properties/launchSettings.json
similarity index 100%
rename from src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/ChatWithCustomData-CSharp.Web/Properties/launchSettings.json
rename to src/ProjectTemplates/Microsoft.Extensions.AI.Templates/templates/AIChatWeb-CSharp/AIChatWeb-CSharp.Web/Properties/launchSettings.json
diff --git a/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/ChatWithCustomData-CSharp.Web/README.md b/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/templates/AIChatWeb-CSharp/AIChatWeb-CSharp.Web/README.md
similarity index 98%
rename from src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/ChatWithCustomData-CSharp.Web/README.md
rename to src/ProjectTemplates/Microsoft.Extensions.AI.Templates/templates/AIChatWeb-CSharp/AIChatWeb-CSharp.Web/README.md
index 88dff74d315..14677ca5372 100644
--- a/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/ChatWithCustomData-CSharp.Web/README.md
+++ b/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/templates/AIChatWeb-CSharp/AIChatWeb-CSharp.Web/README.md
@@ -168,7 +168,7 @@ To use Azure AI Search, you will need an Azure account and an Azure AI Search re
### 1. Create an Azure AI Search Resource
Follow the instructions in the [Azure portal](https://portal.azure.com/) to create an Azure AI Search resource. Note that there is a free tier for the service but it is not currently the default setting on the portal.
-Note that if you previously used the same Azure AI Search resource with different model using this project name, you may need to delete your `data-ChatWithCustomData-CSharp.Web-chunks` and `data-ChatWithCustomData-CSharp.Web-documents` indexes using the [Azure portal](https://portal.azure.com/) first before continuing; otherwise, data ingestion may fail due to a vector dimension mismatch.
+Note that if you previously used the same Azure AI Search resource with different model using this project name, you may need to delete your `data-AIChatWeb-CSharp.Web-chunks` and `data-AIChatWeb-CSharp.Web-documents` indexes using the [Azure portal](https://portal.azure.com/) first before continuing; otherwise, data ingestion may fail due to a vector dimension mismatch.
#### ---#if (IsManagedIdentity)
### 2. Configure Azure AI Search for Keyless Authentication
diff --git a/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/ChatWithCustomData-CSharp.Web/Services/IngestedChunk.cs b/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/templates/AIChatWeb-CSharp/AIChatWeb-CSharp.Web/Services/IngestedChunk.cs
similarity index 90%
rename from src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/ChatWithCustomData-CSharp.Web/Services/IngestedChunk.cs
rename to src/ProjectTemplates/Microsoft.Extensions.AI.Templates/templates/AIChatWeb-CSharp/AIChatWeb-CSharp.Web/Services/IngestedChunk.cs
index 9316ee1dcfb..60e6b5684e4 100644
--- a/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/ChatWithCustomData-CSharp.Web/Services/IngestedChunk.cs
+++ b/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/templates/AIChatWeb-CSharp/AIChatWeb-CSharp.Web/Services/IngestedChunk.cs
@@ -1,7 +1,7 @@
using System.Text.Json.Serialization;
using Microsoft.Extensions.VectorData;
-namespace ChatWithCustomData_CSharp.Web.Services;
+namespace AIChatWeb_CSharp.Web.Services;
public class IngestedChunk
{
@@ -15,7 +15,7 @@ public class IngestedChunk
#else
public const string VectorDistanceFunction = DistanceFunction.CosineDistance;
#endif
- public const string CollectionName = "data-ChatWithCustomData-CSharp.Web-chunks";
+ public const string CollectionName = "data-AIChatWeb-CSharp.Web-chunks";
[VectorStoreKey(StorageName = "key")]
[JsonPropertyName("key")]
diff --git a/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/ChatWithCustomData-CSharp.Web/Services/Ingestion/DataIngestor.cs b/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/templates/AIChatWeb-CSharp/AIChatWeb-CSharp.Web/Services/Ingestion/DataIngestor.cs
similarity index 95%
rename from src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/ChatWithCustomData-CSharp.Web/Services/Ingestion/DataIngestor.cs
rename to src/ProjectTemplates/Microsoft.Extensions.AI.Templates/templates/AIChatWeb-CSharp/AIChatWeb-CSharp.Web/Services/Ingestion/DataIngestor.cs
index af23c29f13c..c573403e618 100644
--- a/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/ChatWithCustomData-CSharp.Web/Services/Ingestion/DataIngestor.cs
+++ b/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/templates/AIChatWeb-CSharp/AIChatWeb-CSharp.Web/Services/Ingestion/DataIngestor.cs
@@ -4,7 +4,7 @@
using Microsoft.Extensions.VectorData;
using Microsoft.ML.Tokenizers;
-namespace ChatWithCustomData_CSharp.Web.Services.Ingestion;
+namespace AIChatWeb_CSharp.Web.Services.Ingestion;
public class DataIngestor(
ILogger logger,
diff --git a/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/ChatWithCustomData-CSharp.Web/Services/Ingestion/DocumentReader.cs b/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/templates/AIChatWeb-CSharp/AIChatWeb-CSharp.Web/Services/Ingestion/DocumentReader.cs
similarity index 96%
rename from src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/ChatWithCustomData-CSharp.Web/Services/Ingestion/DocumentReader.cs
rename to src/ProjectTemplates/Microsoft.Extensions.AI.Templates/templates/AIChatWeb-CSharp/AIChatWeb-CSharp.Web/Services/Ingestion/DocumentReader.cs
index 5122cde3e9a..0a27e628326 100644
--- a/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/ChatWithCustomData-CSharp.Web/Services/Ingestion/DocumentReader.cs
+++ b/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/templates/AIChatWeb-CSharp/AIChatWeb-CSharp.Web/Services/Ingestion/DocumentReader.cs
@@ -1,6 +1,6 @@
using Microsoft.Extensions.DataIngestion;
-namespace ChatWithCustomData_CSharp.Web.Services.Ingestion;
+namespace AIChatWeb_CSharp.Web.Services.Ingestion;
internal sealed class DocumentReader(DirectoryInfo rootDirectory) : IngestionDocumentReader
{
diff --git a/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/ChatWithCustomData-CSharp.Web/Services/Ingestion/PdfPigReader.cs b/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/templates/AIChatWeb-CSharp/AIChatWeb-CSharp.Web/Services/Ingestion/PdfPigReader.cs
similarity index 95%
rename from src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/ChatWithCustomData-CSharp.Web/Services/Ingestion/PdfPigReader.cs
rename to src/ProjectTemplates/Microsoft.Extensions.AI.Templates/templates/AIChatWeb-CSharp/AIChatWeb-CSharp.Web/Services/Ingestion/PdfPigReader.cs
index 2e1ef18494d..ab8d61ac558 100644
--- a/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/ChatWithCustomData-CSharp.Web/Services/Ingestion/PdfPigReader.cs
+++ b/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/templates/AIChatWeb-CSharp/AIChatWeb-CSharp.Web/Services/Ingestion/PdfPigReader.cs
@@ -4,7 +4,7 @@
using UglyToad.PdfPig.DocumentLayoutAnalysis.PageSegmenter;
using UglyToad.PdfPig.DocumentLayoutAnalysis.WordExtractor;
-namespace ChatWithCustomData_CSharp.Web.Services.Ingestion;
+namespace AIChatWeb_CSharp.Web.Services.Ingestion;
internal sealed class PdfPigReader : IngestionDocumentReader
{
diff --git a/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/ChatWithCustomData-CSharp.Web/Services/SemanticSearch.cs b/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/templates/AIChatWeb-CSharp/AIChatWeb-CSharp.Web/Services/SemanticSearch.cs
similarity index 90%
rename from src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/ChatWithCustomData-CSharp.Web/Services/SemanticSearch.cs
rename to src/ProjectTemplates/Microsoft.Extensions.AI.Templates/templates/AIChatWeb-CSharp/AIChatWeb-CSharp.Web/Services/SemanticSearch.cs
index fb0c2eccef0..49bef8de3d1 100644
--- a/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/ChatWithCustomData-CSharp.Web/Services/SemanticSearch.cs
+++ b/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/templates/AIChatWeb-CSharp/AIChatWeb-CSharp.Web/Services/SemanticSearch.cs
@@ -1,7 +1,7 @@
-using ChatWithCustomData_CSharp.Web.Services.Ingestion;
+using AIChatWeb_CSharp.Web.Services.Ingestion;
using Microsoft.Extensions.VectorData;
-namespace ChatWithCustomData_CSharp.Web.Services;
+namespace AIChatWeb_CSharp.Web.Services;
public class SemanticSearch(
#if (IsQdrant)
diff --git a/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/ChatWithCustomData-CSharp.Web/appsettings.Development.json b/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/templates/AIChatWeb-CSharp/AIChatWeb-CSharp.Web/appsettings.Development.json
similarity index 100%
rename from src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/ChatWithCustomData-CSharp.Web/appsettings.Development.json
rename to src/ProjectTemplates/Microsoft.Extensions.AI.Templates/templates/AIChatWeb-CSharp/AIChatWeb-CSharp.Web/appsettings.Development.json
diff --git a/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/ChatWithCustomData-CSharp.Web/appsettings.json b/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/templates/AIChatWeb-CSharp/AIChatWeb-CSharp.Web/appsettings.json
similarity index 100%
rename from src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/ChatWithCustomData-CSharp.Web/appsettings.json
rename to src/ProjectTemplates/Microsoft.Extensions.AI.Templates/templates/AIChatWeb-CSharp/AIChatWeb-CSharp.Web/appsettings.json
diff --git a/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/ChatWithCustomData-CSharp.Web/wwwroot/Data/Example_Emergency_Survival_Kit.pdf b/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/templates/AIChatWeb-CSharp/AIChatWeb-CSharp.Web/wwwroot/Data/Example_Emergency_Survival_Kit.pdf
similarity index 100%
rename from src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/ChatWithCustomData-CSharp.Web/wwwroot/Data/Example_Emergency_Survival_Kit.pdf
rename to src/ProjectTemplates/Microsoft.Extensions.AI.Templates/templates/AIChatWeb-CSharp/AIChatWeb-CSharp.Web/wwwroot/Data/Example_Emergency_Survival_Kit.pdf
diff --git a/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/ChatWithCustomData-CSharp.Web/wwwroot/Data/Example_GPS_Watch.md b/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/templates/AIChatWeb-CSharp/AIChatWeb-CSharp.Web/wwwroot/Data/Example_GPS_Watch.md
similarity index 100%
rename from src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/ChatWithCustomData-CSharp.Web/wwwroot/Data/Example_GPS_Watch.md
rename to src/ProjectTemplates/Microsoft.Extensions.AI.Templates/templates/AIChatWeb-CSharp/AIChatWeb-CSharp.Web/wwwroot/Data/Example_GPS_Watch.md
diff --git a/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/ChatWithCustomData-CSharp.Web/wwwroot/app.css b/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/templates/AIChatWeb-CSharp/AIChatWeb-CSharp.Web/wwwroot/app.css
similarity index 100%
rename from src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/ChatWithCustomData-CSharp.Web/wwwroot/app.css
rename to src/ProjectTemplates/Microsoft.Extensions.AI.Templates/templates/AIChatWeb-CSharp/AIChatWeb-CSharp.Web/wwwroot/app.css
diff --git a/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/ChatWithCustomData-CSharp.Web/wwwroot/app.js b/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/templates/AIChatWeb-CSharp/AIChatWeb-CSharp.Web/wwwroot/app.js
similarity index 100%
rename from src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/ChatWithCustomData-CSharp.Web/wwwroot/app.js
rename to src/ProjectTemplates/Microsoft.Extensions.AI.Templates/templates/AIChatWeb-CSharp/AIChatWeb-CSharp.Web/wwwroot/app.js
diff --git a/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/ChatWithCustomData-CSharp.Web/wwwroot/favicon.ico b/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/templates/AIChatWeb-CSharp/AIChatWeb-CSharp.Web/wwwroot/favicon.ico
similarity index 100%
rename from src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/ChatWithCustomData-CSharp.Web/wwwroot/favicon.ico
rename to src/ProjectTemplates/Microsoft.Extensions.AI.Templates/templates/AIChatWeb-CSharp/AIChatWeb-CSharp.Web/wwwroot/favicon.ico
diff --git a/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/ChatWithCustomData-CSharp.Web/wwwroot/lib/dompurify/README.md b/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/templates/AIChatWeb-CSharp/AIChatWeb-CSharp.Web/wwwroot/lib/dompurify/README.md
similarity index 100%
rename from src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/ChatWithCustomData-CSharp.Web/wwwroot/lib/dompurify/README.md
rename to src/ProjectTemplates/Microsoft.Extensions.AI.Templates/templates/AIChatWeb-CSharp/AIChatWeb-CSharp.Web/wwwroot/lib/dompurify/README.md
diff --git a/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/ChatWithCustomData-CSharp.Web/wwwroot/lib/dompurify/dist/purify.es.mjs b/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/templates/AIChatWeb-CSharp/AIChatWeb-CSharp.Web/wwwroot/lib/dompurify/dist/purify.es.mjs
similarity index 100%
rename from src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/ChatWithCustomData-CSharp.Web/wwwroot/lib/dompurify/dist/purify.es.mjs
rename to src/ProjectTemplates/Microsoft.Extensions.AI.Templates/templates/AIChatWeb-CSharp/AIChatWeb-CSharp.Web/wwwroot/lib/dompurify/dist/purify.es.mjs
diff --git a/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/ChatWithCustomData-CSharp.Web/wwwroot/lib/markdown_viewer/viewer.html b/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/templates/AIChatWeb-CSharp/AIChatWeb-CSharp.Web/wwwroot/lib/markdown_viewer/viewer.html
similarity index 100%
rename from src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/ChatWithCustomData-CSharp.Web/wwwroot/lib/markdown_viewer/viewer.html
rename to src/ProjectTemplates/Microsoft.Extensions.AI.Templates/templates/AIChatWeb-CSharp/AIChatWeb-CSharp.Web/wwwroot/lib/markdown_viewer/viewer.html
diff --git a/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/ChatWithCustomData-CSharp.Web/wwwroot/lib/markdown_viewer/viewer.mjs b/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/templates/AIChatWeb-CSharp/AIChatWeb-CSharp.Web/wwwroot/lib/markdown_viewer/viewer.mjs
similarity index 100%
rename from src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/ChatWithCustomData-CSharp.Web/wwwroot/lib/markdown_viewer/viewer.mjs
rename to src/ProjectTemplates/Microsoft.Extensions.AI.Templates/templates/AIChatWeb-CSharp/AIChatWeb-CSharp.Web/wwwroot/lib/markdown_viewer/viewer.mjs
diff --git a/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/ChatWithCustomData-CSharp.Web/wwwroot/lib/marked/README.md b/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/templates/AIChatWeb-CSharp/AIChatWeb-CSharp.Web/wwwroot/lib/marked/README.md
similarity index 100%
rename from src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/ChatWithCustomData-CSharp.Web/wwwroot/lib/marked/README.md
rename to src/ProjectTemplates/Microsoft.Extensions.AI.Templates/templates/AIChatWeb-CSharp/AIChatWeb-CSharp.Web/wwwroot/lib/marked/README.md
diff --git a/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/ChatWithCustomData-CSharp.Web/wwwroot/lib/marked/dist/marked.esm.js b/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/templates/AIChatWeb-CSharp/AIChatWeb-CSharp.Web/wwwroot/lib/marked/dist/marked.esm.js
similarity index 100%
rename from src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/ChatWithCustomData-CSharp.Web/wwwroot/lib/marked/dist/marked.esm.js
rename to src/ProjectTemplates/Microsoft.Extensions.AI.Templates/templates/AIChatWeb-CSharp/AIChatWeb-CSharp.Web/wwwroot/lib/marked/dist/marked.esm.js
diff --git a/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/ChatWithCustomData-CSharp.Web/wwwroot/lib/pdf_viewer/viewer.html b/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/templates/AIChatWeb-CSharp/AIChatWeb-CSharp.Web/wwwroot/lib/pdf_viewer/viewer.html
similarity index 100%
rename from src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/ChatWithCustomData-CSharp.Web/wwwroot/lib/pdf_viewer/viewer.html
rename to src/ProjectTemplates/Microsoft.Extensions.AI.Templates/templates/AIChatWeb-CSharp/AIChatWeb-CSharp.Web/wwwroot/lib/pdf_viewer/viewer.html
diff --git a/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/ChatWithCustomData-CSharp.Web/wwwroot/lib/pdf_viewer/viewer.mjs b/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/templates/AIChatWeb-CSharp/AIChatWeb-CSharp.Web/wwwroot/lib/pdf_viewer/viewer.mjs
similarity index 100%
rename from src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/ChatWithCustomData-CSharp.Web/wwwroot/lib/pdf_viewer/viewer.mjs
rename to src/ProjectTemplates/Microsoft.Extensions.AI.Templates/templates/AIChatWeb-CSharp/AIChatWeb-CSharp.Web/wwwroot/lib/pdf_viewer/viewer.mjs
diff --git a/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/ChatWithCustomData-CSharp.Web/wwwroot/lib/pdfjs-dist/README.md b/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/templates/AIChatWeb-CSharp/AIChatWeb-CSharp.Web/wwwroot/lib/pdfjs-dist/README.md
similarity index 100%
rename from src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/ChatWithCustomData-CSharp.Web/wwwroot/lib/pdfjs-dist/README.md
rename to src/ProjectTemplates/Microsoft.Extensions.AI.Templates/templates/AIChatWeb-CSharp/AIChatWeb-CSharp.Web/wwwroot/lib/pdfjs-dist/README.md
diff --git a/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/ChatWithCustomData-CSharp.Web/wwwroot/lib/pdfjs-dist/dist/build/pdf.min.mjs b/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/templates/AIChatWeb-CSharp/AIChatWeb-CSharp.Web/wwwroot/lib/pdfjs-dist/dist/build/pdf.min.mjs
similarity index 100%
rename from src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/ChatWithCustomData-CSharp.Web/wwwroot/lib/pdfjs-dist/dist/build/pdf.min.mjs
rename to src/ProjectTemplates/Microsoft.Extensions.AI.Templates/templates/AIChatWeb-CSharp/AIChatWeb-CSharp.Web/wwwroot/lib/pdfjs-dist/dist/build/pdf.min.mjs
diff --git a/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/ChatWithCustomData-CSharp.Web/wwwroot/lib/pdfjs-dist/dist/build/pdf.worker.min.mjs b/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/templates/AIChatWeb-CSharp/AIChatWeb-CSharp.Web/wwwroot/lib/pdfjs-dist/dist/build/pdf.worker.min.mjs
similarity index 100%
rename from src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/ChatWithCustomData-CSharp.Web/wwwroot/lib/pdfjs-dist/dist/build/pdf.worker.min.mjs
rename to src/ProjectTemplates/Microsoft.Extensions.AI.Templates/templates/AIChatWeb-CSharp/AIChatWeb-CSharp.Web/wwwroot/lib/pdfjs-dist/dist/build/pdf.worker.min.mjs
diff --git a/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/ChatWithCustomData-CSharp.Web/wwwroot/lib/pdfjs-dist/dist/web/images/loading-icon.gif b/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/templates/AIChatWeb-CSharp/AIChatWeb-CSharp.Web/wwwroot/lib/pdfjs-dist/dist/web/images/loading-icon.gif
similarity index 100%
rename from src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/ChatWithCustomData-CSharp.Web/wwwroot/lib/pdfjs-dist/dist/web/images/loading-icon.gif
rename to src/ProjectTemplates/Microsoft.Extensions.AI.Templates/templates/AIChatWeb-CSharp/AIChatWeb-CSharp.Web/wwwroot/lib/pdfjs-dist/dist/web/images/loading-icon.gif
diff --git a/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/ChatWithCustomData-CSharp.Web/wwwroot/lib/pdfjs-dist/dist/web/pdf_viewer.css b/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/templates/AIChatWeb-CSharp/AIChatWeb-CSharp.Web/wwwroot/lib/pdfjs-dist/dist/web/pdf_viewer.css
similarity index 100%
rename from src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/ChatWithCustomData-CSharp.Web/wwwroot/lib/pdfjs-dist/dist/web/pdf_viewer.css
rename to src/ProjectTemplates/Microsoft.Extensions.AI.Templates/templates/AIChatWeb-CSharp/AIChatWeb-CSharp.Web/wwwroot/lib/pdfjs-dist/dist/web/pdf_viewer.css
diff --git a/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/ChatWithCustomData-CSharp.Web/wwwroot/lib/pdfjs-dist/dist/web/pdf_viewer.mjs b/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/templates/AIChatWeb-CSharp/AIChatWeb-CSharp.Web/wwwroot/lib/pdfjs-dist/dist/web/pdf_viewer.mjs
similarity index 100%
rename from src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/ChatWithCustomData-CSharp.Web/wwwroot/lib/pdfjs-dist/dist/web/pdf_viewer.mjs
rename to src/ProjectTemplates/Microsoft.Extensions.AI.Templates/templates/AIChatWeb-CSharp/AIChatWeb-CSharp.Web/wwwroot/lib/pdfjs-dist/dist/web/pdf_viewer.mjs
diff --git a/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/ChatWithCustomData-CSharp.Web/wwwroot/lib/tailwindcss/README.md b/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/templates/AIChatWeb-CSharp/AIChatWeb-CSharp.Web/wwwroot/lib/tailwindcss/README.md
similarity index 100%
rename from src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/ChatWithCustomData-CSharp.Web/wwwroot/lib/tailwindcss/README.md
rename to src/ProjectTemplates/Microsoft.Extensions.AI.Templates/templates/AIChatWeb-CSharp/AIChatWeb-CSharp.Web/wwwroot/lib/tailwindcss/README.md
diff --git a/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/ChatWithCustomData-CSharp.Web/wwwroot/lib/tailwindcss/dist/preflight.css b/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/templates/AIChatWeb-CSharp/AIChatWeb-CSharp.Web/wwwroot/lib/tailwindcss/dist/preflight.css
similarity index 100%
rename from src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/ChatWithCustomData-CSharp.Web/wwwroot/lib/tailwindcss/dist/preflight.css
rename to src/ProjectTemplates/Microsoft.Extensions.AI.Templates/templates/AIChatWeb-CSharp/AIChatWeb-CSharp.Web/wwwroot/lib/tailwindcss/dist/preflight.css
diff --git a/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/ChatWithCustomData-CSharp.sln.in b/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/templates/AIChatWeb-CSharp/AIChatWeb-CSharp.sln
similarity index 70%
rename from src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/ChatWithCustomData-CSharp.sln.in
rename to src/ProjectTemplates/Microsoft.Extensions.AI.Templates/templates/AIChatWeb-CSharp/AIChatWeb-CSharp.sln
index aa1c261a2a3..0959f5ab945 100644
--- a/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/ChatWithCustomData-CSharp.sln.in
+++ b/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/templates/AIChatWeb-CSharp/AIChatWeb-CSharp.sln
@@ -3,11 +3,11 @@ Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.0.31903.59
MinimumVisualStudioVersion = 10.0.40219.1
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ChatWithCustomData-CSharp.AppHost", "ChatWithCustomData-CSharp.AppHost\ChatWithCustomData-CSharp.AppHost.csproj", "{4DF52F58-4890-4A0A-BC25-5C3D167B3490}"
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AIChatWeb-CSharp.AppHost", "AIChatWeb-CSharp.AppHost\AIChatWeb-CSharp.AppHost.csproj", "{4DF52F58-4890-4A0A-BC25-5C3D167B3490}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ChatWithCustomData-CSharp.ServiceDefaults", "ChatWithCustomData-CSharp.ServiceDefaults\ChatWithCustomData-CSharp.ServiceDefaults.csproj", "{2222CF31-6E3A-42E7-AD3A-A56B14EAD9D0}"
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AIChatWeb-CSharp.ServiceDefaults", "AIChatWeb-CSharp.ServiceDefaults\AIChatWeb-CSharp.ServiceDefaults.csproj", "{2222CF31-6E3A-42E7-AD3A-A56B14EAD9D0}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ChatWithCustomData-CSharp.Web", "ChatWithCustomData-CSharp.Web\ChatWithCustomData-CSharp.Web.csproj", "{A7D19173-F0AD-4A8D-B8EA-E12DE203E409}"
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AIChatWeb-CSharp.Web", "AIChatWeb-CSharp.Web\AIChatWeb-CSharp.Web.csproj", "{A7D19173-F0AD-4A8D-B8EA-E12DE203E409}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
diff --git a/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/README.Aspire.md b/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/templates/AIChatWeb-CSharp/README.Aspire.md
similarity index 91%
rename from src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/README.Aspire.md
rename to src/ProjectTemplates/Microsoft.Extensions.AI.Templates/templates/AIChatWeb-CSharp/README.Aspire.md
index f30fcbfcf2e..0fff810489c 100644
--- a/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/ChatWithCustomData/README.Aspire.md
+++ b/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/templates/AIChatWeb-CSharp/README.Aspire.md
@@ -27,7 +27,7 @@ To use models hosted by GitHub Models, you will need to create a GitHub personal
#### ---#if (hostIdentifier == "vs")
Configure your token for this project using .NET User Secrets:
-1. In Visual Studio, right-click on the ChatWithCustomData-CSharp.AppHost project in the Solution Explorer and select "Manage User Secrets".
+1. In Visual Studio, right-click on the AIChatWeb-CSharp.AppHost project in the Solution Explorer and select "Manage User Secrets".
2. This opens a `secrets.json` file where you can store your API keys without them being tracked in source control. Add the following key and value:
```json
@@ -39,7 +39,7 @@ Configure your token for this project using .NET User Secrets:
From the command line, configure your token for this project using .NET User Secrets by running the following commands:
```sh
-cd ChatWithCustomData-CSharp.AppHost
+cd AIChatWeb-CSharp.AppHost
dotnet user-secrets set ConnectionStrings:openai "Endpoint=https://models.inference.ai.azure.com;Key=YOUR-API-KEY"
```
#### ---#endif
@@ -54,7 +54,7 @@ To call the OpenAI REST API, you will need an API key. To obtain one, first [cre
#### ---#if (hostIdentifier == "vs")
Configure your API key for this project, using .NET User Secrets:
-1. In Visual Studio, right-click on the ChatWithCustomData-CSharp.AppHost project in the Solution Explorer and select "Manage User Secrets".
+1. In Visual Studio, right-click on the AIChatWeb-CSharp.AppHost project in the Solution Explorer and select "Manage User Secrets".
2. This will open a secrets.json file where you can store your API key without them being tracked in source control. Add the following key and value to the file:
```json
@@ -67,7 +67,7 @@ Configure your API key for this project, using .NET User Secrets:
From the command line, configure your API key for this project using .NET User Secrets by running the following commands:
```sh
-cd ChatWithCustomData-CSharp.AppHost
+cd AIChatWeb-CSharp.AppHost
dotnet user-secrets set ConnectionStrings:openai "Key=YOUR-API-KEY"
```
#### ---#endif
@@ -108,7 +108,7 @@ Note: Qdrant and Docker are excellent open source products, but are not maintain
1. Open the project folder in Visual Studio Code.
2. Install the [C# Dev Kit extension](https://marketplace.visualstudio.com/items?itemName=ms-dotnettools.csdevkit) for Visual Studio Code.
-3. Once installed, Open the `Program.cs` file in the ChatWithCustomData-CSharp.AppHost project.
+3. Once installed, Open the `Program.cs` file in the AIChatWeb-CSharp.AppHost project.
4. Run the project by clicking the "Run" button in the Debug view.
## Trust the localhost certificate
@@ -119,7 +119,7 @@ See [Troubleshoot untrusted localhost certificate in Aspire](https://learn.micro
# Updating JavaScript dependencies
-This template leverages JavaScript libraries to provide essential functionality. These libraries are located in the wwwroot/lib folder of the ChatWithCustomData-CSharp.Web project. For instructions on updating each dependency, please refer to the README.md file in each respective folder.
+This template leverages JavaScript libraries to provide essential functionality. These libraries are located in the wwwroot/lib folder of the AIChatWeb-CSharp.Web project. For instructions on updating each dependency, please refer to the README.md file in each respective folder.
# Learn More
To learn more about development with .NET and AI, check out the following links:
diff --git a/src/ProjectTemplates/Microsoft.McpServer.ProjectTemplates/Microsoft.McpServer.ProjectTemplates.csproj b/src/ProjectTemplates/Microsoft.McpServer.ProjectTemplates/Microsoft.McpServer.ProjectTemplates.csproj
new file mode 100644
index 00000000000..d13bce3c597
--- /dev/null
+++ b/src/ProjectTemplates/Microsoft.McpServer.ProjectTemplates/Microsoft.McpServer.ProjectTemplates.csproj
@@ -0,0 +1,47 @@
+
+
+
+ Template
+ netstandard2.0
+ MCP Server project templates.
+ dotnet-new;templates;ai
+
+ preview
+
+
+ 0
+ 5
+ 0
+ preview
+ 1
+
+ AI
+ 0
+ 0
+
+ true
+ false
+ true
+ false
+ false
+ content
+ false
+ true
+ true
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/ProjectTemplates/Microsoft.McpServer.ProjectTemplates/README.md b/src/ProjectTemplates/Microsoft.McpServer.ProjectTemplates/README.md
new file mode 100644
index 00000000000..c8d71cb61fd
--- /dev/null
+++ b/src/ProjectTemplates/Microsoft.McpServer.ProjectTemplates/README.md
@@ -0,0 +1,3 @@
+# Microsoft.McpServer.ProjectTemplates
+
+Provides MCP Server Project Templates.
diff --git a/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/McpServer/McpServer-CSharp/.template.config/dotnetcli.host.json b/src/ProjectTemplates/Microsoft.McpServer.ProjectTemplates/templates/McpServer-CSharp/.template.config/dotnetcli.host.json
similarity index 66%
rename from src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/McpServer/McpServer-CSharp/.template.config/dotnetcli.host.json
rename to src/ProjectTemplates/Microsoft.McpServer.ProjectTemplates/templates/McpServer-CSharp/.template.config/dotnetcli.host.json
index 64694e46660..c2105a0018c 100644
--- a/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/McpServer/McpServer-CSharp/.template.config/dotnetcli.host.json
+++ b/src/ProjectTemplates/Microsoft.McpServer.ProjectTemplates/templates/McpServer-CSharp/.template.config/dotnetcli.host.json
@@ -1,13 +1,9 @@
{
"$schema": "https://json.schemastore.org/dotnetcli.host",
"symbolInfo": {
- "TargetFrameworkOverride": {
- "isHidden": "true",
- "longName": "target-framework-override",
- "shortName": ""
- },
- "Framework": {
- "longName": "framework"
+ "Transport": {
+ "longName": "transport",
+ "shortName": "t"
},
"NativeAot": {
"longName": "aot",
@@ -16,6 +12,15 @@
"SelfContained": {
"longName": "self-contained",
"shortName": ""
+ },
+ "Framework": {
+ "longName": "framework"
+ },
+ "httpPort": {
+ "isHidden": true
+ },
+ "httpsPort": {
+ "isHidden": true
}
},
"usageExamples": [
diff --git a/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/McpServer/McpServer-CSharp/.template.config/ide.host.json b/src/ProjectTemplates/Microsoft.McpServer.ProjectTemplates/templates/McpServer-CSharp/.template.config/ide.host.json
similarity index 79%
rename from src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/McpServer/McpServer-CSharp/.template.config/ide.host.json
rename to src/ProjectTemplates/Microsoft.McpServer.ProjectTemplates/templates/McpServer-CSharp/.template.config/ide.host.json
index 8574a4767a5..a4971fdf7fc 100644
--- a/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/McpServer/McpServer-CSharp/.template.config/ide.host.json
+++ b/src/ProjectTemplates/Microsoft.McpServer.ProjectTemplates/templates/McpServer-CSharp/.template.config/ide.host.json
@@ -3,6 +3,10 @@
"order": 0,
"icon": "ide/icon.ico",
"symbolInfo": [
+ {
+ "id": "Transport",
+ "isVisible": true
+ },
{
"id": "NativeAot",
"isVisible": true
diff --git a/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/McpServer/McpServer-CSharp/.template.config/ide/icon.ico b/src/ProjectTemplates/Microsoft.McpServer.ProjectTemplates/templates/McpServer-CSharp/.template.config/ide/icon.ico
similarity index 100%
rename from src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/McpServer/McpServer-CSharp/.template.config/ide/icon.ico
rename to src/ProjectTemplates/Microsoft.McpServer.ProjectTemplates/templates/McpServer-CSharp/.template.config/ide/icon.ico
diff --git a/src/ProjectTemplates/Microsoft.McpServer.ProjectTemplates/templates/McpServer-CSharp/.template.config/template.json b/src/ProjectTemplates/Microsoft.McpServer.ProjectTemplates/templates/McpServer-CSharp/.template.config/template.json
new file mode 100644
index 00000000000..74ea40a826e
--- /dev/null
+++ b/src/ProjectTemplates/Microsoft.McpServer.ProjectTemplates/templates/McpServer-CSharp/.template.config/template.json
@@ -0,0 +1,210 @@
+{
+ "$schema": "http://json.schemastore.org/template",
+ "author": "Microsoft",
+ "classifications": [
+ "Common",
+ "AI",
+ "MCP"
+ ],
+ "identity": "Microsoft.McpServer.ProjectTemplates.McpServer.CSharp",
+ "name": "MCP Server App",
+ "description": "A project template for creating a Model Context Protocol (MCP) server using C# and the ModelContextProtocol package.",
+ "shortName": "mcpserver",
+ "defaultName": "McpServer",
+ "sourceName": "McpServer-CSharp",
+ "preferNameDirectory": true,
+ "tags": {
+ "language": "C#",
+ "type": "project"
+ },
+ "guids": [
+ "aaaaaaaa-bbbb-cccc-dddd-eeeeeeffffff"
+ ],
+ "symbols": {
+ "hostIdentifier": {
+ "type": "bind",
+ "binding": "HostIdentifier"
+ },
+ "Transport": {
+ "type": "parameter",
+ "displayName": "The MCP server _transport type to use",
+ "description": "Whether to create a 'local' (stdio transport) or 'remote' (http transport) MCP server",
+ "datatype": "choice",
+ "choices": [
+ {
+ "choice": "local",
+ "description": "A console application will be created to use the stdio transport as a local MCP server"
+ },
+ {
+ "choice": "remote",
+ "description": "An ASP.NET Core web application will be created to use the http transport as a remote MCP server"
+ }
+ ],
+ "defaultValue": "local"
+ },
+ "NativeAot": {
+ "type": "parameter",
+ "datatype": "bool",
+ "defaultValue": "false",
+ "displayName": "Enable _native AOT publish",
+ "description": "Whether to enable the MCP server for publishing as a native AOT application."
+ },
+ "SelfContained": {
+ "type": "parameter",
+ "datatype": "bool",
+ "defaultValue": "true",
+ "displayName": "Enable _self-contained publish",
+ "description": "Whether to enable the MCP server for publishing as a self-contained application."
+ },
+ "Framework": {
+ "type": "parameter",
+ "description": "The target framework for the project.",
+ "displayName": "Framework",
+ "datatype": "choice",
+ "choices": [
+ {
+ "choice": "net10.0",
+ "description": ".NET 10"
+ },
+ {
+ "choice": "net9.0",
+ "description": ".NET 9"
+ },
+ {
+ "choice": "net8.0",
+ "description": ".NET 8"
+ }
+ ],
+ "replaces": "net10.0",
+ "defaultValue": "net10.0"
+ },
+ "httpsPort": {
+ "type": "parameter",
+ "datatype": "integer",
+ "description": "Port number to use for the HTTPS endpoint in launchSettings.json."
+ },
+ "httpsPortGenerated": {
+ "type": "generated",
+ "generator": "port",
+ "parameters": {
+ "low": 5000,
+ "high": 5300
+ }
+ },
+ "httpsPortReplacer": {
+ "type": "generated",
+ "generator": "coalesce",
+ "parameters": {
+ "sourceVariableName": "httpsPort",
+ "fallbackVariableName": "httpsPortGenerated"
+ },
+ "replaces": "9995",
+ "onlyIf": [{
+ "after": "localhost:"
+ }]
+ },
+ "httpPort": {
+ "type": "parameter",
+ "datatype": "integer",
+ "description": "Port number to use for the HTTP endpoint in launchSettings.json."
+ },
+ "httpPortGenerated": {
+ "type": "generated",
+ "generator": "port",
+ "parameters": {
+ "low": 6000,
+ "high": 6300
+ }
+ },
+ "httpPortReplacer": {
+ "type": "generated",
+ "generator": "coalesce",
+ "parameters": {
+ "sourceVariableName": "httpPort",
+ "fallbackVariableName": "httpPortGenerated"
+ },
+ "replaces": "9996",
+ "onlyIf": [{
+ "after": "localhost:"
+ }]
+ },
+ "IsTransportRemote": {
+ "type": "computed",
+ "value": "(Transport == \"remote\")"
+ },
+ "IsTransportLocal": {
+ "type": "computed",
+ "value": "(!IsTransportRemote)"
+ }
+ },
+ "primaryOutputs": [
+ {
+ "path": "./README.md"
+ },
+ {
+ "path": "./McpServer-CSharp.csproj"
+ }
+ ],
+ "sources": [
+ {
+ "source": "./common",
+ "target": "./"
+ },
+ {
+ "condition": "(IsTransportLocal)",
+ "source": "./local",
+ "target": "./"
+ },
+ {
+ "condition": "(IsTransportRemote)",
+ "source": "./remote",
+ "target": "./"
+ }
+ ],
+ "postActions": [
+ {
+ "condition": "(hostIdentifier != \"dotnetcli\" && hostIdentifier != \"dotnetcli-preview\")",
+ "description": "Opens README file in the editor",
+ "manualInstructions": [],
+ "actionId": "84C0DA21-51C8-4541-9940-6CA19AF04EE6",
+ "args": {
+ "files": "0"
+ },
+ "continueOnError": true
+ }
+ ],
+ "SpecialCustomOperations": {
+ "**/*.md": {
+ "operations": [
+ {
+ "type": "conditional",
+ "configuration": {
+ "if": [ "#### ---#if" ],
+ "else": [ "#### ---#else" ],
+ "elseif": [ "#### ---#elseif", "#### ---#elif" ],
+ "endif": [ "#### ---#endif" ],
+ "trim": "true",
+ "wholeLine": "true",
+ "evaluator": "C++"
+ }
+ }
+ ]
+ },
+ "**/*.http": {
+ "operations": [
+ {
+ "type": "conditional",
+ "configuration": {
+ "if": [ "#if" ],
+ "else": [ "#else" ],
+ "elseif": [ "#elseif", "#elif" ],
+ "endif": [ "#endif" ],
+ "trim": "true",
+ "wholeLine": "true",
+ "evaluator": "C++"
+ }
+ }
+ ]
+ }
+ }
+}
diff --git a/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/McpServer/McpServer-CSharp/Tools/RandomNumberTools.cs b/src/ProjectTemplates/Microsoft.McpServer.ProjectTemplates/templates/McpServer-CSharp/common/Tools/RandomNumberTools.cs
similarity index 100%
rename from src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/McpServer/McpServer-CSharp/Tools/RandomNumberTools.cs
rename to src/ProjectTemplates/Microsoft.McpServer.ProjectTemplates/templates/McpServer-CSharp/common/Tools/RandomNumberTools.cs
diff --git a/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/McpServer/McpServer-CSharp/.mcp/server.json b/src/ProjectTemplates/Microsoft.McpServer.ProjectTemplates/templates/McpServer-CSharp/local/.mcp/server.json
similarity index 100%
rename from src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/McpServer/McpServer-CSharp/.mcp/server.json
rename to src/ProjectTemplates/Microsoft.McpServer.ProjectTemplates/templates/McpServer-CSharp/local/.mcp/server.json
diff --git a/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/McpServer/McpServer-CSharp/McpServer-CSharp.csproj.in b/src/ProjectTemplates/Microsoft.McpServer.ProjectTemplates/templates/McpServer-CSharp/local/McpServer-CSharp.csproj-in
similarity index 85%
rename from src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/McpServer/McpServer-CSharp/McpServer-CSharp.csproj.in
rename to src/ProjectTemplates/Microsoft.McpServer.ProjectTemplates/templates/McpServer-CSharp/local/McpServer-CSharp.csproj-in
index 799d5845c32..6105d4d53a9 100644
--- a/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/McpServer/McpServer-CSharp/McpServer-CSharp.csproj.in
+++ b/src/ProjectTemplates/Microsoft.McpServer.ProjectTemplates/templates/McpServer-CSharp/local/McpServer-CSharp.csproj-in
@@ -1,8 +1,7 @@
- net10.0
- TargetFrameworkOverride
+ net10.0win-x64;win-arm64;osx-arm64;linux-x64;linux-arm64;linux-musl-x64
@@ -46,8 +45,8 @@
-
-
+
+
diff --git a/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/McpServer/McpServer-CSharp/Program.cs b/src/ProjectTemplates/Microsoft.McpServer.ProjectTemplates/templates/McpServer-CSharp/local/Program.cs
similarity index 100%
rename from src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/McpServer/McpServer-CSharp/Program.cs
rename to src/ProjectTemplates/Microsoft.McpServer.ProjectTemplates/templates/McpServer-CSharp/local/Program.cs
diff --git a/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/McpServer/McpServer-CSharp/README.md b/src/ProjectTemplates/Microsoft.McpServer.ProjectTemplates/templates/McpServer-CSharp/local/README.md
similarity index 98%
rename from src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/McpServer/McpServer-CSharp/README.md
rename to src/ProjectTemplates/Microsoft.McpServer.ProjectTemplates/templates/McpServer-CSharp/local/README.md
index 95612c5e35e..85da5d0e61f 100644
--- a/src/ProjectTemplates/Microsoft.Extensions.AI.Templates/src/McpServer/McpServer-CSharp/README.md
+++ b/src/ProjectTemplates/Microsoft.McpServer.ProjectTemplates/templates/McpServer-CSharp/local/README.md
@@ -56,6 +56,11 @@ To test this MCP server from source code (locally) without using a built MCP ser
}
```
+Refer to the VS Code or Visual Studio documentation for more information on configuring and using MCP servers:
+
+- [Use MCP servers in VS Code (Preview)](https://code.visualstudio.com/docs/copilot/chat/mcp-servers)
+- [Use MCP servers in Visual Studio (Preview)](https://learn.microsoft.com/visualstudio/ide/mcp-servers)
+
## Testing the MCP Server
Once configured, you can ask Copilot Chat for a random number, for example, `Give me 3 random numbers`. It should prompt you to use the `get_random_number` tool on the `McpServer-CSharp` MCP server and show you the results.
@@ -98,8 +103,4 @@ For both VS Code and Visual Studio, the configuration file uses the following se
- [Official Documentation](https://modelcontextprotocol.io/)
- [Protocol Specification](https://spec.modelcontextprotocol.io/)
- [GitHub Organization](https://github.com/modelcontextprotocol)
-
-Refer to the VS Code or Visual Studio documentation for more information on configuring and using MCP servers:
-
-- [Use MCP servers in VS Code (Preview)](https://code.visualstudio.com/docs/copilot/chat/mcp-servers)
-- [Use MCP servers in Visual Studio (Preview)](https://learn.microsoft.com/visualstudio/ide/mcp-servers)
+- [MCP C# SDK](https://modelcontextprotocol.github.io/csharp-sdk)
diff --git a/src/ProjectTemplates/Microsoft.McpServer.ProjectTemplates/templates/McpServer-CSharp/remote/McpServer-CSharp.csproj-in b/src/ProjectTemplates/Microsoft.McpServer.ProjectTemplates/templates/McpServer-CSharp/remote/McpServer-CSharp.csproj-in
new file mode 100644
index 00000000000..dfeea98e66b
--- /dev/null
+++ b/src/ProjectTemplates/Microsoft.McpServer.ProjectTemplates/templates/McpServer-CSharp/remote/McpServer-CSharp.csproj-in
@@ -0,0 +1,35 @@
+
+
+
+ net10.0
+
+ win-x64;win-arm64;osx-arm64;linux-x64;linux-arm64;linux-musl-x64
+
+ Major
+
+ enable
+ enable
+ aaaaaaaa-bbbb-cccc-dddd-eeeeeeffffff
+
+
+
+
+ true
+ true
+
+
+ true
+
+
+
+
+ true
+ true
+
+
+
+
+
+
+
+
diff --git a/src/ProjectTemplates/Microsoft.McpServer.ProjectTemplates/templates/McpServer-CSharp/remote/McpServer-CSharp.http b/src/ProjectTemplates/Microsoft.McpServer.ProjectTemplates/templates/McpServer-CSharp/remote/McpServer-CSharp.http
new file mode 100644
index 00000000000..f79d8ec1429
--- /dev/null
+++ b/src/ProjectTemplates/Microsoft.McpServer.ProjectTemplates/templates/McpServer-CSharp/remote/McpServer-CSharp.http
@@ -0,0 +1,21 @@
+# For more info on HTTP files go to https://aka.ms/vs/httpfile
+
+#if (hostIdentifier == "vs")
+@HostAddress = https://localhost:9995
+#else
+@HostAddress = http://localhost:9996
+#endif
+
+POST {{HostAddress}}/
+Accept: application/json, text/event-stream
+Content-Type: application/json
+MCP-Protocol-Version: 2025-11-25
+
+{
+ "jsonrpc": "2.0",
+ "id": 1,
+ "method": "tools/call",
+ "params": {
+ "name": "get_random_number"
+ }
+}
diff --git a/src/ProjectTemplates/Microsoft.McpServer.ProjectTemplates/templates/McpServer-CSharp/remote/Program.cs b/src/ProjectTemplates/Microsoft.McpServer.ProjectTemplates/templates/McpServer-CSharp/remote/Program.cs
new file mode 100644
index 00000000000..3a3ce231e69
--- /dev/null
+++ b/src/ProjectTemplates/Microsoft.McpServer.ProjectTemplates/templates/McpServer-CSharp/remote/Program.cs
@@ -0,0 +1,15 @@
+var builder = WebApplication.CreateBuilder(args);
+
+// Add the MCP services: the transport to use (http) and the tools to register.
+builder.Services
+ .AddMcpServer()
+ .WithHttpTransport()
+ .WithTools();
+
+var app = builder.Build();
+app.MapMcp();
+#if (hostIdentifier == "vs")
+app.UseHttpsRedirection();
+#endif
+
+app.Run();
diff --git a/src/ProjectTemplates/Microsoft.McpServer.ProjectTemplates/templates/McpServer-CSharp/remote/Properties/launchSettings.json b/src/ProjectTemplates/Microsoft.McpServer.ProjectTemplates/templates/McpServer-CSharp/remote/Properties/launchSettings.json
new file mode 100644
index 00000000000..37d5661e4de
--- /dev/null
+++ b/src/ProjectTemplates/Microsoft.McpServer.ProjectTemplates/templates/McpServer-CSharp/remote/Properties/launchSettings.json
@@ -0,0 +1,23 @@
+{
+ "$schema": "https://json.schemastore.org/launchsettings.json",
+ "profiles": {
+ "http": {
+ "commandName": "Project",
+ "dotnetRunMessages": true,
+ "launchBrowser": false,
+ "applicationUrl": "http://localhost:9996",
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ },
+ "https": {
+ "commandName": "Project",
+ "dotnetRunMessages": true,
+ "launchBrowser": false,
+ "applicationUrl": "https://localhost:9995;http://localhost:9996",
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ }
+ }
+}
diff --git a/src/ProjectTemplates/Microsoft.McpServer.ProjectTemplates/templates/McpServer-CSharp/remote/README.md b/src/ProjectTemplates/Microsoft.McpServer.ProjectTemplates/templates/McpServer-CSharp/remote/README.md
new file mode 100644
index 00000000000..a8700767510
--- /dev/null
+++ b/src/ProjectTemplates/Microsoft.McpServer.ProjectTemplates/templates/McpServer-CSharp/remote/README.md
@@ -0,0 +1,78 @@
+# MCP Server
+
+This README was created using the C# MCP server project template.
+It demonstrates how you can easily create an MCP server using C# and run it as an ASP.NET Core web application.
+
+#### ---#if (SelfContained)
+The MCP server is built as a self-contained application and does not require the .NET runtime to be installed on the target machine.
+However, since it is self-contained, it must be built for each target platform separately.
+By default, the template is configured to build for:
+* `win-x64`
+* `win-arm64`
+* `osx-arm64`
+* `linux-x64`
+* `linux-arm64`
+* `linux-musl-x64`
+
+If you require more platforms to be supported, update the list of runtime identifiers in the project's `` element.
+#### ---#else
+The MCP server is built as a framework-dependent application and requires the ASP.NET Core runtime to be installed on the target machine.
+The application is configured to roll-forward to the next highest major version of the runtime if one is available on the target machine.
+If an applicable .NET runtime is not available, the MCP server will not start.
+Consider building the MCP server as a self-contained application if you want to avoid this dependency.
+#### ---#endif
+
+Please note that this template is currently in an early preview stage. If you have feedback, please take a [brief survey](http://aka.ms/dotnet-mcp-template-survey).
+
+## Developing locally
+
+To test this MCP server from source code (locally), you can configure your IDE to connect to the server using localhost.
+
+#### ---#if (hostIdentifier == "vs")
+```json
+{
+ "servers": {
+ "McpServer-CSharp": {
+ "type": "http",
+ "url": "https://localhost:9995"
+ }
+ }
+}
+```
+#### ---#else
+```json
+{
+ "servers": {
+ "McpServer-CSharp": {
+ "type": "http",
+ "url": "http://localhost:9996"
+ }
+ }
+}
+```
+#### ---#endif
+
+Refer to the VS Code or Visual Studio documentation for more information on configuring and using MCP servers:
+
+- [Use MCP servers in VS Code (Preview)](https://code.visualstudio.com/docs/copilot/chat/mcp-servers)
+- [Use MCP servers in Visual Studio (Preview)](https://learn.microsoft.com/visualstudio/ide/mcp-servers)
+
+## Testing the MCP Server
+
+Once configured, you can ask Copilot Chat for a random number, for example, `Give me 3 random numbers`. It should prompt you to use the `get_random_number` tool on the `McpServer-CSharp` MCP server and show you the results.
+
+## Known issues
+
+1. When using VS Code, connecting to `https://localhost:9995` fails.
+ * This is related to using a self-signed developer certificate, even when the certificate is trusted by the system.
+ * Connecting with `http://localhost:9996` succeeds.
+ * See [Cannot connect to MCP server via SSE using trusted developer certificate (microsoft/vscode#248170)](https://github.com/microsoft/vscode/issues/248170) for more information.
+
+## More information
+
+ASP.NET Core MCP servers use the [ModelContextProtocol.AspNetCore](https://www.nuget.org/packages/ModelContextProtocol.AspNetCore) package from the MCP C# SDK. For more information about MCP:
+
+- [Official Documentation](https://modelcontextprotocol.io/)
+- [Protocol Specification](https://spec.modelcontextprotocol.io/)
+- [GitHub Organization](https://github.com/modelcontextprotocol)
+- [MCP C# SDK](https://modelcontextprotocol.github.io/csharp-sdk)
diff --git a/src/ProjectTemplates/README.md b/src/ProjectTemplates/README.md
index f527c08d74e..335a3881d96 100644
--- a/src/ProjectTemplates/README.md
+++ b/src/ProjectTemplates/README.md
@@ -2,10 +2,12 @@
## Updating project template JavaScript dependencies
-To update project template JavaScript dependencies:
+The AIChatWeb project template within Microsoft.Extensions.AI.Templates bundles JavaScript dependencies into the package. To update those project template JavaScript dependencies:
+
+1. Navigate into the root of the Microsoft.Extensions.AI.Templates directory
1. Install a recent build of Node.js
2. Update the `package.json` file with added or updated dependencies
-3. Run the following commands from this directory:
+3. Run the following commands:
```sh
npm install
npm run copy-dependencies
@@ -23,7 +25,7 @@ There are template execution tests in the `test/ProjectTemplates` folders that c
However, CG can't detect JS dependencies by scanning execution test output, because the generated projects don't contain manifests describing JS dependencies. Instead, we have a `package.json` and `package-lock.json` in the same folder as this README that define which JS dependencies get included in the template and how they get copied into template content (see previous section in this document). CG then automatically tracks packages listed in this `package-lock.json`.
-## Build the templates using just-built library package versions
+## Build the templates
By default the templates use just-built versions of library packages from this repository, so NuGet packages must be produced before the templates can be run:
@@ -35,24 +37,84 @@ By default the templates use just-built versions of library packages from this r
Once the library packages are built, the template packages can be built with references to the local package versions using the following commands:
```pwsh
-.\build.cmd -pack -projects .\src\ProjectTemplates\Microsoft.Agents.AI.ProjectTemplates\Microsoft.Extensions.AI.Templates.csproj
-.\build.cmd -pack -projects .\src\ProjectTemplates\Microsoft.Extensions.AI.Templates\Microsoft.Extensions.AI.Templates.csproj
+.\build.cmd -build -pack -projects .\src\ProjectTemplates\Microsoft.Agents.AI.ProjectTemplates\Microsoft.Agents.AI.ProjectTemplates.csproj
+.\build.cmd -build -pack -projects .\src\ProjectTemplates\Microsoft.Extensions.AI.Templates\Microsoft.Extensions.AI.Templates.csproj
```
-## Build the templates using pinned library package versions
+## Package references in the project templates
-The templates can also be built to reference pinned versions of the library packages. This approach is used when a templates package is updated off-cycle from the library packages. The pinned versions are hard-coded in the `GeneratedContent.targets` file in this directory. To build the templates package using the pinned versions, run:
+The `Directory.Build.targets` file defines and configures the necessary targets for processing package references in the project template to insert the package versions into the produced `.csproj` files.
-```pwsh
-.\build.cmd -pack -projects .\src\ProjectTemplates\Microsoft.Agents.AI.ProjectTemplates\Microsoft.Agents.AI.ProjectTemplates.csproj /p:TemplateUsePinnedPackageVersions=true
-.\build.cmd -pack -projects .\src\ProjectTemplates\Microsoft.Extensions.AI.Templates\Microsoft.Extensions.AI.Templates.csproj /p:TemplateUsePinnedPackageVersions=true
+Template projects can reference packages either with pinned `` or have versions resolved from projects within the repository using `` items. If both a `` and `` are specified, the version from
+the `` is used.
+
+```xml
+
+
+
+
+
+
+
+
+
+
+
```
-Setting `/p:TemplateUsePinnedPackageVersions=true` will apply three different categories of pinned package versions:
+Files in the template that need to reference the resolved versions must be pre-processed as generated template content. While this works with any text file, it is typically used with `.csproj` files. This is accomplished by:
+
+1. Rename the `.csproj` file to `.csproj-in`
+2. Exclude the `.csproj-in` file from the project ``
+3. Include the `.csproj-in` file in the project's ``
+
+**Project template project**
+```xml
+
+
-1. Packages from this repository that are _not_ part of `Microsoft.Extensions.AI*`, namely `Microsoft.Extensions.Http.Resilience`
-2. Packages from this repository that _are_ part of `Microsoft.Extensions.AI*`
-3. The `Microsoft.EntityFrameworkCoreSqlite` package
+
+
+
+
+```
+
+Note that for the 'ChangeExtension' behavior to work, the extension to be replaced cannot contain a '.'. Therefore, `.csproj.in` cannot be used, which is why `.csproj-in` is used instead. This is true for any extension, so `.md-in` can also be changed to `.md` using this same logic.
+
+**Project template csproj-in file**
+```xml
+
+...
+
+...
+
+...
+
+```
+
+During build, the generated content is saved into the `/artifacts/ProjectTemplates/GeneratedContent` folder, and the generated content is then added as `` included from the artifacts folder.
## Installing the templates locally
@@ -77,20 +139,32 @@ dotnet new install .\artifacts\packages\Debug\Shipping\Microsoft.Extensions.AI.T
Finally, create a project from the template and run it:
```pwsh
-dotnet new aiagent-webapi `
- [--provider ] `
- [--managed-identity]
+ dotnet new aiagent-webapi `
+ [--provider ] `
+ [--managed-identity]
# or
-dotnet new aichatweb `
- [--provider ] `
- [--vector-store ] `
- [--aspire] `
- [--managed-identity]
+ dotnet new aichatweb `
+ [--provider ] `
+ [--vector-store ] `
+ [--aspire] `
+ [--managed-identity]
-# If using `--aspire`, cd into the *AppHost directory
-# Follow the instructions in the generated README for setting the necessary user-secrets
+ # If using `--aspire`, cd into the *AppHost directory
+ # Follow the instructions in the generated README for setting the necessary user-secrets
+
+# or
+
+ dotnet new mcpserver [--aot] [--self-contained]
dotnet run
```
+
+## Cleaning ProjectTemplate build output
+
+Running the `clean` target for a Project Template project will remove its entire artifacts folder. This includes:
+
+- `/artifacts/ProjectTemplates//GeneratedContent` (generated template content files)
+- `/artifacts/ProjectTemplates//Sandbox` (execution test sandbox)
+- `/artifacts/ProjectTemplates//Snapshots` (snapshot test output)
diff --git a/test/Directory.Build.props b/test/Directory.Build.props
index 09ea86b52b4..f886872fa3d 100644
--- a/test/Directory.Build.props
+++ b/test/Directory.Build.props
@@ -1,8 +1,8 @@
-
-
+
false
+ $(NoWarn);RT0000
diff --git a/test/Directory.Build.targets b/test/Directory.Build.targets
index ddaf65de061..8cddc800bac 100644
--- a/test/Directory.Build.targets
+++ b/test/Directory.Build.targets
@@ -14,8 +14,4 @@
-
-
- $(NoWarn);RT0000
-
diff --git a/test/Directory.Packages.props b/test/Directory.Packages.props
new file mode 100644
index 00000000000..010335bc108
--- /dev/null
+++ b/test/Directory.Packages.props
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/test/ProjectTemplates/.gitignore b/test/ProjectTemplates/.gitignore
deleted file mode 100644
index 6fbeae3c400..00000000000
--- a/test/ProjectTemplates/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-*/ExecutionTestSandbox
diff --git a/test/ProjectTemplates/Infrastructure/TemplateExecutionTestBase.cs b/test/ProjectTemplates/Infrastructure/TemplateExecutionTestBase.cs
index 430f731e0c8..188f5022fd1 100644
--- a/test/ProjectTemplates/Infrastructure/TemplateExecutionTestBase.cs
+++ b/test/ProjectTemplates/Infrastructure/TemplateExecutionTestBase.cs
@@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.
using System;
+using System.Threading.Tasks;
using Xunit;
using Xunit.Abstractions;
@@ -29,6 +30,18 @@ protected TemplateExecutionTestBase(TemplateExecutionTestFixture fixture, ITestO
OutputHelper = outputHelper;
}
+ protected async Task CreateRestoreAndBuild(string projectName, string[] args, string? startupProjectRelativePath = null)
+ {
+ var project = await Fixture.CreateProjectAsync(
+ TConfiguration.Configuration.TemplateName,
+ projectName,
+ startupProjectRelativePath,
+ args);
+
+ await Fixture.RestoreProjectAsync(project);
+ await Fixture.BuildProjectAsync(project);
+ }
+
protected virtual void Dispose(bool disposing)
{
if (_disposed)
diff --git a/test/ProjectTemplates/Infrastructure/TemplateExecutionTestClassFixtureBase.cs b/test/ProjectTemplates/Infrastructure/TemplateExecutionTestClassFixtureBase.cs
index 9144593db73..4c9939d960a 100644
--- a/test/ProjectTemplates/Infrastructure/TemplateExecutionTestClassFixtureBase.cs
+++ b/test/ProjectTemplates/Infrastructure/TemplateExecutionTestClassFixtureBase.cs
@@ -15,9 +15,12 @@ namespace Microsoft.Shared.ProjectTemplates.Tests;
///
public abstract class TemplateExecutionTestClassFixtureBase : IAsyncLifetime
{
- private readonly TemplateExecutionTestConfiguration _configuration;
- private readonly string _templateTestOutputPath;
- private readonly string _customHivePath;
+ private readonly string _templatePackageName;
+ private readonly string _sandboxPackages;
+ private readonly string _sandboxOutput;
+ private readonly string _sandboxInstallPath;
+ private readonly string _sandboxProjectsPath;
+
private readonly MessageSinkTestOutputHelper _messageSinkTestOutputHelper;
private ITestOutputHelper? _currentTestOutputHelper;
@@ -30,46 +33,66 @@ public abstract class TemplateExecutionTestClassFixtureBase : IAsyncLifetime
protected TemplateExecutionTestClassFixtureBase(TemplateExecutionTestConfiguration configuration, IMessageSink messageSink)
{
- _configuration = configuration;
_messageSinkTestOutputHelper = new(messageSink);
- var outputFolderName = GetRandomizedFileName(prefix: _configuration.TestOutputFolderPrefix);
- _templateTestOutputPath = Path.Combine(WellKnownPaths.TemplateSandboxOutputRoot, outputFolderName);
- _customHivePath = Path.Combine(_templateTestOutputPath, "hive");
- }
+ _templatePackageName = configuration.TemplatePackageName;
+ _sandboxPackages = configuration.TemplateSandboxPackages;
+ _sandboxOutput = configuration.TemplateSandboxOutput;
- private static string GetRandomizedFileName(string prefix)
- => prefix + "_" + Guid.NewGuid().ToString("N").Substring(0, 10).ToLowerInvariant();
+ _sandboxInstallPath = Path.Combine(_sandboxOutput, "install");
+ _sandboxProjectsPath = Path.Combine(_sandboxOutput, "projects");
+ }
public async Task InitializeAsync()
{
- Directory.CreateDirectory(_templateTestOutputPath);
+ // Here, we clear execution test output from the previous test run, if it exists.
+ // It's critical that this clearing happens *before* the tests start, *not* after they complete.
+ //
+ // This is because:
+ // 1. This enables debugging the previous test run by building/running generated projects manually.
+ // 2. The existence of a project.assets.json file on disk is what allows template content to get discovered
+ // for component governance reporting.
+ // Copy the template sandbox infrastructure to the output location for use during tests
+ CopySandboxDirectory(WellKnownPaths.TemplateSandboxSource, _sandboxOutput);
+
+ var installResult = await new DotNetNewCommand("install", _templatePackageName)
+ .WithWorkingDirectory(_sandboxInstallPath)
+ .WithEnvironmentVariable("LOCAL_SHIPPING_PATH", WellKnownPaths.LocalShippingPackagesPath)
+ .WithEnvironmentVariable("NUGET_PACKAGES", _sandboxPackages)
+ .WithCustomHive(_sandboxInstallPath)
+ .ExecuteAsync(OutputHelper);
+
+ installResult.AssertSucceeded($"dotnet new install {_templatePackageName}");
- await InstallTemplatesAsync();
+ // Create the sub-directory for the generated projects
+ Directory.CreateDirectory(_sandboxProjectsPath);
+ }
- async Task InstallTemplatesAsync()
+ private static void CopySandboxDirectory(string sandboxSource, string testSandbox)
+ {
+ if (Directory.Exists(testSandbox))
{
- var installSandboxPath = Path.Combine(_templateTestOutputPath, "install");
- Directory.CreateDirectory(installSandboxPath);
+ Directory.Delete(testSandbox, recursive: true);
+ }
- var installNuGetConfigPath = Path.Combine(installSandboxPath, "nuget.config");
- File.Copy(WellKnownPaths.TemplateInstallNuGetConfigPath, installNuGetConfigPath);
+ Directory.CreateDirectory(testSandbox);
- var installResult = await new DotNetNewCommand("install", _configuration.TemplatePackageName)
- .WithWorkingDirectory(installSandboxPath)
- .WithEnvironmentVariable("LOCAL_SHIPPING_PATH", WellKnownPaths.LocalShippingPackagesPath)
- .WithEnvironmentVariable("NUGET_PACKAGES", WellKnownPaths.NuGetPackagesPath)
- .WithCustomHive(_customHivePath)
- .ExecuteAsync(OutputHelper);
+ var source = new DirectoryInfo(sandboxSource);
- installResult.AssertSucceeded($"dotnet new install {_configuration.TemplatePackageName}");
+ foreach (FileInfo file in source.GetFiles())
+ {
+ file.CopyTo(Path.Combine(testSandbox, file.Name));
+ }
+
+ foreach (DirectoryInfo subDir in source.GetDirectories())
+ {
+ CopySandboxDirectory(subDir.FullName, Path.Combine(testSandbox, subDir.Name));
}
}
- public async Task CreateProjectAsync(string templateName, string projectName, params string[] args)
+ public async Task CreateProjectAsync(string templateName, string projectName, string? startupProjectRelativePath, params string[] args)
{
- var outputFolderName = GetRandomizedFileName(projectName);
- var outputFolderPath = Path.Combine(_templateTestOutputPath, outputFolderName);
+ var outputFolderPath = Path.Combine(_sandboxProjectsPath, projectName);
ReadOnlySpan dotNetNewCommandArgs = [
templateName,
@@ -82,16 +105,13 @@ .. args
var testDescription = string.Join(' ', dotNetNewCommandArgs);
var newProjectResult = await new DotNetNewCommand(dotNetNewCommandArgs)
- .WithWorkingDirectory(_templateTestOutputPath)
- .WithCustomHive(_customHivePath)
+ .WithWorkingDirectory(_sandboxProjectsPath)
+ .WithCustomHive(_sandboxInstallPath)
.ExecuteAsync(OutputHelper);
newProjectResult.AssertSucceeded(testDescription);
- var templateNuGetConfigPath = Path.Combine(outputFolderPath, "nuget.config");
- File.Copy(WellKnownPaths.TemplateTestNuGetConfigPath, templateNuGetConfigPath);
-
- return new Project(outputFolderPath, projectName);
+ return new Project(outputFolderPath, projectName) { StartupProjectRelativePath = startupProjectRelativePath };
}
public async Task RestoreProjectAsync(Project project)
@@ -99,7 +119,7 @@ public async Task RestoreProjectAsync(Project project)
var restoreResult = await new DotNetCommand("restore")
.WithWorkingDirectory(project.StartupProjectFullPath)
.WithEnvironmentVariable("LOCAL_SHIPPING_PATH", WellKnownPaths.LocalShippingPackagesPath)
- .WithEnvironmentVariable("NUGET_PACKAGES", WellKnownPaths.NuGetPackagesPath)
+ .WithEnvironmentVariable("NUGET_PACKAGES", _sandboxPackages)
.ExecuteAsync(OutputHelper);
restoreResult.AssertSucceeded($"""
@@ -107,7 +127,7 @@ dotnet restore
Working Directory: {project.StartupProjectFullPath}
Local Shipping Path: {WellKnownPaths.LocalShippingPackagesPath}
- NuGet Packages Path: {WellKnownPaths.NuGetPackagesPath}
+ NuGet Packages Path: {_sandboxPackages}
""");
}
diff --git a/test/ProjectTemplates/Infrastructure/TemplateExecutionTestCollection.cs b/test/ProjectTemplates/Infrastructure/TemplateExecutionTestCollection.cs
index dfabfb9a089..608b51eac07 100644
--- a/test/ProjectTemplates/Infrastructure/TemplateExecutionTestCollection.cs
+++ b/test/ProjectTemplates/Infrastructure/TemplateExecutionTestCollection.cs
@@ -6,7 +6,7 @@
namespace Microsoft.Shared.ProjectTemplates.Tests;
[CollectionDefinition(name: Name)]
-public sealed class TemplateExecutionTestCollection : ICollectionFixture
+public sealed class TemplateExecutionTestCollection
{
public const string Name = "Template execution test";
}
diff --git a/test/ProjectTemplates/Infrastructure/TemplateExecutionTestCollectionFixture.cs b/test/ProjectTemplates/Infrastructure/TemplateExecutionTestCollectionFixture.cs
deleted file mode 100644
index 3b015d80202..00000000000
--- a/test/ProjectTemplates/Infrastructure/TemplateExecutionTestCollectionFixture.cs
+++ /dev/null
@@ -1,39 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-using System.IO;
-
-namespace Microsoft.Shared.ProjectTemplates.Tests;
-
-///
-/// Provides functionality scoped to the lifetime of all tests defined in
-/// test classes extending .
-///
-public sealed class TemplateExecutionTestCollectionFixture
-{
- public TemplateExecutionTestCollectionFixture()
- {
- // Here, we clear execution test output from the previous test run, if it exists.
- //
- // It's critical that this clearing happens *before* the tests start, *not* after they complete.
- //
- // This is because:
- // 1. This enables debugging the previous test run by building/running generated projects manually.
- // 2. The existence of a project.assets.json file on disk is what allows template content to get discovered
- // for component governance reporting.
- if (Directory.Exists(WellKnownPaths.TemplateSandboxOutputRoot))
- {
- Directory.Delete(WellKnownPaths.TemplateSandboxOutputRoot, recursive: true);
- }
-
- // Then we copy the template sandbox infrastructure to the output location for use during tests.
- Directory.CreateDirectory(WellKnownPaths.TemplateSandboxOutputRoot);
-
- foreach (var filePath in Directory.EnumerateFiles(WellKnownPaths.TemplateSandboxSource))
- {
- var fileName = Path.GetFileName(filePath);
- var destFilePath = Path.Combine(WellKnownPaths.TemplateSandboxOutputRoot, fileName);
- File.Copy(filePath, destFilePath);
- }
- }
-}
diff --git a/test/ProjectTemplates/Infrastructure/TemplateExecutionTestConfiguration.cs b/test/ProjectTemplates/Infrastructure/TemplateExecutionTestConfiguration.cs
index 060f28fe368..cf6bb3e5934 100644
--- a/test/ProjectTemplates/Infrastructure/TemplateExecutionTestConfiguration.cs
+++ b/test/ProjectTemplates/Infrastructure/TemplateExecutionTestConfiguration.cs
@@ -1,11 +1,16 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
+using System.IO;
+
namespace Microsoft.Shared.ProjectTemplates.Tests;
public sealed class TemplateExecutionTestConfiguration
{
public required string TemplatePackageName { get; init; }
+ public required string TemplateName { get; init; }
- public required string TestOutputFolderPrefix { get; init; }
+ private string TemplateSandboxRoot => Path.Combine(WellKnownPaths.ProjectTemplatesArtifactsRoot, TemplatePackageName, "Sandbox");
+ public string TemplateSandboxPackages => Path.Combine(TemplateSandboxRoot, "packages");
+ public string TemplateSandboxOutput => Path.Combine(TemplateSandboxRoot, TemplateName);
}
diff --git a/test/ProjectTemplates/Infrastructure/TemplateSandbox/README.md b/test/ProjectTemplates/Infrastructure/TemplateSandbox/README.md
index 6a9ecb84b86..839ee778551 100644
--- a/test/ProjectTemplates/Infrastructure/TemplateSandbox/README.md
+++ b/test/ProjectTemplates/Infrastructure/TemplateSandbox/README.md
@@ -17,15 +17,16 @@ Template tests can be debugged either in VS or by running `dotnet test`.
However, it's sometimes helpful to debug failures by building, running, and modifying the generated projects directly instead of tinkering with test code.
To help with this scenario:
-* The `ExecutionTestSandbox` folder containing the generated projects doesn't get cleared until the start of the next test run.
+* The `/artifacts/ProjectTemplates/Sandbox/` folder containing the generated projects doesn't get cleared until the start of the next test run.
* An `activate.ps1` script can be used to simulate the environment that the template execution tests use. This script:
* Sets the active .NET installation to `/.dotnet`.
- * Sets the `NUGET_PACKAGES` environment variable to the `ExecutionTestSandbox/packages` folder to use the isolated package cache.
+ * Sets the `NUGET_PACKAGES` environment variable to the `/artifacts/ProjectTemplates/Sandbox//packages` folder to use the isolated package cache.
* Sets a `LOCAL_SHIPPING_PATH` environment variable so that locally-built packages can get picked up during restore.
As an example, here's how you can build a project generated by the tests:
```sh
+cd /artifacts/ProjectTemplates/Sandbox/
. ./activate.ps1
-cd ./[test_collection]/[generated_template]
+cd .//
dotnet build
```
diff --git a/test/ProjectTemplates/Infrastructure/TemplateSandbox/nuget.template_install.config b/test/ProjectTemplates/Infrastructure/TemplateSandbox/install/nuget.config
similarity index 100%
rename from test/ProjectTemplates/Infrastructure/TemplateSandbox/nuget.template_install.config
rename to test/ProjectTemplates/Infrastructure/TemplateSandbox/install/nuget.config
diff --git a/test/ProjectTemplates/Infrastructure/TemplateSandbox/Directory.Build.props b/test/ProjectTemplates/Infrastructure/TemplateSandbox/projects/Directory.Build.props
similarity index 100%
rename from test/ProjectTemplates/Infrastructure/TemplateSandbox/Directory.Build.props
rename to test/ProjectTemplates/Infrastructure/TemplateSandbox/projects/Directory.Build.props
diff --git a/test/ProjectTemplates/Infrastructure/TemplateSandbox/Directory.Build.targets b/test/ProjectTemplates/Infrastructure/TemplateSandbox/projects/Directory.Build.targets
similarity index 100%
rename from test/ProjectTemplates/Infrastructure/TemplateSandbox/Directory.Build.targets
rename to test/ProjectTemplates/Infrastructure/TemplateSandbox/projects/Directory.Build.targets
diff --git a/test/ProjectTemplates/Infrastructure/TemplateSandbox/nuget.template_test.config b/test/ProjectTemplates/Infrastructure/TemplateSandbox/projects/nuget.config
similarity index 100%
rename from test/ProjectTemplates/Infrastructure/TemplateSandbox/nuget.template_test.config
rename to test/ProjectTemplates/Infrastructure/TemplateSandbox/projects/nuget.config
diff --git a/test/ProjectTemplates/Infrastructure/TemplateSnapshotTestBase.cs b/test/ProjectTemplates/Infrastructure/TemplateSnapshotTestBase.cs
new file mode 100644
index 00000000000..d716d0d5d8b
--- /dev/null
+++ b/test/ProjectTemplates/Infrastructure/TemplateSnapshotTestBase.cs
@@ -0,0 +1,53 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System;
+using System.IO;
+using System.Linq;
+using Microsoft.TemplateEngine.Authoring.TemplateVerifier;
+
+namespace Microsoft.Shared.ProjectTemplates.Tests;
+
+public abstract class TemplateSnapshotTestBase
+{
+ protected virtual TemplateVerifierOptions PrepareSnapshotVerifier(
+ string projectNamePrefix,
+ string templatePackageName,
+ string templateName,
+ string[] templateArgs,
+ string[]? verificationExcludePatterns = null)
+ {
+ // TemplateVerifierOptions.DoNotPrependTemplateNameToScenarioName results in a '_' prefix.
+ // So skip setting a prefix here and let TemplateVerifier use the template name prefix.
+ string scenarioName = TemplateTestUtilities.GetProjectNameForArgs(templateArgs);
+
+ // Create a working directory using the same prefixing approach as the TemplateVerifier
+ // to improve the debugging experience
+ string workingDir = Path.Combine(WellKnownPaths.ProjectTemplatesArtifactsRoot, templatePackageName, "Snapshots", templateName, $"{templateName}.{scenarioName}");
+
+ // Ensure the working directory is clean
+ if (Directory.Exists(workingDir))
+ {
+ Directory.Delete(workingDir, recursive: true);
+ }
+
+ // Get the template location from the template package. Use a wildcard for the version number in the file name.
+ string templateLocation = Path.Combine(WellKnownPaths.LocalShippingPackagesPath, $"{templatePackageName}.*.nupkg");
+
+ string[]? excludePatterns = Path.DirectorySeparatorChar is '/'
+ ? verificationExcludePatterns
+ : verificationExcludePatterns?.Select(p => p.Replace('/', Path.DirectorySeparatorChar)).ToArray();
+
+ return new TemplateVerifierOptions(templateName)
+ {
+ TemplatePath = templateLocation,
+ TemplateSpecificArgs = templateArgs,
+ SnapshotsDirectory = Path.Combine("Snapshots", templateName),
+ OutputDirectory = workingDir,
+ DoNotPrependCallerMethodNameToScenarioName = true,
+ DoNotAppendTemplateArgsToScenarioName = true,
+ ScenarioName = scenarioName,
+ VerificationExcludePatterns = excludePatterns
+ };
+ }
+}
diff --git a/test/ProjectTemplates/Infrastructure/TemplateTestUtilities.cs b/test/ProjectTemplates/Infrastructure/TemplateTestUtilities.cs
new file mode 100644
index 00000000000..58fe84b7198
--- /dev/null
+++ b/test/ProjectTemplates/Infrastructure/TemplateTestUtilities.cs
@@ -0,0 +1,95 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text.RegularExpressions;
+
+namespace Microsoft.Shared.ProjectTemplates.Tests;
+
+public static class TemplateTestUtilities
+{
+ /// Create a sanitized and standardized project name from the supplied args
+ ///
+ /// Framework name is shortened from "net10.0" to "net10", e.g.
+ /// Boolean options explicitly set to "true" use the option name followed by '_T'.
+ /// Boolean options explicitly set to "false" use the option name followed by '_F'.
+ /// Options with names and values use only the option value.
+ /// Options without values use the option name.
+ /// Non-word characters are removed.
+ /// Empty values are removed.
+ ///
+ /// Name parts are abbreviated to avoid path length limits
+ /// - AzureOpenAI -> aoai
+ /// - GitHubModels -> gh
+ /// - Ollama -> o
+ /// - OpenAI -> oai
+ /// - AzureAISearch -> aais
+ /// - Qdrant -> q
+ /// - Local -> l
+ /// - Aspire -> A
+ /// - ManagedIdentity -> ID
+ /// - aot -> AOT
+ /// - SelfContained -> SC
+ ///
+ public static string GetProjectNameForArgs(string[] args, string? prefix = null)
+ {
+ IEnumerable nameParts = args
+ .Select(arg => Regex.Replace(arg, @"-(?:f|-[Ff]ramework)=(net[0-9]+)\.0", "$1"))
+ .Select(arg => Regex.Replace(arg, "--(.*?)=true", "$1_T"))
+ .Select(arg => Regex.Replace(arg, "--(.*?)=false", "$1_F"))
+ .Select(arg => Regex.Replace(arg, "--(.*?)=(.*)", "$2"))
+ .Select(arg => Regex.Replace(arg, "--(.*)", "$1"))
+ .Select(arg => Regex.Replace(arg, @"\W", ""))
+ .Select(arg => arg
+ .Replace("azureopenai", "aoai")
+ .Replace("githubmodels", "gh")
+ .Replace("ollama", "o")
+ .Replace("openai", "oai")
+ .Replace("azureaisearch", "aais")
+ .Replace("qdrant", "q")
+ .Replace("local", "l")
+ .Replace("aspire", "A")
+ .Replace("managedidentity", "ID")
+ .Replace("aot", "AOT")
+ .Replace("selfcontained", "SC"))
+ .Where(arg => !string.IsNullOrEmpty(arg));
+
+ return (nameParts.Any(), prefix is not null) switch
+ {
+ (false, false) => "_defaults",
+ (false, true) => $"{prefix}_defaults",
+ (true, false) => string.Join('_', nameParts),
+ _ => string.Join('_', nameParts.Prepend(prefix)),
+ };
+ }
+
+ /// Gets all combinations of options provided for a project template.
+ public static IEnumerable GetPossibleOptions(ReadOnlyMemory<(string name, string[] values)> options)
+ {
+ if (options.Length == 0)
+ {
+ yield return [];
+ yield break;
+ }
+
+ var firstOption = options.Span[0];
+
+ foreach (var value in firstOption.values)
+ {
+ foreach (var otherOptions in GetPossibleOptions(options[1..]))
+ {
+ yield return [$"{firstOption.name}={value}", .. otherOptions];
+ }
+ }
+ }
+
+ /// Checks for a specific option/value pair
+ public static bool HasOption(string[] args, string option, string value) =>
+ args.Contains($"{option}={value}");
+
+ /// Checks for a boolean option to be specified
+ public static bool HasOption(string[] args, string option) =>
+ args.Contains(option) || args.Contains($"{option}=true");
+}
diff --git a/test/ProjectTemplates/Infrastructure/VerifyScrubbers.cs b/test/ProjectTemplates/Infrastructure/VerifyScrubbers.cs
index 505feb99c14..1fa35f33a5e 100644
--- a/test/ProjectTemplates/Infrastructure/VerifyScrubbers.cs
+++ b/test/ProjectTemplates/Infrastructure/VerifyScrubbers.cs
@@ -1,13 +1,59 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
+using System;
+using System.IO;
using System.Text;
using System.Text.RegularExpressions;
+using Microsoft.TemplateEngine.Authoring.TemplateVerifier;
namespace Microsoft.Shared.ProjectTemplates.Tests;
internal static class VerifyScrubbers
{
+ public static ScrubbersDefinition AddSolutionFileGuidScrubber(this ScrubbersDefinition scrubbers) => scrubbers
+ .AddScrubber(
+ content => content.ScrubByRegex(pattern: @"\{.{36}\}", replacement: "{00000000-0000-0000-0000-000000000000}"),
+ extension: "sln");
+
+ public static ScrubbersDefinition AddUserSecretsScrubber(this ScrubbersDefinition scrubbers) => scrubbers
+ .AddScrubber(
+ content => content.ScrubByRegex(pattern: ".{36}", replacement: "{00000000-0000-0000-0000-000000000000}"),
+ extension: "csproj");
+
+ public static ScrubbersDefinition AddPackageReferenceScrubber(this ScrubbersDefinition scrubbers) => scrubbers
+ .AddScrubber(
+ content => content.ScrubByRegex(
+ pattern: @"",
+ replacement: @""),
+ extension: "csproj");
+
+ public static ScrubbersDefinition AddLocalhostPortScrubber(
+ this ScrubbersDefinition scrubbers,
+ (string pattern, string replacement)? https = null,
+ (string pattern, string replacement)? http = null)
+ {
+ https ??= (@"\d{4,5}", "9995");
+ http ??= (@"\d{4,5}", "9996");
+
+ Action scrubPorts = content =>
+ {
+ content.ScrubByRegex($@"(https://localhost):({https.Value.pattern})", $"$1:{https.Value.replacement}");
+ content.ScrubByRegex($@"(http://localhost):({http.Value.pattern})", $"$1:{http.Value.replacement}");
+ };
+
+ return scrubbers
+ .AddScrubber(scrubPorts, extension: "md")
+ .AddScrubber(scrubPorts, extension: "http")
+ .AddScrubber((path, content) =>
+ {
+ if (Path.GetFileName(path).Equals("launchSettings.json", StringComparison.OrdinalIgnoreCase))
+ {
+ scrubPorts(content);
+ }
+ });
+ }
+
///
/// Removes content after "Details: ".
///
diff --git a/test/ProjectTemplates/Infrastructure/WellKnownPaths.cs b/test/ProjectTemplates/Infrastructure/WellKnownPaths.cs
index 0ebb196fe84..3a30f84d4ff 100644
--- a/test/ProjectTemplates/Infrastructure/WellKnownPaths.cs
+++ b/test/ProjectTemplates/Infrastructure/WellKnownPaths.cs
@@ -9,38 +9,32 @@ namespace Microsoft.Shared.ProjectTemplates.Tests;
internal static class WellKnownPaths
{
+ private const string BuildConfigurationFolder =
+#if DEBUG
+ "Debug";
+#else
+ "Release";
+#endif
+
public static readonly string RepoRoot;
public static readonly string RepoDotNetExePath;
- public static readonly string ThisProjectRoot;
+ public static readonly string LocalShippingPackagesPath;
+ public static readonly string ProjectTemplatesArtifactsRoot;
- public static readonly string TemplateFeedLocation;
+ // Execution Test Paths
public static readonly string TemplateSandboxSource;
- public static readonly string TemplateSandboxOutputRoot;
- public static readonly string TemplateInstallNuGetConfigPath;
public static readonly string TemplateTestNuGetConfigPath;
- public static readonly string LocalShippingPackagesPath;
- public static readonly string NuGetPackagesPath;
static WellKnownPaths()
{
RepoRoot = GetRepoRoot();
RepoDotNetExePath = GetRepoDotNetExePath();
- ThisProjectRoot = ProjectRootHelper.GetThisProjectRoot();
- TemplateFeedLocation = Path.Combine(RepoRoot, "src", "ProjectTemplates");
+ ProjectTemplatesArtifactsRoot = Path.Combine(RepoRoot, "artifacts", "ProjectTemplates");
TemplateSandboxSource = Path.Combine(RepoRoot, "test", "ProjectTemplates", "Infrastructure", "TemplateSandbox");
- TemplateSandboxOutputRoot = Path.Combine(ThisProjectRoot, "ExecutionTestSandbox");
- TemplateInstallNuGetConfigPath = Path.Combine(TemplateSandboxSource, "nuget.template_install.config");
- TemplateTestNuGetConfigPath = Path.Combine(TemplateSandboxSource, "nuget.template_test.config");
+ TemplateTestNuGetConfigPath = Path.Combine(TemplateSandboxSource, "nuget.config");
- const string BuildConfigurationFolder =
-#if DEBUG
- "Debug";
-#else
- "Release";
-#endif
LocalShippingPackagesPath = Path.Combine(RepoRoot, "artifacts", "packages", BuildConfigurationFolder, "Shipping");
- NuGetPackagesPath = Path.Combine(TemplateSandboxOutputRoot, "packages");
}
private static string GetRepoRoot()
diff --git a/test/ProjectTemplates/Microsoft.Agents.AI.ProjectTemplates.IntegrationTests/AIAgentWebAPIExecutionTests.cs b/test/ProjectTemplates/Microsoft.Agents.AI.ProjectTemplates.IntegrationTests/AIAgentWebAPIExecutionTests.cs
new file mode 100644
index 00000000000..675fb642aa6
--- /dev/null
+++ b/test/ProjectTemplates/Microsoft.Agents.AI.ProjectTemplates.IntegrationTests/AIAgentWebAPIExecutionTests.cs
@@ -0,0 +1,65 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.Collections.Generic;
+using System.Threading.Tasks;
+using Microsoft.Shared.ProjectTemplates.Tests;
+using Xunit;
+using Xunit.Abstractions;
+using static Microsoft.Shared.ProjectTemplates.Tests.TemplateTestUtilities;
+
+namespace Microsoft.Agents.AI.ProjectTemplates.Tests;
+
+///
+/// Contains execution tests for the "AI Agent Web API" template.
+///
+///
+/// In addition to validating that the templates build and restore correctly,
+/// these tests are also responsible for template component governance reporting.
+/// This is because the generated output is left on disk after tests complete,
+/// most importantly the project.assets.json file that gets created during restore.
+/// Therefore, it's *critical* that these tests remain in a working state,
+/// as disabling them will also disable CG reporting.
+///
+public class AIAgentWebAPIExecutionTests : TemplateExecutionTestBase, ITemplateExecutionTestConfigurationProvider
+{
+ public AIAgentWebAPIExecutionTests(TemplateExecutionTestFixture fixture, ITestOutputHelper outputHelper)
+ : base(fixture, outputHelper)
+ {
+ }
+
+ public static TemplateExecutionTestConfiguration Configuration { get; } = new()
+ {
+ TemplatePackageName = "Microsoft.Agents.AI.ProjectTemplates",
+ TemplateName = "aiagent-webapi"
+ };
+
+ public static IEnumerable
diff --git a/test/ProjectTemplates/Microsoft.Agents.AI.ProjectTemplates.IntegrationTests/Snapshots/aiagent-webapi.AzureOpenAI_ApiKey.verified/aiagent-webapi/appsettings.json b/test/ProjectTemplates/Microsoft.Agents.AI.ProjectTemplates.IntegrationTests/Snapshots/aiagent-webapi/aiagent-webapi._defaults.verified/aiagent-webapi/appsettings.json
similarity index 100%
rename from test/ProjectTemplates/Microsoft.Agents.AI.ProjectTemplates.IntegrationTests/Snapshots/aiagent-webapi.AzureOpenAI_ApiKey.verified/aiagent-webapi/appsettings.json
rename to test/ProjectTemplates/Microsoft.Agents.AI.ProjectTemplates.IntegrationTests/Snapshots/aiagent-webapi/aiagent-webapi._defaults.verified/aiagent-webapi/appsettings.json
diff --git a/test/ProjectTemplates/Microsoft.Agents.AI.ProjectTemplates.IntegrationTests/Snapshots/aiagent-webapi.AzureOpenAI_ApiKey.verified/aiagent-webapi/Program.cs b/test/ProjectTemplates/Microsoft.Agents.AI.ProjectTemplates.IntegrationTests/Snapshots/aiagent-webapi/aiagent-webapi.aoai_ID_F.verified/aiagent-webapi/Program.cs
similarity index 93%
rename from test/ProjectTemplates/Microsoft.Agents.AI.ProjectTemplates.IntegrationTests/Snapshots/aiagent-webapi.AzureOpenAI_ApiKey.verified/aiagent-webapi/Program.cs
rename to test/ProjectTemplates/Microsoft.Agents.AI.ProjectTemplates.IntegrationTests/Snapshots/aiagent-webapi/aiagent-webapi.aoai_ID_F.verified/aiagent-webapi/Program.cs
index ddc551393fa..3ece18c0d08 100644
--- a/test/ProjectTemplates/Microsoft.Agents.AI.ProjectTemplates.IntegrationTests/Snapshots/aiagent-webapi.AzureOpenAI_ApiKey.verified/aiagent-webapi/Program.cs
+++ b/test/ProjectTemplates/Microsoft.Agents.AI.ProjectTemplates.IntegrationTests/Snapshots/aiagent-webapi/aiagent-webapi.aoai_ID_F.verified/aiagent-webapi/Program.cs
@@ -36,9 +36,12 @@
builder.AddWorkflow("publisher", (sp, key) => AgentWorkflowBuilder.BuildSequential(
workflowName: key,
- sp.GetRequiredKeyedService("writer"),
- sp.GetRequiredKeyedService("editor")
-)).AddAsAIAgent();
+ agents:
+ [
+ sp.GetRequiredKeyedService("writer"),
+ sp.GetRequiredKeyedService("editor")
+ ]
+)).AddAsAIAgent("publisher-agent");
// Register services for OpenAI responses and conversations (also required for DevUI)
builder.Services.AddOpenAIResponses();
diff --git a/test/ProjectTemplates/Microsoft.Agents.AI.ProjectTemplates.IntegrationTests/Snapshots/aiagent-webapi.AzureOpenAI_ApiKey.verified/aiagent-webapi/Properties/launchSettings.json b/test/ProjectTemplates/Microsoft.Agents.AI.ProjectTemplates.IntegrationTests/Snapshots/aiagent-webapi/aiagent-webapi.aoai_ID_F.verified/aiagent-webapi/Properties/launchSettings.json
similarity index 82%
rename from test/ProjectTemplates/Microsoft.Agents.AI.ProjectTemplates.IntegrationTests/Snapshots/aiagent-webapi.AzureOpenAI_ApiKey.verified/aiagent-webapi/Properties/launchSettings.json
rename to test/ProjectTemplates/Microsoft.Agents.AI.ProjectTemplates.IntegrationTests/Snapshots/aiagent-webapi/aiagent-webapi.aoai_ID_F.verified/aiagent-webapi/Properties/launchSettings.json
index c242aacc025..d71b1876d35 100644
--- a/test/ProjectTemplates/Microsoft.Agents.AI.ProjectTemplates.IntegrationTests/Snapshots/aiagent-webapi.AzureOpenAI_ApiKey.verified/aiagent-webapi/Properties/launchSettings.json
+++ b/test/ProjectTemplates/Microsoft.Agents.AI.ProjectTemplates.IntegrationTests/Snapshots/aiagent-webapi/aiagent-webapi.aoai_ID_F.verified/aiagent-webapi/Properties/launchSettings.json
@@ -6,7 +6,7 @@
"dotnetRunMessages": true,
"launchBrowser": true,
"launchUrl": "devui/",
- "applicationUrl": "http://localhost:9999",
+ "applicationUrl": "http://localhost:9996",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
@@ -16,7 +16,7 @@
"dotnetRunMessages": true,
"launchBrowser": true,
"launchUrl": "devui/",
- "applicationUrl": "https://localhost:9999;http://localhost:9999",
+ "applicationUrl": "https://localhost:9995;http://localhost:9996",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
diff --git a/test/ProjectTemplates/Microsoft.Agents.AI.ProjectTemplates.IntegrationTests/Snapshots/aiagent-webapi.AzureOpenAI_ApiKey.verified/aiagent-webapi/README.md b/test/ProjectTemplates/Microsoft.Agents.AI.ProjectTemplates.IntegrationTests/Snapshots/aiagent-webapi/aiagent-webapi.aoai_ID_F.verified/aiagent-webapi/README.md
similarity index 98%
rename from test/ProjectTemplates/Microsoft.Agents.AI.ProjectTemplates.IntegrationTests/Snapshots/aiagent-webapi.AzureOpenAI_ApiKey.verified/aiagent-webapi/README.md
rename to test/ProjectTemplates/Microsoft.Agents.AI.ProjectTemplates.IntegrationTests/Snapshots/aiagent-webapi/aiagent-webapi.aoai_ID_F.verified/aiagent-webapi/README.md
index de250a2916e..222e83f1188 100644
--- a/test/ProjectTemplates/Microsoft.Agents.AI.ProjectTemplates.IntegrationTests/Snapshots/aiagent-webapi.AzureOpenAI_ApiKey.verified/aiagent-webapi/README.md
+++ b/test/ProjectTemplates/Microsoft.Agents.AI.ProjectTemplates.IntegrationTests/Snapshots/aiagent-webapi/aiagent-webapi.aoai_ID_F.verified/aiagent-webapi/README.md
@@ -48,8 +48,8 @@ dotnet run -lp https
```
The application will start and listen on:
-- HTTP: `http://localhost:9999`
-- HTTPS: `https://localhost:9999`
+- HTTP: `http://localhost:9996`
+- HTTPS: `https://localhost:9995`
### 3. Test the Application
diff --git a/test/ProjectTemplates/Microsoft.Agents.AI.ProjectTemplates.IntegrationTests/Snapshots/aiagent-webapi.GitHubModels.verified/aiagent-webapi/aiagent-webapi.csproj b/test/ProjectTemplates/Microsoft.Agents.AI.ProjectTemplates.IntegrationTests/Snapshots/aiagent-webapi/aiagent-webapi.aoai_ID_F.verified/aiagent-webapi/aiagent-webapi.csproj
similarity index 69%
rename from test/ProjectTemplates/Microsoft.Agents.AI.ProjectTemplates.IntegrationTests/Snapshots/aiagent-webapi.GitHubModels.verified/aiagent-webapi/aiagent-webapi.csproj
rename to test/ProjectTemplates/Microsoft.Agents.AI.ProjectTemplates.IntegrationTests/Snapshots/aiagent-webapi/aiagent-webapi.aoai_ID_F.verified/aiagent-webapi/aiagent-webapi.csproj
index 337bfdd220c..6e5004343c4 100644
--- a/test/ProjectTemplates/Microsoft.Agents.AI.ProjectTemplates.IntegrationTests/Snapshots/aiagent-webapi.GitHubModels.verified/aiagent-webapi/aiagent-webapi.csproj
+++ b/test/ProjectTemplates/Microsoft.Agents.AI.ProjectTemplates.IntegrationTests/Snapshots/aiagent-webapi/aiagent-webapi.aoai_ID_F.verified/aiagent-webapi/aiagent-webapi.csproj
@@ -4,16 +4,16 @@
net10.0enableenable
- secret
+ {00000000-0000-0000-0000-000000000000}
-
-
-
-
-
-
+
+
+
+
+
+
diff --git a/test/ProjectTemplates/Microsoft.Agents.AI.ProjectTemplates.IntegrationTests/Snapshots/aiagent-webapi.AzureOpenAI_ManagedIdentity.verified/aiagent-webapi/appsettings.json b/test/ProjectTemplates/Microsoft.Agents.AI.ProjectTemplates.IntegrationTests/Snapshots/aiagent-webapi/aiagent-webapi.aoai_ID_F.verified/aiagent-webapi/appsettings.json
similarity index 100%
rename from test/ProjectTemplates/Microsoft.Agents.AI.ProjectTemplates.IntegrationTests/Snapshots/aiagent-webapi.AzureOpenAI_ManagedIdentity.verified/aiagent-webapi/appsettings.json
rename to test/ProjectTemplates/Microsoft.Agents.AI.ProjectTemplates.IntegrationTests/Snapshots/aiagent-webapi/aiagent-webapi.aoai_ID_F.verified/aiagent-webapi/appsettings.json
diff --git a/test/ProjectTemplates/Microsoft.Agents.AI.ProjectTemplates.IntegrationTests/Snapshots/aiagent-webapi.AzureOpenAI_ManagedIdentity.verified/aiagent-webapi/Program.cs b/test/ProjectTemplates/Microsoft.Agents.AI.ProjectTemplates.IntegrationTests/Snapshots/aiagent-webapi/aiagent-webapi.aoai_ID_T.verified/aiagent-webapi/Program.cs
similarity index 93%
rename from test/ProjectTemplates/Microsoft.Agents.AI.ProjectTemplates.IntegrationTests/Snapshots/aiagent-webapi.AzureOpenAI_ManagedIdentity.verified/aiagent-webapi/Program.cs
rename to test/ProjectTemplates/Microsoft.Agents.AI.ProjectTemplates.IntegrationTests/Snapshots/aiagent-webapi/aiagent-webapi.aoai_ID_T.verified/aiagent-webapi/Program.cs
index 3749e820b45..037ac3deb7e 100644
--- a/test/ProjectTemplates/Microsoft.Agents.AI.ProjectTemplates.IntegrationTests/Snapshots/aiagent-webapi.AzureOpenAI_ManagedIdentity.verified/aiagent-webapi/Program.cs
+++ b/test/ProjectTemplates/Microsoft.Agents.AI.ProjectTemplates.IntegrationTests/Snapshots/aiagent-webapi/aiagent-webapi.aoai_ID_T.verified/aiagent-webapi/Program.cs
@@ -38,9 +38,12 @@
builder.AddWorkflow("publisher", (sp, key) => AgentWorkflowBuilder.BuildSequential(
workflowName: key,
- sp.GetRequiredKeyedService("writer"),
- sp.GetRequiredKeyedService("editor")
-)).AddAsAIAgent();
+ agents:
+ [
+ sp.GetRequiredKeyedService("writer"),
+ sp.GetRequiredKeyedService("editor")
+ ]
+)).AddAsAIAgent("publisher-agent");
// Register services for OpenAI responses and conversations (also required for DevUI)
builder.Services.AddOpenAIResponses();
diff --git a/test/ProjectTemplates/Microsoft.Agents.AI.ProjectTemplates.IntegrationTests/Snapshots/aiagent-webapi.AzureOpenAI_ManagedIdentity.verified/aiagent-webapi/Properties/launchSettings.json b/test/ProjectTemplates/Microsoft.Agents.AI.ProjectTemplates.IntegrationTests/Snapshots/aiagent-webapi/aiagent-webapi.aoai_ID_T.verified/aiagent-webapi/Properties/launchSettings.json
similarity index 82%
rename from test/ProjectTemplates/Microsoft.Agents.AI.ProjectTemplates.IntegrationTests/Snapshots/aiagent-webapi.AzureOpenAI_ManagedIdentity.verified/aiagent-webapi/Properties/launchSettings.json
rename to test/ProjectTemplates/Microsoft.Agents.AI.ProjectTemplates.IntegrationTests/Snapshots/aiagent-webapi/aiagent-webapi.aoai_ID_T.verified/aiagent-webapi/Properties/launchSettings.json
index c242aacc025..d71b1876d35 100644
--- a/test/ProjectTemplates/Microsoft.Agents.AI.ProjectTemplates.IntegrationTests/Snapshots/aiagent-webapi.AzureOpenAI_ManagedIdentity.verified/aiagent-webapi/Properties/launchSettings.json
+++ b/test/ProjectTemplates/Microsoft.Agents.AI.ProjectTemplates.IntegrationTests/Snapshots/aiagent-webapi/aiagent-webapi.aoai_ID_T.verified/aiagent-webapi/Properties/launchSettings.json
@@ -6,7 +6,7 @@
"dotnetRunMessages": true,
"launchBrowser": true,
"launchUrl": "devui/",
- "applicationUrl": "http://localhost:9999",
+ "applicationUrl": "http://localhost:9996",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
@@ -16,7 +16,7 @@
"dotnetRunMessages": true,
"launchBrowser": true,
"launchUrl": "devui/",
- "applicationUrl": "https://localhost:9999;http://localhost:9999",
+ "applicationUrl": "https://localhost:9995;http://localhost:9996",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
diff --git a/test/ProjectTemplates/Microsoft.Agents.AI.ProjectTemplates.IntegrationTests/Snapshots/aiagent-webapi.AzureOpenAI_ManagedIdentity.verified/aiagent-webapi/README.md b/test/ProjectTemplates/Microsoft.Agents.AI.ProjectTemplates.IntegrationTests/Snapshots/aiagent-webapi/aiagent-webapi.aoai_ID_T.verified/aiagent-webapi/README.md
similarity index 98%
rename from test/ProjectTemplates/Microsoft.Agents.AI.ProjectTemplates.IntegrationTests/Snapshots/aiagent-webapi.AzureOpenAI_ManagedIdentity.verified/aiagent-webapi/README.md
rename to test/ProjectTemplates/Microsoft.Agents.AI.ProjectTemplates.IntegrationTests/Snapshots/aiagent-webapi/aiagent-webapi.aoai_ID_T.verified/aiagent-webapi/README.md
index 3cb72789072..99157e36906 100644
--- a/test/ProjectTemplates/Microsoft.Agents.AI.ProjectTemplates.IntegrationTests/Snapshots/aiagent-webapi.AzureOpenAI_ManagedIdentity.verified/aiagent-webapi/README.md
+++ b/test/ProjectTemplates/Microsoft.Agents.AI.ProjectTemplates.IntegrationTests/Snapshots/aiagent-webapi/aiagent-webapi.aoai_ID_T.verified/aiagent-webapi/README.md
@@ -20,8 +20,8 @@ dotnet run -lp https
```
The application will start and listen on:
-- HTTP: `http://localhost:9999`
-- HTTPS: `https://localhost:9999`
+- HTTP: `http://localhost:9996`
+- HTTPS: `https://localhost:9995`
### 3. Test the Application
diff --git a/test/ProjectTemplates/Microsoft.Agents.AI.ProjectTemplates.IntegrationTests/Snapshots/aiagent-webapi.AzureOpenAI_ManagedIdentity.verified/aiagent-webapi/aiagent-webapi.csproj b/test/ProjectTemplates/Microsoft.Agents.AI.ProjectTemplates.IntegrationTests/Snapshots/aiagent-webapi/aiagent-webapi.aoai_ID_T.verified/aiagent-webapi/aiagent-webapi.csproj
similarity index 63%
rename from test/ProjectTemplates/Microsoft.Agents.AI.ProjectTemplates.IntegrationTests/Snapshots/aiagent-webapi.AzureOpenAI_ManagedIdentity.verified/aiagent-webapi/aiagent-webapi.csproj
rename to test/ProjectTemplates/Microsoft.Agents.AI.ProjectTemplates.IntegrationTests/Snapshots/aiagent-webapi/aiagent-webapi.aoai_ID_T.verified/aiagent-webapi/aiagent-webapi.csproj
index 0dab5ae9e6e..393be1ca919 100644
--- a/test/ProjectTemplates/Microsoft.Agents.AI.ProjectTemplates.IntegrationTests/Snapshots/aiagent-webapi.AzureOpenAI_ManagedIdentity.verified/aiagent-webapi/aiagent-webapi.csproj
+++ b/test/ProjectTemplates/Microsoft.Agents.AI.ProjectTemplates.IntegrationTests/Snapshots/aiagent-webapi/aiagent-webapi.aoai_ID_T.verified/aiagent-webapi/aiagent-webapi.csproj
@@ -4,17 +4,17 @@
net10.0enableenable
- secret
+ {00000000-0000-0000-0000-000000000000}
-
-
-
-
-
-
-
+
+
+
+
+
+
+
diff --git a/test/ProjectTemplates/Microsoft.Agents.AI.ProjectTemplates.IntegrationTests/Snapshots/aiagent-webapi.DefaultParameters.verified/aiagent-webapi/appsettings.json b/test/ProjectTemplates/Microsoft.Agents.AI.ProjectTemplates.IntegrationTests/Snapshots/aiagent-webapi/aiagent-webapi.aoai_ID_T.verified/aiagent-webapi/appsettings.json
similarity index 100%
rename from test/ProjectTemplates/Microsoft.Agents.AI.ProjectTemplates.IntegrationTests/Snapshots/aiagent-webapi.DefaultParameters.verified/aiagent-webapi/appsettings.json
rename to test/ProjectTemplates/Microsoft.Agents.AI.ProjectTemplates.IntegrationTests/Snapshots/aiagent-webapi/aiagent-webapi.aoai_ID_T.verified/aiagent-webapi/appsettings.json
diff --git a/test/ProjectTemplates/Microsoft.Agents.AI.ProjectTemplates.IntegrationTests/Snapshots/aiagent-webapi.Ollama.verified/aiagent-webapi/Program.cs b/test/ProjectTemplates/Microsoft.Agents.AI.ProjectTemplates.IntegrationTests/Snapshots/aiagent-webapi/aiagent-webapi.o.verified/aiagent-webapi/Program.cs
similarity index 91%
rename from test/ProjectTemplates/Microsoft.Agents.AI.ProjectTemplates.IntegrationTests/Snapshots/aiagent-webapi.Ollama.verified/aiagent-webapi/Program.cs
rename to test/ProjectTemplates/Microsoft.Agents.AI.ProjectTemplates.IntegrationTests/Snapshots/aiagent-webapi/aiagent-webapi.o.verified/aiagent-webapi/Program.cs
index 2e9c6d25484..dfc311d6e17 100644
--- a/test/ProjectTemplates/Microsoft.Agents.AI.ProjectTemplates.IntegrationTests/Snapshots/aiagent-webapi.Ollama.verified/aiagent-webapi/Program.cs
+++ b/test/ProjectTemplates/Microsoft.Agents.AI.ProjectTemplates.IntegrationTests/Snapshots/aiagent-webapi/aiagent-webapi.o.verified/aiagent-webapi/Program.cs
@@ -25,9 +25,12 @@
builder.AddWorkflow("publisher", (sp, key) => AgentWorkflowBuilder.BuildSequential(
workflowName: key,
- sp.GetRequiredKeyedService("writer"),
- sp.GetRequiredKeyedService("editor")
-)).AddAsAIAgent();
+ agents:
+ [
+ sp.GetRequiredKeyedService("writer"),
+ sp.GetRequiredKeyedService("editor")
+ ]
+)).AddAsAIAgent("publisher-agent");
// Register services for OpenAI responses and conversations (also required for DevUI)
builder.Services.AddOpenAIResponses();
diff --git a/test/ProjectTemplates/Microsoft.Agents.AI.ProjectTemplates.IntegrationTests/Snapshots/aiagent-webapi.DefaultParameters.verified/aiagent-webapi/Properties/launchSettings.json b/test/ProjectTemplates/Microsoft.Agents.AI.ProjectTemplates.IntegrationTests/Snapshots/aiagent-webapi/aiagent-webapi.o.verified/aiagent-webapi/Properties/launchSettings.json
similarity index 82%
rename from test/ProjectTemplates/Microsoft.Agents.AI.ProjectTemplates.IntegrationTests/Snapshots/aiagent-webapi.DefaultParameters.verified/aiagent-webapi/Properties/launchSettings.json
rename to test/ProjectTemplates/Microsoft.Agents.AI.ProjectTemplates.IntegrationTests/Snapshots/aiagent-webapi/aiagent-webapi.o.verified/aiagent-webapi/Properties/launchSettings.json
index c242aacc025..d71b1876d35 100644
--- a/test/ProjectTemplates/Microsoft.Agents.AI.ProjectTemplates.IntegrationTests/Snapshots/aiagent-webapi.DefaultParameters.verified/aiagent-webapi/Properties/launchSettings.json
+++ b/test/ProjectTemplates/Microsoft.Agents.AI.ProjectTemplates.IntegrationTests/Snapshots/aiagent-webapi/aiagent-webapi.o.verified/aiagent-webapi/Properties/launchSettings.json
@@ -6,7 +6,7 @@
"dotnetRunMessages": true,
"launchBrowser": true,
"launchUrl": "devui/",
- "applicationUrl": "http://localhost:9999",
+ "applicationUrl": "http://localhost:9996",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
@@ -16,7 +16,7 @@
"dotnetRunMessages": true,
"launchBrowser": true,
"launchUrl": "devui/",
- "applicationUrl": "https://localhost:9999;http://localhost:9999",
+ "applicationUrl": "https://localhost:9995;http://localhost:9996",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
diff --git a/test/ProjectTemplates/Microsoft.Agents.AI.ProjectTemplates.IntegrationTests/Snapshots/aiagent-webapi.Ollama.verified/aiagent-webapi/README.md b/test/ProjectTemplates/Microsoft.Agents.AI.ProjectTemplates.IntegrationTests/Snapshots/aiagent-webapi/aiagent-webapi.o.verified/aiagent-webapi/README.md
similarity index 96%
rename from test/ProjectTemplates/Microsoft.Agents.AI.ProjectTemplates.IntegrationTests/Snapshots/aiagent-webapi.Ollama.verified/aiagent-webapi/README.md
rename to test/ProjectTemplates/Microsoft.Agents.AI.ProjectTemplates.IntegrationTests/Snapshots/aiagent-webapi/aiagent-webapi.o.verified/aiagent-webapi/README.md
index 411f6c90acc..13f6f85451d 100644
--- a/test/ProjectTemplates/Microsoft.Agents.AI.ProjectTemplates.IntegrationTests/Snapshots/aiagent-webapi.Ollama.verified/aiagent-webapi/README.md
+++ b/test/ProjectTemplates/Microsoft.Agents.AI.ProjectTemplates.IntegrationTests/Snapshots/aiagent-webapi/aiagent-webapi.o.verified/aiagent-webapi/README.md
@@ -21,7 +21,7 @@ This application uses Ollama running locally (model: llama3.2). You'll need to h
```
3. Ensure Ollama is running (it starts automatically after installation)
-The application is configured to connect to Ollama at `http://localhost:9999`.
+The application is configured to connect to Ollama at `http://localhost:9996`.
### 2. Run the Application
@@ -31,8 +31,8 @@ dotnet run -lp https
```
The application will start and listen on:
-- HTTP: `http://localhost:9999`
-- HTTPS: `https://localhost:9999`
+- HTTP: `http://localhost:9996`
+- HTTPS: `https://localhost:9995`
### 3. Test the Application
@@ -104,7 +104,7 @@ dotnet new aiagent-webapi --provider ollama --chat-model llama3.1
**Solution**:
- Ensure Ollama is running. On macOS/Linux, check with `pgrep ollama`. On Windows, check Task Manager.
-- Verify Ollama is accessible at `http://localhost:9999`
+- Verify Ollama is accessible at `http://localhost:9996`
- Make sure you've downloaded the llama3.2 model: `ollama pull llama3.2`
**Problem**: Model responses are slow or time out
diff --git a/test/ProjectTemplates/Microsoft.Agents.AI.ProjectTemplates.IntegrationTests/Snapshots/aiagent-webapi.Ollama.verified/aiagent-webapi/aiagent-webapi.csproj b/test/ProjectTemplates/Microsoft.Agents.AI.ProjectTemplates.IntegrationTests/Snapshots/aiagent-webapi/aiagent-webapi.o.verified/aiagent-webapi/aiagent-webapi.csproj
similarity index 62%
rename from test/ProjectTemplates/Microsoft.Agents.AI.ProjectTemplates.IntegrationTests/Snapshots/aiagent-webapi.Ollama.verified/aiagent-webapi/aiagent-webapi.csproj
rename to test/ProjectTemplates/Microsoft.Agents.AI.ProjectTemplates.IntegrationTests/Snapshots/aiagent-webapi/aiagent-webapi.o.verified/aiagent-webapi/aiagent-webapi.csproj
index 1070edf0dad..4ee728aaba3 100644
--- a/test/ProjectTemplates/Microsoft.Agents.AI.ProjectTemplates.IntegrationTests/Snapshots/aiagent-webapi.Ollama.verified/aiagent-webapi/aiagent-webapi.csproj
+++ b/test/ProjectTemplates/Microsoft.Agents.AI.ProjectTemplates.IntegrationTests/Snapshots/aiagent-webapi/aiagent-webapi.o.verified/aiagent-webapi/aiagent-webapi.csproj
@@ -4,16 +4,16 @@
net10.0enableenable
- secret
+ {00000000-0000-0000-0000-000000000000}
-
-
-
-
-
-
+
+
+
+
+
+
diff --git a/test/ProjectTemplates/Microsoft.Agents.AI.ProjectTemplates.IntegrationTests/Snapshots/aiagent-webapi.GitHubModels.verified/aiagent-webapi/appsettings.json b/test/ProjectTemplates/Microsoft.Agents.AI.ProjectTemplates.IntegrationTests/Snapshots/aiagent-webapi/aiagent-webapi.o.verified/aiagent-webapi/appsettings.json
similarity index 100%
rename from test/ProjectTemplates/Microsoft.Agents.AI.ProjectTemplates.IntegrationTests/Snapshots/aiagent-webapi.GitHubModels.verified/aiagent-webapi/appsettings.json
rename to test/ProjectTemplates/Microsoft.Agents.AI.ProjectTemplates.IntegrationTests/Snapshots/aiagent-webapi/aiagent-webapi.o.verified/aiagent-webapi/appsettings.json
diff --git a/test/ProjectTemplates/Microsoft.Agents.AI.ProjectTemplates.IntegrationTests/Snapshots/aiagent-webapi.OpenAI.verified/aiagent-webapi/Program.cs b/test/ProjectTemplates/Microsoft.Agents.AI.ProjectTemplates.IntegrationTests/Snapshots/aiagent-webapi/aiagent-webapi.oai.verified/aiagent-webapi/Program.cs
similarity index 92%
rename from test/ProjectTemplates/Microsoft.Agents.AI.ProjectTemplates.IntegrationTests/Snapshots/aiagent-webapi.OpenAI.verified/aiagent-webapi/Program.cs
rename to test/ProjectTemplates/Microsoft.Agents.AI.ProjectTemplates.IntegrationTests/Snapshots/aiagent-webapi/aiagent-webapi.oai.verified/aiagent-webapi/Program.cs
index 15009d121cd..efed4c96ad5 100644
--- a/test/ProjectTemplates/Microsoft.Agents.AI.ProjectTemplates.IntegrationTests/Snapshots/aiagent-webapi.OpenAI.verified/aiagent-webapi/Program.cs
+++ b/test/ProjectTemplates/Microsoft.Agents.AI.ProjectTemplates.IntegrationTests/Snapshots/aiagent-webapi/aiagent-webapi.oai.verified/aiagent-webapi/Program.cs
@@ -31,9 +31,12 @@
builder.AddWorkflow("publisher", (sp, key) => AgentWorkflowBuilder.BuildSequential(
workflowName: key,
- sp.GetRequiredKeyedService("writer"),
- sp.GetRequiredKeyedService("editor")
-)).AddAsAIAgent();
+ agents:
+ [
+ sp.GetRequiredKeyedService("writer"),
+ sp.GetRequiredKeyedService("editor")
+ ]
+)).AddAsAIAgent("publisher-agent");
// Register services for OpenAI responses and conversations (also required for DevUI)
builder.Services.AddOpenAIResponses();
diff --git a/test/ProjectTemplates/Microsoft.Agents.AI.ProjectTemplates.IntegrationTests/Snapshots/aiagent-webapi/aiagent-webapi.oai.verified/aiagent-webapi/Properties/launchSettings.json b/test/ProjectTemplates/Microsoft.Agents.AI.ProjectTemplates.IntegrationTests/Snapshots/aiagent-webapi/aiagent-webapi.oai.verified/aiagent-webapi/Properties/launchSettings.json
new file mode 100644
index 00000000000..d71b1876d35
--- /dev/null
+++ b/test/ProjectTemplates/Microsoft.Agents.AI.ProjectTemplates.IntegrationTests/Snapshots/aiagent-webapi/aiagent-webapi.oai.verified/aiagent-webapi/Properties/launchSettings.json
@@ -0,0 +1,25 @@
+{
+ "$schema": "https://json.schemastore.org/launchsettings.json",
+ "profiles": {
+ "http": {
+ "commandName": "Project",
+ "dotnetRunMessages": true,
+ "launchBrowser": true,
+ "launchUrl": "devui/",
+ "applicationUrl": "http://localhost:9996",
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ },
+ "https": {
+ "commandName": "Project",
+ "dotnetRunMessages": true,
+ "launchBrowser": true,
+ "launchUrl": "devui/",
+ "applicationUrl": "https://localhost:9995;http://localhost:9996",
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ }
+ }
+}
diff --git a/test/ProjectTemplates/Microsoft.Agents.AI.ProjectTemplates.IntegrationTests/Snapshots/aiagent-webapi.OpenAI.verified/aiagent-webapi/README.md b/test/ProjectTemplates/Microsoft.Agents.AI.ProjectTemplates.IntegrationTests/Snapshots/aiagent-webapi/aiagent-webapi.oai.verified/aiagent-webapi/README.md
similarity index 98%
rename from test/ProjectTemplates/Microsoft.Agents.AI.ProjectTemplates.IntegrationTests/Snapshots/aiagent-webapi.OpenAI.verified/aiagent-webapi/README.md
rename to test/ProjectTemplates/Microsoft.Agents.AI.ProjectTemplates.IntegrationTests/Snapshots/aiagent-webapi/aiagent-webapi.oai.verified/aiagent-webapi/README.md
index a989e78b7d7..dfd846707b6 100644
--- a/test/ProjectTemplates/Microsoft.Agents.AI.ProjectTemplates.IntegrationTests/Snapshots/aiagent-webapi.OpenAI.verified/aiagent-webapi/README.md
+++ b/test/ProjectTemplates/Microsoft.Agents.AI.ProjectTemplates.IntegrationTests/Snapshots/aiagent-webapi/aiagent-webapi.oai.verified/aiagent-webapi/README.md
@@ -50,8 +50,8 @@ dotnet run -lp https
```
The application will start and listen on:
-- HTTP: `http://localhost:9999`
-- HTTPS: `https://localhost:9999`
+- HTTP: `http://localhost:9996`
+- HTTPS: `https://localhost:9995`
### 3. Test the Application
diff --git a/test/ProjectTemplates/Microsoft.Agents.AI.ProjectTemplates.IntegrationTests/Snapshots/aiagent-webapi.DefaultParameters.verified/aiagent-webapi/aiagent-webapi.csproj b/test/ProjectTemplates/Microsoft.Agents.AI.ProjectTemplates.IntegrationTests/Snapshots/aiagent-webapi/aiagent-webapi.oai.verified/aiagent-webapi/aiagent-webapi.csproj
similarity index 69%
rename from test/ProjectTemplates/Microsoft.Agents.AI.ProjectTemplates.IntegrationTests/Snapshots/aiagent-webapi.DefaultParameters.verified/aiagent-webapi/aiagent-webapi.csproj
rename to test/ProjectTemplates/Microsoft.Agents.AI.ProjectTemplates.IntegrationTests/Snapshots/aiagent-webapi/aiagent-webapi.oai.verified/aiagent-webapi/aiagent-webapi.csproj
index 337bfdd220c..6e5004343c4 100644
--- a/test/ProjectTemplates/Microsoft.Agents.AI.ProjectTemplates.IntegrationTests/Snapshots/aiagent-webapi.DefaultParameters.verified/aiagent-webapi/aiagent-webapi.csproj
+++ b/test/ProjectTemplates/Microsoft.Agents.AI.ProjectTemplates.IntegrationTests/Snapshots/aiagent-webapi/aiagent-webapi.oai.verified/aiagent-webapi/aiagent-webapi.csproj
@@ -4,16 +4,16 @@
net10.0enableenable
- secret
+ {00000000-0000-0000-0000-000000000000}
-
-
-
-
-
-
+
+
+
+
+
+
diff --git a/test/ProjectTemplates/Microsoft.Agents.AI.ProjectTemplates.IntegrationTests/Snapshots/aiagent-webapi.Ollama.verified/aiagent-webapi/appsettings.json b/test/ProjectTemplates/Microsoft.Agents.AI.ProjectTemplates.IntegrationTests/Snapshots/aiagent-webapi/aiagent-webapi.oai.verified/aiagent-webapi/appsettings.json
similarity index 100%
rename from test/ProjectTemplates/Microsoft.Agents.AI.ProjectTemplates.IntegrationTests/Snapshots/aiagent-webapi.Ollama.verified/aiagent-webapi/appsettings.json
rename to test/ProjectTemplates/Microsoft.Agents.AI.ProjectTemplates.IntegrationTests/Snapshots/aiagent-webapi/aiagent-webapi.oai.verified/aiagent-webapi/appsettings.json
diff --git a/test/ProjectTemplates/Microsoft.Agents.AI.ProjectTemplates.IntegrationTests/WebApiAgentTemplateExecutionTests.cs b/test/ProjectTemplates/Microsoft.Agents.AI.ProjectTemplates.IntegrationTests/WebApiAgentTemplateExecutionTests.cs
deleted file mode 100644
index 2462a7bd002..00000000000
--- a/test/ProjectTemplates/Microsoft.Agents.AI.ProjectTemplates.IntegrationTests/WebApiAgentTemplateExecutionTests.cs
+++ /dev/null
@@ -1,123 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-using System;
-using System.Collections.Generic;
-using System.Threading.Tasks;
-using Microsoft.Shared.ProjectTemplates.Tests;
-using Xunit;
-using Xunit.Abstractions;
-
-namespace Microsoft.Agents.AI.ProjectTemplates.Tests;
-
-///
-/// Contains execution tests for the "AI Agent Web API" template.
-///
-///
-/// In addition to validating that the templates build and restore correctly,
-/// these tests are also responsible for template component governance reporting.
-/// This is because the generated output is left on disk after tests complete,
-/// most importantly the project.assets.json file that gets created during restore.
-/// Therefore, it's *critical* that these tests remain in a working state,
-/// as disabling them will also disable CG reporting.
-///
-public class WebApiAgentTemplateExecutionTests : TemplateExecutionTestBase, ITemplateExecutionTestConfigurationProvider
-{
- public WebApiAgentTemplateExecutionTests(TemplateExecutionTestFixture fixture, ITestOutputHelper outputHelper)
- : base(fixture, outputHelper)
- {
- }
-
- public static TemplateExecutionTestConfiguration Configuration { get; } = new()
- {
- TemplatePackageName = "Microsoft.Agents.AI.ProjectTemplates",
- TestOutputFolderPrefix = "WebApiAgent"
- };
-
- public static IEnumerable