DreamineVMS.Web 1.0.0.0
DreamineVMS 에이전트가 제공하는 HLS 카메라 영상을 브라우저에서 관리·재생하는 원격 CCTV 웹 서비스입니다.
로딩중...
검색중...
일치하는것 없음
Program.cs 파일 참조

이 파일의 소스 코드 페이지로 가기

함수

builder.Configuration. AddUserSecrets ("codemaru-oauth-2ba4e1b2")
builder.Services. AddRazorComponents () .AddInteractiveServerComponents()
builder.Services. Configure< CircuitOptions > (o=> o.DetailedErrors=true)
builder.Services. AddHttpClient ()
builder.Services. AddDreamineIdentityWeb (authOptions, usersDbPath)
builder.Services. AddSingleton< VmsDatabase > ()
builder.Services. AddSingleton< VmsUserService > ()
builder.Services. AddSingleton< VmsSessionService > ()
builder.Services. AddScoped< VmsAuthState > ()
builder.Services. AddSingleton< IVmsCameraRepository, SqliteCameraRepository > ()
builder.Services. AddSingleton< AgentTokenService > ()
builder.Services. AddSingleton< HlsSegmentStore > ()
app. UseForwardedHeaders ()
app. UseStaticFiles (new StaticFileOptions { ContentTypeProvider=provider })
app. UseRouting ()
app. UseAuthentication ()
app. UseAuthorization ()
app. UseAntiforgery ()
app. Use (async(ctx, next)=> { var ua=ctx.Request.Headers.UserAgent.ToString();bool looksLikeBrowser=ua.Contains("AppleWebKit") &&(ua.Contains("Chrome")||ua.Contains("Safari")||ua.Contains("Mobile"));bool isCrawler=!looksLikeBrowser &&(ua.Contains("Kakaotalk", StringComparison.OrdinalIgnoreCase)||ua.Contains("kakaostory", StringComparison.OrdinalIgnoreCase)||ua.Contains("Naverbot", StringComparison.OrdinalIgnoreCase)||ua.Contains("DaumApps", StringComparison.OrdinalIgnoreCase))||(ua.Contains("facebookexternalhit", StringComparison.OrdinalIgnoreCase)||ua.Contains("Twitterbot", StringComparison.OrdinalIgnoreCase)||ua.Contains("LinkedInBot", StringComparison.OrdinalIgnoreCase)||ua.Contains("Slackbot", StringComparison.OrdinalIgnoreCase)||ua.Contains("Discordbot", StringComparison.OrdinalIgnoreCase));if(!isCrawler) { await next();return;} var path=ctx.Request.Path.Value ?? "";if(path=="/"||path=="") { var siteUrl=$"https://{ctx.Request.Host}";const string title="CodeMaru CCTV Viewer";const string desc="카메라 주인은 앱 하나 설치, 보는 사람은 링크만으로 실시간 시청";var image=$"{siteUrl}/images/cctvviewer-og.png";ctx.Response.ContentType="text/html; charset=utf-8";await ctx.Response.WriteAsync($""" <!DOCTYPE html> <html lang="ko"> <head> <meta charset="utf-8"/> <title>{title}</title> <meta property="og:type" content="website"/> <meta property="og:url" content="{siteUrl}/"/> <meta property="og:title" content="{title}"/> <meta property="og:description" content="{desc}"/> <meta property="og:image" content="{image}"/> <meta property="og:site_name" content="CodeMaru CCTV Viewer"/> <meta name="description" content="{desc}"/> </head> <body><p><a href="{siteUrl}/">{title}</a></p></body> </html> """);return;} var parts=path.Trim('/').Split('/');if(parts.Length==2 &&parts[1]=="live") { var slug=parts[0];var userSvc=ctx.RequestServices.GetRequiredService< VmsUserService >();var user=await userSvc.FindBySlugAsync(slug);if(user is not null) { var siteUrl=$"https://{ctx.Request.Host}";var pageUrl=$"{siteUrl}/{slug}/live";var title=string.IsNullOrWhiteSpace(user.OgTitle) ? $"{user.DisplayName} CCTV Live" :user.OgTitle;var desc=string.IsNullOrWhiteSpace(user.OgDescription) ? $"{user.DisplayName}의 실시간 카메라 스트림입니다." :user.OgDescription;var image=string.IsNullOrWhiteSpace(user.OgImage) ? $"{siteUrl}/img/og-default.png" :user.OgImage;ctx.Response.ContentType="text/html; charset=utf-8";await ctx.Response.WriteAsync($""" <!DOCTYPE html> <html lang="ko"> <head> <meta charset="utf-8"/> <title>{title}</title> <meta property="og:type" content="website"/> <meta property="og:url" content="{pageUrl}"/> <meta property="og:title" content="{title}"/> <meta property="og:description" content="{desc}"/> <meta property="og:image" content="{image}"/> <meta property="og:site_name" content="CodeMaru CCTV Viewer"/> <meta name="description" content="{desc}"/> </head> <body><p><a href="{pageUrl}">{title}</a></p></body> </html> """);return;} } await next();})
app. MapPost ("/api/agent/login", async(AgentLoginRequest req, HttpContext ctx, VmsUserService users, AgentTokenService tokens, IVmsCameraRepository repo)=> { var(ok, _, user)=await users.LoginAsync(req.Email, req.Password);if(!ok||user is null) return Results.Unauthorized();var token=tokens.Issue(user);var cameras=repo.GetAll() .Where(c=> c.TenantId==user.Id &&c.Enabled &&!c.IsDirectHls) .Select(c=> new AgentCameraDto(c.Id, c.Name, c.Host, c.RtspUrl, c.AutoReconnect, c.IsPublic)) .ToList();var hlsStore=ctx.RequestServices.GetRequiredService< HlsSegmentStore >();foreach(var cam in cameras) hlsStore.ClearCameraHls(user.Id, cam.Id);return Results.Ok(new AgentLoginResponse(token, user.Id, cameras));})
app. MapPost ("/api/agent/sync-cameras", async(AgentSyncRequest req, AgentTokenService tokens, IVmsCameraRepository repo, HlsSegmentStore store)=> { var user=tokens.Validate(req.Token);if(user is null) return Results.Unauthorized();var existing=repo.GetAll().Where(c=> c.TenantId==user.Id).ToDictionary(c=> c.Id);int order=existing.Count > 0 ? existing.Values.Max(c=> c.DisplayOrder)+1 :1;foreach(var cam in req.Cameras) { var device=new DreamineVMS.Web.Models.CameraDevice { Id=cam.Id, TenantId=user.Id, Name=cam.Name, Host=cam.Host, RtspUrl=cam.RtspUrl, DisplayOrder=existing.ContainsKey(cam.Id) ? existing[cam.Id].DisplayOrder :order++, Enabled=true, AutoReconnect=cam.AutoReconnect, IsPublic=cam.IsPublic };if(existing.ContainsKey(cam.Id)) await repo.UpdateAsync(device);else await repo.AddAsync(device);} return Results.Ok();})
app. MapPost ("/api/agent/hls/{token}/{cameraId}/{filename}", async(string token, string cameraId, string filename, HttpContext ctx, AgentTokenService tokens, HlsSegmentStore store, ILoggerFactory loggerFactory)=> { var log=loggerFactory.CreateLogger("AgentPush");var user=tokens.Validate(token);if(user is null) { log.LogWarning("[Push] 토큰 인증 실패: {cam}/{file}", cameraId, filename);return Results.Unauthorized();} await store.SaveSegmentAsync(user.Id, cameraId, filename, ctx.Request.Body);log.LogDebug("[Push] OK {cam}/{file} ({bytes}B)", cameraId, filename, ctx.Request.ContentLength ?? -1);return Results.Ok();})
app. MapGet ("/hls/{tenantId}/{cameraId}/{filename}",(string tenantId, string cameraId, string filename, HlsSegmentStore store, HttpContext ctx, ILoggerFactory loggerFactory)=> { var log=loggerFactory.CreateLogger("HlsServe");var(stream, ct)=store.GetFile(tenantId, cameraId, filename);if(stream is null) { log.LogWarning("[Serve] 404 {cam}/{file}", cameraId, filename);return Results.NotFound();} if(filename.EndsWith(".m3u8", StringComparison.OrdinalIgnoreCase)) { ctx.Response.Headers.CacheControl="no-store, no-cache, must-revalidate, max-age=0";ctx.Response.Headers.Pragma="no-cache";ctx.Response.Headers.Expires="0";} else { ctx.Response.Headers.CacheControl="public, max-age=60, immutable";} return Results.Stream(stream, ct);})
app. MapPost ("/api/upload/og-image", async(HttpContext ctx, AgentTokenService tokens, IWebHostEnvironment env)=> { var sessionToken=ctx.Request.Headers["X-Session-Token"].ToString();if(string.IsNullOrWhiteSpace(sessionToken)) return Results.Unauthorized();var sessSvc=ctx.RequestServices.GetRequiredService< VmsSessionService >();var user=sessSvc.ValidateToken(sessionToken);if(user is null) return Results.Unauthorized();if(!ctx.Request.HasFormContentType) return Results.BadRequest("multipart form required");var form=await ctx.Request.ReadFormAsync();var file=form.Files.GetFile("file");if(file is null||file.Length==0) return Results.BadRequest("no file");var ext=Path.GetExtension(file.FileName).ToLowerInvariant();if(ext is not(".jpg" or ".jpeg" or ".png" or ".webp" or ".gif")) return Results.BadRequest("허용되지 않는 파일 형식입니다.");if(file.Length > 5 *1024 *1024) return Results.BadRequest("파일이 너무 큽니다 (최대 5MB).");var saveDir=Path.Combine(env.WebRootPath, "images", "og");Directory.CreateDirectory(saveDir);var fileName=$"{user.PublicSlug}-{DateTimeOffset.UtcNow.ToUnixTimeSeconds()}{ext}";var savePath=Path.Combine(saveDir, fileName);await using var fs=File.Create(savePath);await file.CopyToAsync(fs);var url=$"https://{ctx.Request.Host}/images/og/{fileName}";return Results.Ok(new { url });})
app. MapRazorComponents< AppShell > () .AddInteractiveServerRenderMode()
app. Run ()
static string ResolvePath (string? configuredPath, string fallback)
record AgentLoginRequest (string Email, string Password)
record AgentCameraDto (string Id, string Name, string Host, string RtspUrl, bool AutoReconnect, bool IsPublic)
record AgentLoginResponse (string Token, string TenantId, List< AgentCameraDto > Cameras)
record AgentSyncRequest (string Token, List< AgentCameraDto > Cameras)

