Switched Azure Function to ASP.net
Some checks failed
CI Build and Deploy / build (push) Has been cancelled
Some checks failed
CI Build and Deploy / build (push) Has been cancelled
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.Azure.Functions.Worker;
|
using Microsoft.Azure.Functions.Worker; // ← SWAP: remove for AspNetCore
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using Registration.Data;
|
using Registration.Data;
|
||||||
using System.Security.Claims;
|
using System.Security.Claims;
|
||||||
@@ -17,13 +17,33 @@ namespace Registration.Functions;
|
|||||||
/// entraSubjectId is extracted from the validated
|
/// entraSubjectId is extracted from the validated
|
||||||
/// token — the client never supplies it.
|
/// token — the client never supplies it.
|
||||||
///
|
///
|
||||||
/// GET /api/registration/pending — Admin; requires Function key.
|
/// GET /api/registration/pending — Admin; requires internal API key.
|
||||||
/// GET /api/registration/item/{id} — Admin; requires Function key.
|
/// GET /api/registration/item/{id} — Admin; requires internal API key.
|
||||||
/// POST /api/registration/action/{id}/reject — Admin; requires Function key.
|
/// POST /api/registration/action/{id}/reject — Admin; requires internal API key.
|
||||||
/// POST /api/registration/action/{id}/complete — Admin; requires Function key.
|
/// POST /api/registration/action/{id}/complete — Admin; requires internal API key.
|
||||||
/// GET /api/health — Anonymous.
|
/// GET /api/health — Anonymous.
|
||||||
|
///
|
||||||
|
/// ═══════════════════════════════════════════════════════
|
||||||
|
/// HOST SWAP — three files change, everything else stays:
|
||||||
|
/// 1. Functions/RegistrationFunctions.cs ← this file
|
||||||
|
/// 2. Program.cs
|
||||||
|
/// 3. Registration.csproj
|
||||||
|
///
|
||||||
|
/// To switch to ASP.NET Core:
|
||||||
|
/// a) In this file: swap class declaration and method signatures (marked below)
|
||||||
|
/// b) In Program.cs: comment Azure Functions block, uncomment AspNetCore block
|
||||||
|
/// c) In Registration.csproj: swap ItemGroup (marked in that file)
|
||||||
|
/// d) In authConfig.js (client): update API_BASE_URL, remove API_FUNCTION_KEY
|
||||||
|
/// ═══════════════════════════════════════════════════════
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
||||||
|
// ── SWAP: Azure Functions class declaration ───────────────────────────────
|
||||||
public class RegistrationFunctions
|
public class RegistrationFunctions
|
||||||
|
// ── SWAP: AspNetCore class declaration ────────────────────────────────────
|
||||||
|
// [ApiController]
|
||||||
|
// [Route("api")]
|
||||||
|
// public class RegistrationFunctions : ControllerBase
|
||||||
|
// ─────────────────────────────────────────────────────────────────────────
|
||||||
{
|
{
|
||||||
private readonly IRegistrationDataService _data;
|
private readonly IRegistrationDataService _data;
|
||||||
private readonly ILogger<RegistrationFunctions> _log;
|
private readonly ILogger<RegistrationFunctions> _log;
|
||||||
@@ -54,21 +74,21 @@ public class RegistrationFunctions
|
|||||||
|
|
||||||
// ── Public: Register ─────────────────────────────────────────────────
|
// ── Public: Register ─────────────────────────────────────────────────
|
||||||
|
|
||||||
/// <summary>
|
// ── SWAP: Azure Functions ─────────────────────────────────────────────
|
||||||
/// Register a new prospect.
|
|
||||||
///
|
|
||||||
/// AuthorizationLevel.Anonymous at the trigger allows any caller with a valid
|
|
||||||
/// Bearer token — no Function key required from the browser.
|
|
||||||
/// The [Authorize] attribute ensures the JWT is present and valid before
|
|
||||||
/// the function body runs. entraSubjectId is extracted from token claims only.
|
|
||||||
/// </summary>
|
|
||||||
[Function("Register")]
|
[Function("Register")]
|
||||||
[Authorize]
|
[Authorize]
|
||||||
public async Task<IActionResult> Register(
|
public async Task<IActionResult> Register(
|
||||||
[HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = "registration/register")] HttpRequest req,
|
[HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = "registration/register")] HttpRequest req,
|
||||||
CancellationToken ct)
|
CancellationToken ct)
|
||||||
|
// ── SWAP: AspNetCore ──────────────────────────────────────────────────
|
||||||
|
// [HttpPost("registration/register")]
|
||||||
|
// [Authorize]
|
||||||
|
// public async Task<IActionResult> Register(CancellationToken ct)
|
||||||
|
// ─────────────────────────────────────────────────────────────────────
|
||||||
{
|
{
|
||||||
// Identity comes from the validated JWT — never from the request body
|
// AspNetCore only — uncomment when in AspNetCore mode:
|
||||||
|
// var req = HttpContext.Request;
|
||||||
|
|
||||||
var entraSubjectId = GetEntraSubjectId(req.HttpContext.User);
|
var entraSubjectId = GetEntraSubjectId(req.HttpContext.User);
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(entraSubjectId))
|
if (string.IsNullOrEmpty(entraSubjectId))
|
||||||
@@ -90,7 +110,6 @@ public class RegistrationFunctions
|
|||||||
if (request == null || string.IsNullOrWhiteSpace(request.BusinessName))
|
if (request == null || string.IsNullOrWhiteSpace(request.BusinessName))
|
||||||
return new BadRequestObjectResult(new { ok = false, error = "businessName is required" });
|
return new BadRequestObjectResult(new { ok = false, error = "businessName is required" });
|
||||||
|
|
||||||
// Stamp the server-validated identity — client-supplied value is ignored
|
|
||||||
request.EntraSubjectId = entraSubjectId;
|
request.EntraSubjectId = entraSubjectId;
|
||||||
|
|
||||||
_log.LogInformation("[Registration] POST register: {Name} by entra={EntraId}",
|
_log.LogInformation("[Registration] POST register: {Name} by entra={EntraId}",
|
||||||
@@ -106,11 +125,15 @@ public class RegistrationFunctions
|
|||||||
|
|
||||||
// ── Admin: List pending ───────────────────────────────────────────────
|
// ── Admin: List pending ───────────────────────────────────────────────
|
||||||
|
|
||||||
/// <summary>List all pending registrations. Called by Management API with Function key.</summary>
|
// ── SWAP: Azure Functions ─────────────────────────────────────────────
|
||||||
[Function("GetPending")]
|
[Function("GetPending")]
|
||||||
public async Task<IActionResult> GetPending(
|
public async Task<IActionResult> GetPending(
|
||||||
[HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "registration/pending")] HttpRequest req,
|
[HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "registration/pending")] HttpRequest req,
|
||||||
CancellationToken ct)
|
CancellationToken ct)
|
||||||
|
// ── SWAP: AspNetCore ──────────────────────────────────────────────────
|
||||||
|
// [HttpGet("registration/pending")]
|
||||||
|
// public async Task<IActionResult> GetPending(CancellationToken ct)
|
||||||
|
// ─────────────────────────────────────────────────────────────────────
|
||||||
{
|
{
|
||||||
_log.LogInformation("[Registration] GET pending");
|
_log.LogInformation("[Registration] GET pending");
|
||||||
var result = await _data.GetPendingAsync(ct);
|
var result = await _data.GetPendingAsync(ct);
|
||||||
@@ -119,12 +142,16 @@ public class RegistrationFunctions
|
|||||||
|
|
||||||
// ── Admin: Get by ID ─────────────────────────────────────────────────
|
// ── Admin: Get by ID ─────────────────────────────────────────────────
|
||||||
|
|
||||||
/// <summary>Get a single applicant by registration ID. Called by Management API.</summary>
|
// ── SWAP: Azure Functions ─────────────────────────────────────────────
|
||||||
[Function("GetById")]
|
[Function("GetById")]
|
||||||
public async Task<IActionResult> GetById(
|
public async Task<IActionResult> GetById(
|
||||||
[HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "registration/item/{registrationId}")] HttpRequest req,
|
[HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "registration/item/{registrationId}")] HttpRequest req,
|
||||||
string registrationId,
|
string registrationId,
|
||||||
CancellationToken ct)
|
CancellationToken ct)
|
||||||
|
// ── SWAP: AspNetCore ──────────────────────────────────────────────────
|
||||||
|
// [HttpGet("registration/item/{registrationId}")]
|
||||||
|
// public async Task<IActionResult> GetById(string registrationId, CancellationToken ct)
|
||||||
|
// ─────────────────────────────────────────────────────────────────────
|
||||||
{
|
{
|
||||||
_log.LogInformation("[Registration] GET {Id}", registrationId);
|
_log.LogInformation("[Registration] GET {Id}", registrationId);
|
||||||
|
|
||||||
@@ -137,13 +164,20 @@ public class RegistrationFunctions
|
|||||||
|
|
||||||
// ── Admin: Reject ────────────────────────────────────────────────────
|
// ── Admin: Reject ────────────────────────────────────────────────────
|
||||||
|
|
||||||
/// <summary>Reject a pending applicant. Called by Management after admin clicks Reject.</summary>
|
// ── SWAP: Azure Functions ─────────────────────────────────────────────
|
||||||
[Function("Reject")]
|
[Function("Reject")]
|
||||||
public async Task<IActionResult> Reject(
|
public async Task<IActionResult> Reject(
|
||||||
[HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = "registration/action/{registrationId}/reject")] HttpRequest req,
|
[HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = "registration/action/{registrationId}/reject")] HttpRequest req,
|
||||||
string registrationId,
|
string registrationId,
|
||||||
CancellationToken ct)
|
CancellationToken ct)
|
||||||
|
// ── SWAP: AspNetCore ──────────────────────────────────────────────────
|
||||||
|
// [HttpPost("registration/action/{registrationId}/reject")]
|
||||||
|
// public async Task<IActionResult> Reject(string registrationId, CancellationToken ct)
|
||||||
|
// ─────────────────────────────────────────────────────────────────────
|
||||||
{
|
{
|
||||||
|
// AspNetCore only — uncomment when in AspNetCore mode:
|
||||||
|
// var req = HttpContext.Request;
|
||||||
|
|
||||||
RejectBody? body = null;
|
RejectBody? body = null;
|
||||||
try { body = await JsonSerializer.DeserializeAsync<RejectBody>(req.Body, JsonOpts, ct); }
|
try { body = await JsonSerializer.DeserializeAsync<RejectBody>(req.Body, JsonOpts, ct); }
|
||||||
catch { /* optional body */ }
|
catch { /* optional body */ }
|
||||||
@@ -159,19 +193,22 @@ public class RegistrationFunctions
|
|||||||
return new OkObjectResult(result);
|
return new OkObjectResult(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ── Admin: Complete (approved) ────────────────────────────────────────
|
// ── Admin: Complete ───────────────────────────────────────────────────
|
||||||
|
|
||||||
/// <summary>
|
// ── SWAP: Azure Functions ─────────────────────────────────────────────
|
||||||
/// Mark a registration as approved/completed.
|
|
||||||
/// Called by Management after spClientManagement.create succeeds.
|
|
||||||
/// Receives the platformClientId to link the registration to the platform record.
|
|
||||||
/// </summary>
|
|
||||||
[Function("Complete")]
|
[Function("Complete")]
|
||||||
public async Task<IActionResult> Complete(
|
public async Task<IActionResult> Complete(
|
||||||
[HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = "registration/action/{registrationId}/complete")] HttpRequest req,
|
[HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = "registration/action/{registrationId}/complete")] HttpRequest req,
|
||||||
string registrationId,
|
string registrationId,
|
||||||
CancellationToken ct)
|
CancellationToken ct)
|
||||||
|
// ── SWAP: AspNetCore ──────────────────────────────────────────────────
|
||||||
|
// [HttpPost("registration/action/{registrationId}/complete")]
|
||||||
|
// public async Task<IActionResult> Complete(string registrationId, CancellationToken ct)
|
||||||
|
// ─────────────────────────────────────────────────────────────────────
|
||||||
{
|
{
|
||||||
|
// AspNetCore only — uncomment when in AspNetCore mode:
|
||||||
|
// var req = HttpContext.Request;
|
||||||
|
|
||||||
CompleteBody? body = null;
|
CompleteBody? body = null;
|
||||||
try { body = await JsonSerializer.DeserializeAsync<CompleteBody>(req.Body, JsonOpts, ct); }
|
try { body = await JsonSerializer.DeserializeAsync<CompleteBody>(req.Body, JsonOpts, ct); }
|
||||||
catch { /* optional body */ }
|
catch { /* optional body */ }
|
||||||
@@ -189,10 +226,14 @@ public class RegistrationFunctions
|
|||||||
|
|
||||||
// ── Health ───────────────────────────────────────────────────────────
|
// ── Health ───────────────────────────────────────────────────────────
|
||||||
|
|
||||||
/// <summary>Health check — anonymous, no auth required.</summary>
|
// ── SWAP: Azure Functions ─────────────────────────────────────────────
|
||||||
[Function("Health")]
|
[Function("Health")]
|
||||||
public IActionResult Health(
|
public IActionResult Health(
|
||||||
[HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "health")] HttpRequest req)
|
[HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "health")] HttpRequest req)
|
||||||
|
// ── SWAP: AspNetCore ──────────────────────────────────────────────────
|
||||||
|
// [HttpGet("health")]
|
||||||
|
// public IActionResult Health()
|
||||||
|
// ─────────────────────────────────────────────────────────────────────
|
||||||
{
|
{
|
||||||
return new OkObjectResult(new
|
return new OkObjectResult(new
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,36 +1,76 @@
|
|||||||
using Microsoft.Azure.Functions.Worker;
|
using Microsoft.Azure.Functions.Worker; // ← SWAP: remove for AspNetCore
|
||||||
|
using Microsoft.Extensions.Configuration;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Microsoft.Extensions.Hosting;
|
using Microsoft.Extensions.Hosting;
|
||||||
using Microsoft.Identity.Web;
|
using Microsoft.Identity.Web;
|
||||||
using Registration.Data;
|
using Registration.Data;
|
||||||
using Registration.Mock;
|
using Registration.Mock;
|
||||||
|
|
||||||
|
// ─────────────────────────────────────────────────────────────────────────────
|
||||||
|
// Shared service registrations — identical in both hosting modes.
|
||||||
|
// Never changes regardless of which block is active below.
|
||||||
|
// ─────────────────────────────────────────────────────────────────────────────
|
||||||
|
void ConfigureServices(IServiceCollection services, IConfiguration config)
|
||||||
|
{
|
||||||
|
// JWT authentication — Entra External ID (CIAM)
|
||||||
|
// Validates Bearer tokens issued by usimclients.ciamlogin.com.
|
||||||
|
// AzureAd config comes from local.settings.json (Functions) or
|
||||||
|
// appsettings.json / environment variables (AspNetCore).
|
||||||
|
services.AddAuthentication()
|
||||||
|
.AddMicrosoftIdentityWebApi(config.GetSection("AzureAd"));
|
||||||
|
|
||||||
|
services.AddAuthorization();
|
||||||
|
|
||||||
|
// Data layer — swap between MockDataService (no DB) and SqlDataService (dbRegistration).
|
||||||
|
// MockDataService: no connection string required, seeds 4 test applicants.
|
||||||
|
// SqlDataService: requires ConnectionStrings:Sql pointed at dbRegistration.
|
||||||
|
// Calls dbo.spRegistration with @action/@rqst/@resp OUTPUT pattern.
|
||||||
|
services.AddSingleton<SqlService>();
|
||||||
|
services.AddSingleton<IRegistrationDataService, SqlDataService>();
|
||||||
|
// ── swap data layer here if needed ──────────────────────────────────────
|
||||||
|
// services.AddSingleton<IRegistrationDataService, MockDataService>();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ═════════════════════════════════════════════════════════════════════════════
|
||||||
|
// SWAP: Azure Functions host
|
||||||
|
// Active when deployed to Azure Functions or running via: func start
|
||||||
|
// ═════════════════════════════════════════════════════════════════════════════
|
||||||
var host = new HostBuilder()
|
var host = new HostBuilder()
|
||||||
.ConfigureFunctionsWebApplication()
|
.ConfigureFunctionsWebApplication()
|
||||||
.ConfigureServices((context, services) =>
|
.ConfigureServices((ctx, services) =>
|
||||||
{
|
{
|
||||||
services.AddApplicationInsightsTelemetryWorkerService();
|
services.AddApplicationInsightsTelemetryWorkerService();
|
||||||
services.ConfigureFunctionsApplicationInsights();
|
services.ConfigureFunctionsApplicationInsights();
|
||||||
|
ConfigureServices(services, ctx.Configuration);
|
||||||
// =============================================================
|
|
||||||
// JWT Authentication — Entra External ID (CIAM)
|
|
||||||
// Validates Bearer tokens issued by usimclients.ciamlogin.com.
|
|
||||||
// AzureAd config is in local.settings.json (dev) or Function App
|
|
||||||
// Configuration (production) using AzureAd__ prefix.
|
|
||||||
// =============================================================
|
|
||||||
services.AddAuthentication()
|
|
||||||
.AddMicrosoftIdentityWebApi(context.Configuration.GetSection("AzureAd"));
|
|
||||||
|
|
||||||
services.AddAuthorization();
|
|
||||||
|
|
||||||
// =============================================================
|
|
||||||
// Data layer — SqlDataService backed by dbRegistration.
|
|
||||||
// Connection string: ConnectionStrings:Sql in local.settings.json
|
|
||||||
// or the "Sql" connection string in Function App Configuration.
|
|
||||||
// =============================================================
|
|
||||||
services.AddSingleton<SqlService>();
|
|
||||||
services.AddSingleton<IRegistrationDataService, SqlDataService>();
|
|
||||||
})
|
})
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
host.Run();
|
host.Run();
|
||||||
|
|
||||||
|
// ═════════════════════════════════════════════════════════════════════════════
|
||||||
|
// SWAP: ASP.NET Core host
|
||||||
|
// Active when running in podman-compose or dotnet run (self-hosted).
|
||||||
|
// Also update RegistrationFunctions.cs and Registration.csproj.
|
||||||
|
// ═════════════════════════════════════════════════════════════════════════════
|
||||||
|
// var builder = WebApplication.CreateBuilder(args);
|
||||||
|
//
|
||||||
|
// ConfigureServices(builder.Services, builder.Configuration);
|
||||||
|
// builder.Services.AddControllers();
|
||||||
|
//
|
||||||
|
// // CORS — replace with actual client origin in production
|
||||||
|
// builder.Services.AddCors(options => options.AddDefaultPolicy(policy =>
|
||||||
|
// policy.WithOrigins(
|
||||||
|
// builder.Configuration["Cors:AllowedOrigin"] ?? "http://localhost:3001"
|
||||||
|
// )
|
||||||
|
// .AllowAnyHeader()
|
||||||
|
// .AllowAnyMethod()));
|
||||||
|
//
|
||||||
|
// var app = builder.Build();
|
||||||
|
//
|
||||||
|
// app.UseCors();
|
||||||
|
// app.UseAuthentication();
|
||||||
|
// app.UseAuthorization();
|
||||||
|
// app.MapControllers();
|
||||||
|
//
|
||||||
|
// await app.RunAsync();
|
||||||
|
// ─────────────────────────────────────────────────────────────────────────────
|
||||||
@@ -1,34 +1,59 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net8.0</TargetFramework>
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
<AzureFunctionsVersion>v4</AzureFunctionsVersion>
|
<OutputType>Exe</OutputType>
|
||||||
<OutputType>Exe</OutputType>
|
<Nullable>enable</Nullable>
|
||||||
<Nullable>enable</Nullable>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<RootNamespace>Registration</RootNamespace>
|
||||||
<RootNamespace>Registration</RootNamespace>
|
<!-- SWAP: Azure Functions only — remove for AspNetCore -->
|
||||||
</PropertyGroup>
|
<AzureFunctionsVersion>v4</AzureFunctionsVersion>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
═══════════════════════════════════════════════════════════════════════════
|
||||||
|
SWAP: Azure Functions packages (active)
|
||||||
|
To switch to AspNetCore: comment this ItemGroup, uncomment the one below,
|
||||||
|
and remove <AzureFunctionsVersion> from PropertyGroup above.
|
||||||
|
═══════════════════════════════════════════════════════════════════════════
|
||||||
|
-->
|
||||||
|
<ItemGroup>
|
||||||
|
<FrameworkReference Include="Microsoft.AspNetCore.App" />
|
||||||
|
<PackageReference Include="Microsoft.Azure.Functions.Worker" Version="2.51.0" />
|
||||||
|
<PackageReference Include="Microsoft.Azure.Functions.Worker.Extensions.Http" Version="3.3.0" />
|
||||||
|
<PackageReference Include="Microsoft.Azure.Functions.Worker.Extensions.Http.AspNetCore" Version="2.1.0" />
|
||||||
|
<PackageReference Include="Microsoft.Azure.Functions.Worker.Sdk" Version="2.0.7" />
|
||||||
|
<PackageReference Include="Microsoft.ApplicationInsights.WorkerService" Version="2.22.0" />
|
||||||
|
<PackageReference Include="Microsoft.Azure.Functions.Worker.ApplicationInsights" Version="2.50.0" />
|
||||||
|
<PackageReference Include="Microsoft.Data.SqlClient" Version="6.1.4" />
|
||||||
|
<PackageReference Include="Microsoft.Identity.Web" Version="4.5.0" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
═══════════════════════════════════════════════════════════════════════════
|
||||||
|
SWAP: ASP.NET Core packages
|
||||||
|
To switch to AspNetCore: uncomment this ItemGroup, comment the one above,
|
||||||
|
and remove <AzureFunctionsVersion> from PropertyGroup above.
|
||||||
|
═══════════════════════════════════════════════════════════════════════════
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<FrameworkReference Include="Microsoft.AspNetCore.App" />
|
<FrameworkReference Include="Microsoft.AspNetCore.App" />
|
||||||
<PackageReference Include="Microsoft.Azure.Functions.Worker" Version="2.51.0" />
|
|
||||||
<PackageReference Include="Microsoft.Azure.Functions.Worker.Extensions.Http" Version="3.3.0" />
|
|
||||||
<PackageReference Include="Microsoft.Azure.Functions.Worker.Extensions.Http.AspNetCore" Version="2.1.0" />
|
|
||||||
<PackageReference Include="Microsoft.Azure.Functions.Worker.Sdk" Version="2.0.7" />
|
|
||||||
<PackageReference Include="Microsoft.ApplicationInsights.WorkerService" Version="2.22.0" />
|
|
||||||
<PackageReference Include="Microsoft.Azure.Functions.Worker.ApplicationInsights" Version="2.50.0" />
|
|
||||||
<PackageReference Include="Microsoft.Data.SqlClient" Version="6.1.4" />
|
<PackageReference Include="Microsoft.Data.SqlClient" Version="6.1.4" />
|
||||||
<PackageReference Include="Microsoft.Identity.Web" Version="4.5.0" />
|
<PackageReference Include="Microsoft.Identity.Web" Version="4.5.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
-->
|
||||||
|
|
||||||
<ItemGroup>
|
<!--
|
||||||
<None Update="host.json">
|
Azure Functions host files — present in both modes, ignored in AspNetCore.
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
host.json and local.settings.json are inert when running as a plain web app.
|
||||||
</None>
|
-->
|
||||||
<None Update="local.settings.json">
|
<ItemGroup>
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<None Update="host.json">
|
||||||
<CopyToPublishDirectory>Never</CopyToPublishDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</None>
|
</None>
|
||||||
</ItemGroup>
|
<None Update="local.settings.json">
|
||||||
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
|
<CopyToPublishDirectory>Never</CopyToPublishDirectory>
|
||||||
|
</None>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
Reference in New Issue
Block a user