변수

var builder = WebApplication.CreateBuilder(args)
AuthOptions authOptions
string usersDbPath
var app = builder.Build()
var provider = new Microsoft.AspNetCore.StaticFiles.FileExtensionContentTypeProvider()
provider. Mappings [".exe"] = "application/octet-stream"

함수 문서화

◆ AddDreamineIdentityWeb()

builder.Services. AddDreamineIdentityWeb ( authOptions ,
usersDbPath  )

다음을 참조함 : authOptions, builder, usersDbPath.

◆ AddHttpClient()

builder.Services. AddHttpClient ( )

다음을 참조함 : builder.

◆ AddRazorComponents()

builder.Services. AddRazorComponents ( )

◆ AddScoped< VmsAuthState >()

builder.Services. AddScoped< VmsAuthState > ( )

다음을 참조함 : builder.

◆ AddSingleton< AgentTokenService >()

builder.Services. AddSingleton< AgentTokenService > ( )

다음을 참조함 : builder.

◆ AddSingleton< HlsSegmentStore >()

builder.Services. AddSingleton< HlsSegmentStore > ( )

다음을 참조함 : builder.

◆ AddSingleton< IVmsCameraRepository, SqliteCameraRepository >()

builder.Services. AddSingleton< IVmsCameraRepository, SqliteCameraRepository > ( )

다음을 참조함 : builder.

◆ AddSingleton< VmsDatabase >()

builder.Services. AddSingleton< VmsDatabase > ( )

다음을 참조함 : builder.

◆ AddSingleton< VmsSessionService >()

builder.Services. AddSingleton< VmsSessionService > ( )

다음을 참조함 : builder.

◆ AddSingleton< VmsUserService >()

builder.Services. AddSingleton< VmsUserService > ( )

다음을 참조함 : builder.

◆ AddUserSecrets()

builder.Configuration. AddUserSecrets ( "codemaru-oauth-2ba4e1b2" )

다음을 참조함 : builder.

◆ AgentCameraDto()

record AgentCameraDto ( string Id,
string Name,
string Host,
string RtspUrl,
bool AutoReconnect,
bool IsPublic )

Agent Camera Dto 기능과 관련 상태를 캡슐화합니다.

다음에 의해서 참조됨 : MapPost().

이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ AgentLoginRequest()

record AgentLoginRequest ( string Email,
string Password )

Agent Login Request 기능과 관련 상태를 캡슐화합니다.

다음에 의해서 참조됨 : MapPost().

이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ AgentLoginResponse()

record AgentLoginResponse ( string Token,
string TenantId,
List< AgentCameraDto > Cameras )

Agent Login Response 기능과 관련 상태를 캡슐화합니다.

다음에 의해서 참조됨 : MapPost().

이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ AgentSyncRequest()

record AgentSyncRequest ( string Token,
List< AgentCameraDto > Cameras )

Agent Sync Request 기능과 관련 상태를 캡슐화합니다.

다음에 의해서 참조됨 : MapPost().

이 함수를 호출하는 함수들에 대한 그래프입니다.:

◆ Configure< CircuitOptions >()

builder.Services. Configure< CircuitOptions > ( o ,
o. DetailedErrors = true )

다음을 참조함 : builder.

◆ MapGet()

app. MapGet ( "/hls/{tenantId}/{cameraId}/{filename}" ,
(string tenantId, string cameraId, string filename, HlsSegmentStore store, HttpContext ctx, ILoggerFactory loggerFactory) ,
{ var log=loggerFactory.CreateLogger("HlsServe");var(stream, ct)=store.GetFile(tenantId, cameraId, filename);if(stream is null) { log.LogWarning("[Serve] 404 {cam}/{file}", cameraId, filename);return Results.NotFound();} if(filename.EndsWith(".m3u8", StringComparison.OrdinalIgnoreCase)) { ctx.Response.Headers.CacheControl="no-store, no-cache, must-revalidate, max-age=0";ctx.Response.Headers.Pragma="no-cache";ctx.Response.Headers.Expires="0";} else { ctx.Response.Headers.CacheControl="public, max-age=60, immutable";} return Results.Stream(stream, ct);}  )

다음을 참조함 : app, DreamineVMS.Web.Services.Hls.HlsSegmentStore.GetFile().

이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:

◆ MapPost() [1/4]

app. MapPost ( "/api/agent/hls/{token}/{cameraId}/{filename}" ,
async(string token, string cameraId, string filename, HttpContext ctx, AgentTokenService tokens, HlsSegmentStore store, ILoggerFactory loggerFactory) ,
{ var log=loggerFactory.CreateLogger("AgentPush");var user=tokens.Validate(token);if(user is null) { log.LogWarning("[Push] 토큰 인증 실패: {cam}/{file}", cameraId, filename);return Results.Unauthorized();} await store.SaveSegmentAsync(user.Id, cameraId, filename, ctx.Request.Body);log.LogDebug("[Push] OK {cam}/{file} ({bytes}B)", cameraId, filename, ctx.Request.ContentLength ?? -1);return Results.Ok();}  )

다음을 참조함 : app, DreamineVMS.Web.Services.Hls.HlsSegmentStore.SaveSegmentAsync(), DreamineVMS.Web.Services.Agent.AgentTokenService.Validate().

이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:

◆ MapPost() [2/4]

app. MapPost ( "/api/agent/login" ,
async(AgentLoginRequest req, HttpContext ctx, VmsUserService users, AgentTokenService tokens, IVmsCameraRepository repo) ,
{ var(ok, _, user)=await users.LoginAsync(req.Email, req.Password);if(!ok||user is null) return Results.Unauthorized();var token=tokens.Issue(user);var cameras=repo.GetAll() .Where(c=> c.TenantId==user.Id &&c.Enabled &&!c.IsDirectHls) .Select(c=> new AgentCameraDto(c.Id, c.Name, c.Host, c.RtspUrl, c.AutoReconnect, c.IsPublic)) .ToList();var hlsStore=ctx.RequestServices.GetRequiredService< HlsSegmentStore >();foreach(var cam in cameras) hlsStore.ClearCameraHls(user.Id, cam.Id);return Results.Ok(new AgentLoginResponse(token, user.Id, cameras));}  )

◆ MapPost() [3/4]

app. MapPost ( "/api/agent/sync-cameras" ,
async(AgentSyncRequest req, AgentTokenService tokens, IVmsCameraRepository repo, HlsSegmentStore store) ,
{ var user=tokens.Validate(req.Token);if(user is null) return Results.Unauthorized();var existing=repo.GetAll().Where(c=> c.TenantId==user.Id).ToDictionary(c=> c.Id);int order=existing.Count > 0 ? existing.Values.Max(c=> c.DisplayOrder)+1 :1;foreach(var cam in req.Cameras) { var device=new DreamineVMS.Web.Models.CameraDevice { Id=cam.Id, TenantId=user.Id, Name=cam.Name, Host=cam.Host, RtspUrl=cam.RtspUrl, DisplayOrder=existing.ContainsKey(cam.Id) ? existing[cam.Id].DisplayOrder :order++, Enabled=true, AutoReconnect=cam.AutoReconnect, IsPublic=cam.IsPublic };if(existing.ContainsKey(cam.Id)) await repo.UpdateAsync(device);else await repo.AddAsync(device);} return Results.Ok();}  )

◆ MapPost() [4/4]

app. MapPost ( "/api/upload/og-image" ,
async(HttpContext ctx, AgentTokenService tokens, IWebHostEnvironment env) ,
{ var sessionToken=ctx.Request.Headers["X-Session-Token"].ToString();if(string.IsNullOrWhiteSpace(sessionToken)) return Results.Unauthorized();var sessSvc=ctx.RequestServices.GetRequiredService< VmsSessionService >();var user=sessSvc.ValidateToken(sessionToken);if(user is null) return Results.Unauthorized();if(!ctx.Request.HasFormContentType) return Results.BadRequest("multipart form required");var form=await ctx.Request.ReadFormAsync();var file=form.Files.GetFile("file");if(file is null||file.Length==0) return Results.BadRequest("no file");var ext=Path.GetExtension(file.FileName).ToLowerInvariant();if(ext is not(".jpg" or ".jpeg" or ".png" or ".webp" or ".gif")) return Results.BadRequest("허용되지 않는 파일 형식입니다.");if(file.Length > 5 *1024 *1024) return Results.BadRequest("파일이 너무 큽니다 (최대 5MB).");var saveDir=Path.Combine(env.WebRootPath, "images", "og");Directory.CreateDirectory(saveDir);var fileName=$"{user.PublicSlug}-{DateTimeOffset.UtcNow.ToUnixTimeSeconds()}{ext}";var savePath=Path.Combine(saveDir, fileName);await using var fs=File.Create(savePath);await file.CopyToAsync(fs);var url=$"https://{ctx.Request.Host}/images/og/{fileName}";return Results.Ok(new { url });}  )

다음을 참조함 : app, DreamineVMS.Web.Services.Auth.VmsSessionService.ValidateToken().

이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:

◆ MapRazorComponents< AppShell >()

app. MapRazorComponents< AppShell > ( )

다음을 참조함 : app.

◆ ResolvePath()

string ResolvePath ( string? configuredPath,
string fallback )
static

Program.cs 파일의 331 번째 라인에서 정의되었습니다.

332{
333 if (string.IsNullOrWhiteSpace(configuredPath))
334 {
335 return fallback;
336 }
337
338 return Path.IsPathRooted(configuredPath)
339 ? configuredPath
340 : Path.GetFullPath(Path.Combine(AppContext.BaseDirectory, configuredPath));
341}

◆ Run()

app. Run ( )

다음을 참조함 : app.

◆ Use()

app. Use ( async(ctx, next) ,
{ var ua=ctx.Request.Headers.UserAgent.ToString();bool looksLikeBrowser=ua.Contains("AppleWebKit") &&(ua.Contains("Chrome")||ua.Contains("Safari")||ua.Contains("Mobile"));bool isCrawler=!looksLikeBrowser &&(ua.Contains("Kakaotalk", StringComparison.OrdinalIgnoreCase)||ua.Contains("kakaostory", StringComparison.OrdinalIgnoreCase)||ua.Contains("Naverbot", StringComparison.OrdinalIgnoreCase)||ua.Contains("DaumApps", StringComparison.OrdinalIgnoreCase))||(ua.Contains("facebookexternalhit", StringComparison.OrdinalIgnoreCase)||ua.Contains("Twitterbot", StringComparison.OrdinalIgnoreCase)||ua.Contains("LinkedInBot", StringComparison.OrdinalIgnoreCase)||ua.Contains("Slackbot", StringComparison.OrdinalIgnoreCase)||ua.Contains("Discordbot", StringComparison.OrdinalIgnoreCase));if(!isCrawler) { await next();return;} var path=ctx.Request.Path.Value ?? "";if(path=="/"||path=="") { var siteUrl=$"https://{ctx.Request.Host}";const string title="CodeMaru CCTV Viewer";const string desc="카메라 주인은 앱 하나 설치, 보는 사람은 링크만으로 실시간 시청";var image=$"{siteUrl}/images/cctvviewer-og.png";ctx.Response.ContentType="text/html; charset=utf-8";await ctx.Response.WriteAsync($""" <!DOCTYPE html> <html lang="ko"> <head> <meta charset="utf-8"/> <title>{title}</title> <meta property="og:type" content="website"/> <meta property="og:url" content="{siteUrl}/"/> <meta property="og:title" content="{title}"/> <meta property="og:description" content="{desc}"/> <meta property="og:image" content="{image}"/> <meta property="og:site_name" content="CodeMaru CCTV Viewer"/> <meta name="description" content="{desc}"/> </head> <body><p><a href="{siteUrl}/">{title}</a></p></body> </html> """);return;} var parts=path.Trim('/').Split('/');if(parts.Length==2 &&parts[1]=="live") { var slug=parts[0];var userSvc=ctx.RequestServices.GetRequiredService< VmsUserService >();var user=await userSvc.FindBySlugAsync(slug);if(user is not null) { var siteUrl=$"https://{ctx.Request.Host}";var pageUrl=$"{siteUrl}/{slug}/live";var title=string.IsNullOrWhiteSpace(user.OgTitle) ? $"{user.DisplayName} CCTV Live" :user.OgTitle;var desc=string.IsNullOrWhiteSpace(user.OgDescription) ? $"{user.DisplayName}의 실시간 카메라 스트림입니다." :user.OgDescription;var image=string.IsNullOrWhiteSpace(user.OgImage) ? $"{siteUrl}/img/og-default.png" :user.OgImage;ctx.Response.ContentType="text/html; charset=utf-8";await ctx.Response.WriteAsync($""" <!DOCTYPE html> <html lang="ko"> <head> <meta charset="utf-8"/> <title>{title}</title> <meta property="og:type" content="website"/> <meta property="og:url" content="{pageUrl}"/> <meta property="og:title" content="{title}"/> <meta property="og:description" content="{desc}"/> <meta property="og:image" content="{image}"/> <meta property="og:site_name" content="CodeMaru CCTV Viewer"/> <meta name="description" content="{desc}"/> </head> <body><p><a href="{pageUrl}">{title}</a></p></body> </html> """);return;} } await next();}  )

다음을 참조함 : app, DreamineVMS.Web.Services.Auth.VmsUserService.FindBySlugAsync().

이 함수 내부에서 호출하는 함수들에 대한 그래프입니다.:

◆ UseAntiforgery()

app. UseAntiforgery ( )

다음을 참조함 : app.

◆ UseAuthentication()

app. UseAuthentication ( )

다음을 참조함 : app.

◆ UseAuthorization()

app. UseAuthorization ( )

다음을 참조함 : app.

◆ UseForwardedHeaders()

app. UseForwardedHeaders ( )

다음을 참조함 : app.

◆ UseRouting()

app. UseRouting ( )

다음을 참조함 : app.

◆ UseStaticFiles()

app. UseStaticFiles ( new StaticFileOptions { ContentTypeProvider=provider } )

다음을 참조함 : app, provider.

변수 문서화

◆ app

var app = builder.Build()

◆ authOptions

AuthOptions authOptions
초기값:
=
builder.Configuration.GetSection(AuthOptions.SectionName).Get<AuthOptions>() ?? new AuthOptions()
var builder
Definition Program.cs:11

Program.cs 파일의 14 번째 라인에서 정의되었습니다.

다음에 의해서 참조됨 : AddDreamineIdentityWeb().

◆ builder

◆ Mappings

provider. Mappings[".exe"] = "application/octet-stream"

Program.cs 파일의 39 번째 라인에서 정의되었습니다.

◆ provider

var provider = new Microsoft.AspNetCore.StaticFiles.FileExtensionContentTypeProvider()

◆ usersDbPath

string usersDbPath
초기값:
builder.Configuration[$"{AuthOptions.SectionName}:UsersDbPath"],
Path.Combine(AppContext.BaseDirectory, "App_Data", "codemaru.db"))
static string ResolvePath(string? configuredPath, string fallback)
Definition Program.cs:331

Program.cs 파일의 16 번째 라인에서 정의되었습니다.

다음에 의해서 참조됨 : AddDreamineIdentityWeb().