Code cleanup, 2022 edition

This commit is contained in:
Laura Hausmann 2022-02-09 20:51:35 +01:00
parent db4a42171d
commit 1d9712294f
Signed by: zotan
GPG Key ID: D044E84C5BE01605
16 changed files with 230 additions and 237 deletions

View File

@ -1,10 +1,10 @@
using LinqToDB.Mapping;
namespace c3stream.DataModels.Tables {
[Table(Name = "States")]
public class States {
[Column(Name = "TalkId"), PrimaryKey, NotNull] public string TalkId { get; set; }
[Column(Name = "UserId"), PrimaryKey, NotNull] public string UserId { get; set; }
[Column(Name = "State"), NotNull] public string State { get; set; }
}
namespace c3stream.DataModels.Tables;
[Table(Name = "States")]
public class States {
[Column(Name = "TalkId"), PrimaryKey, NotNull] public string TalkId { get; set; }
[Column(Name = "UserId"), PrimaryKey, NotNull] public string UserId { get; set; }
[Column(Name = "State"), NotNull] public string State { get; set; }
}

View File

@ -11,7 +11,7 @@ namespace c3stream;
public static class Migrations {
private const int DbVer = 0;
private static readonly List<Migration> _migrations = new() { };
private static readonly List<Migration> _migrations = new();
public static void RunMigrations() {
using var db = new Database.DbConn();

View File

@ -1,8 +1,6 @@
@page
@model ConferenceModel
@using System.Net
@using global::c3stream.DataModels
@using static ConferenceModel
@model ConferenceModel
@{
if (c3stream.Conferences.All(c => c.Acronym != Request.Query["c"])) {
Response.Redirect("/");

View File

@ -1,39 +1,37 @@
using System.Collections.Generic;
using System.Linq;
using System.Linq;
using c3stream.DataModels;
using c3stream.DataModels.Tables;
using LinqToDB;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
namespace c3stream.Pages {
public class ConferenceModel : PageModel {
private readonly ILogger<ConferenceModel> _logger;
namespace c3stream.Pages;
public ConferenceModel(ILogger<ConferenceModel> logger) => _logger = logger;
public class ConferenceModel : PageModel {
private readonly ILogger<ConferenceModel> _logger;
public void OnGet() {
var guid = Request.Query["guid"].ToString();
var state = Request.Query["state"].ToString();
var userid = Request.Cookies["bookmark"];
if (string.IsNullOrWhiteSpace(guid) || string.IsNullOrWhiteSpace(state) || !Request.Cookies.ContainsKey("bookmark"))
return;
public ConferenceModel(ILogger<ConferenceModel> logger) => _logger = logger;
using var db = new Database.DbConn();
var existing = db.States.FirstOrDefault(p => p.TalkId == guid && p.UserId == userid);
if (existing != null)
if (state == "unwatched")
db.States.Delete(p => p == existing);
else {
existing.State = state;
db.Update(existing);
}
else
db.Insert(new States {
State = state, TalkId = guid, UserId = userid
});
Response.Redirect("/");
}
public void OnGet() {
var guid = Request.Query["guid"].ToString();
var state = Request.Query["state"].ToString();
var userid = Request.Cookies["bookmark"];
if (string.IsNullOrWhiteSpace(guid) || string.IsNullOrWhiteSpace(state) || !Request.Cookies.ContainsKey("bookmark"))
return;
using var db = new Database.DbConn();
var existing = db.States.FirstOrDefault(p => p.TalkId == guid && p.UserId == userid);
if (existing != null)
if (state == "unwatched") {
db.States.Delete(p => p == existing);
}
else {
existing.State = state;
db.Update(existing);
}
else
db.Insert(new States { State = state, TalkId = guid, UserId = userid });
Response.Redirect("/");
}
}

View File

@ -1,25 +1,25 @@
@page
@model ErrorModel
@{
ViewData["Title"] = "Error";
ViewData["Title"] = "Error";
}
<h1 class="text-danger">Error.</h1>
<h2 class="text-danger">An error occurred while processing your request.</h2>
@if (Model.ShowRequestId) {
<p>
<strong>Request ID:</strong> <code>@Model.RequestId</code>
</p>
<p>
<strong>Request ID:</strong> <code>@Model.RequestId</code>
</p>
}
<h3>Development Mode</h3>
<p>
Swapping to the <strong>Development</strong> environment displays detailed information about the error that occurred.
Swapping to the <strong>Development</strong> environment displays detailed information about the error that occurred.
</p>
<p>
<strong>The Development environment shouldn't be enabled for deployed applications.</strong>
It can result in displaying sensitive information from exceptions to end users.
For local debugging, enable the <strong>Development</strong> environment by setting the <strong>ASPNETCORE_ENVIRONMENT</strong> environment variable to <strong>Development</strong>
and restarting the app.
<strong>The Development environment shouldn't be enabled for deployed applications.</strong>
It can result in displaying sensitive information from exceptions to end users.
For local debugging, enable the <strong>Development</strong> environment by setting the <strong>ASPNETCORE_ENVIRONMENT</strong> environment variable to <strong>Development</strong>
and restarting the app.
</p>

View File

@ -3,19 +3,19 @@ using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.Extensions.Logging;
namespace c3stream.Pages {
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
public class ErrorModel : PageModel {
private readonly ILogger<ErrorModel> _logger;
namespace c3stream.Pages;
public ErrorModel(ILogger<ErrorModel> logger) => _logger = logger;
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
public class ErrorModel : PageModel {
private readonly ILogger<ErrorModel> _logger;
public string RequestId { get; set; }
public ErrorModel(ILogger<ErrorModel> logger) => _logger = logger;
public bool ShowRequestId => !string.IsNullOrEmpty(RequestId);
public string RequestId { get; set; }
public void OnGet() {
RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier;
}
public bool ShowRequestId => !string.IsNullOrEmpty(RequestId);
public void OnGet() {
RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier;
}
}

View File

@ -1,12 +1,12 @@
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.Extensions.Logging;
namespace c3stream.Pages {
public class IndexModel : PageModel {
private readonly ILogger<IndexModel> _logger;
namespace c3stream.Pages;
public IndexModel(ILogger<IndexModel> logger) => _logger = logger;
public class IndexModel : PageModel {
private readonly ILogger<IndexModel> _logger;
public void OnGet() { }
}
public IndexModel(ILogger<IndexModel> logger) => _logger = logger;
public void OnGet() { }
}

View File

@ -2,115 +2,115 @@
@using global::c3stream.DataModels
@model InfoModel
@{
ViewData["Title"] = "Info";
ViewData["Title"] = "Info";
}
@{
if (string.IsNullOrWhiteSpace(Request.Query["guid"]) || c3stream.GetEventByGuid(Request.Query["guid"]) == null) {
Response.Redirect("/");
return;
}
if (string.IsNullOrWhiteSpace(Request.Query["guid"]) || c3stream.GetEventByGuid(Request.Query["guid"]) == null) {
Response.Redirect("/");
return;
}
var cookie = c3stream.UpdateCookie(Request, Response, $"/Info?guid={Request.Query["guid"]}");
await using var db = new Database.DbConn();
var cookie = c3stream.UpdateCookie(Request, Response, $"/Info?guid={Request.Query["guid"]}");
var talk = c3stream.GetEventByGuid(Request.Query["guid"]);
var state = db.States.FirstOrDefault(p => p.TalkId == Request.Query["guid"].ToString() && p.UserId == cookie)?.State;
if (talk == null) {
Response.Redirect("/");
return;
}
if (state == null) {
state = "unwatched";
}
await using var db = new Database.DbConn();
var title = talk.Title;
var speakers = talk.Persons.Any() ? talk.Persons.Aggregate((s, s1) => $"{s}, {s1}") : "<no speakers>";
var description = talk.Description;
if (string.IsNullOrEmpty(description)) {
description = "&lt;missing description&gt;";
}
var talk = c3stream.GetEventByGuid(Request.Query["guid"]);
var state = db.States.FirstOrDefault(p => p.TalkId == Request.Query["guid"].ToString() && p.UserId == cookie)?.State;
if (talk == null) {
Response.Redirect("/");
return;
}
if (state == null) {
state = "unwatched";
}
var isWatched = state == "watched";
var isMarked = state == "marked";
var file = $"{talk.Slug}.mp4";
var conference = c3stream.GetConferenceByEventGuid(talk.Guid);
var title = talk.Title;
var speakers = talk.Persons.Any() ? talk.Persons.Aggregate((s, s1) => $"{s}, {s1}") : "<no speakers>";
var description = talk.Description;
if (string.IsNullOrEmpty(description)) {
description = "&lt;missing description&gt;";
}
var eventName = talk.Tags.Count <= 1 ? conference.Acronym : talk.Tags[0];
var logoPath = System.IO.Path.Combine(c3stream.CachePath, conference.Acronym, "logo.png");
var isWatched = state == "watched";
var isMarked = state == "marked";
var file = $"{talk.Slug}.mp4";
var conference = c3stream.GetConferenceByEventGuid(talk.Guid);
var category = talk.Tags.Count switch {
0 => "<no category>",
1 => talk.Tags[0],
2 => "<no category>",
3 => talk.Tags[2],
4 => talk.Tags[3],
5 => talk.Tags[3],
6 => talk.Tags[3], // rc3: is this correct?
_ => "<unknown tag format>"
};
var eventName = talk.Tags.Count <= 1 ? conference.Acronym : talk.Tags[0];
var logoPath = System.IO.Path.Combine(c3stream.CachePath, conference.Acronym, "logo.png");
var category = talk.Tags.Count switch {
0 => "<no category>",
1 => talk.Tags[0],
2 => "<no category>",
3 => talk.Tags[2],
4 => talk.Tags[3],
5 => talk.Tags[3],
6 => talk.Tags[3], // rc3: is this correct?
_ => "<unknown tag format>"
};
}
@if (System.IO.File.Exists(logoPath)) {
<img src="@(c3stream.CacheUrl + $"{conference.Acronym}/logo.png")" alt="Conference logo" style="max-height: 110px; float: right;"/>
<img src="@(c3stream.CacheUrl + $"{conference.Acronym}/logo.png")" alt="Conference logo" style="max-height: 110px; float: right;"/>
}
else {
<img src="@conference.LogoUri" alt="Conference logo" style="max-height: 110px; float: right;"/>
<img src="@conference.LogoUri" alt="Conference logo" style="max-height: 110px; float: right;"/>
}
@if (isWatched) {
<h3 style="color: #95cb7a">@title - <i>@speakers</i></h3>
<h3 style="color: #95cb7a">@title - <i>@speakers</i></h3>
}
else if (isMarked) {
<h3 style="color: #da7d4f">@title - <i>@speakers</i></h3>
<h3 style="color: #da7d4f">@title - <i>@speakers</i></h3>
}
else {
<h3>@title - <i>@speakers</i></h3>
<h3>@title - <i>@speakers</i></h3>
}
<h5>@eventName - @category - @talk.Date?.Date.ToShortDateString()</h5>
<div class="btn-group" role="group" style="margin-bottom: 10px">
<a href="@talk.FrontendLink.AbsoluteUri" role="button" class="btn btn-primary btn-c3saction w-100" data-toggle="tooltip" data-placement="right" title="Play">
<i class="fas fa-play-circle"></i>
</a>
@if (System.IO.File.Exists(System.IO.Path.Combine(c3stream.CachePath, conference.Acronym, file))) {
<a href="@(c3stream.CacheUrl + $"{conference.Acronym}/{file}")" role="button" class="btn btn-primary btn-c3saction w-100" data-toggle="tooltip" data-placement="right" title="Mirror">
<i class="fas fa-cloud-download"></i>
</a>
}
else {
<a href="/" role="button" class="btn btn-primary btn-c3saction disabled">
<i class="fas fa-cloud-download"></i>
</a>
}
@if (isWatched) {
<button onclick="SetState('@talk.Guid', 'unwatched')" class="btn btn-primary btn-c3saction w-100" data-toggle="tooltip" data-placement="left" title="Mark unwatched">
<i class="fas fa-times"></i>
</button>
<button class="btn btn-primary btn-c3saction disabled">
<i class="fas fa-clock"></i>
</button>
}
else if (isMarked) {
<button onclick="SetState('@talk.Guid', 'watched')" class="btn btn-primary btn-c3saction w-100" data-toggle="tooltip" data-placement="left" title="Mark watched">
<i class="fas fa-check"></i>
</button>
<button onclick="SetState('@talk.Guid', 'unwatched')" class="btn btn-primary btn-c3saction w-100" data-toggle="tooltip" data-placement="left" title="Remove from watch later">
<i class="fas fa-undo-alt"></i>
</button>
}
else {
<button onclick="SetState('@talk.Guid', 'watched')" class="btn btn-primary btn-c3saction w-100" data-toggle="tooltip" data-placement="left" title="Mark watched">
<i class="fas fa-check"></i>
</button>
<button onclick="SetState('@talk.Guid', 'marked')" class="btn btn-primary btn-c3saction w-100" data-toggle="tooltip" data-placement="left" title="Add to watch later">
<i class="fas fa-clock"></i>
</button>
}
<a href="@talk.FrontendLink.AbsoluteUri" role="button" class="btn btn-primary btn-c3saction w-100" data-toggle="tooltip" data-placement="right" title="Play">
<i class="fas fa-play-circle"></i>
</a>
@if (System.IO.File.Exists(System.IO.Path.Combine(c3stream.CachePath, conference.Acronym, file))) {
<a href="@(c3stream.CacheUrl + $"{conference.Acronym}/{file}")" role="button" class="btn btn-primary btn-c3saction w-100" data-toggle="tooltip" data-placement="right" title="Mirror">
<i class="fas fa-cloud-download"></i>
</a>
}
else {
<a href="/" role="button" class="btn btn-primary btn-c3saction disabled">
<i class="fas fa-cloud-download"></i>
</a>
}
@if (isWatched) {
<button onclick="SetState('@talk.Guid', 'unwatched')" class="btn btn-primary btn-c3saction w-100" data-toggle="tooltip" data-placement="left" title="Mark unwatched">
<i class="fas fa-times"></i>
</button>
<button class="btn btn-primary btn-c3saction disabled">
<i class="fas fa-clock"></i>
</button>
}
else if (isMarked) {
<button onclick="SetState('@talk.Guid', 'watched')" class="btn btn-primary btn-c3saction w-100" data-toggle="tooltip" data-placement="left" title="Mark watched">
<i class="fas fa-check"></i>
</button>
<button onclick="SetState('@talk.Guid', 'unwatched')" class="btn btn-primary btn-c3saction w-100" data-toggle="tooltip" data-placement="left" title="Remove from watch later">
<i class="fas fa-undo-alt"></i>
</button>
}
else {
<button onclick="SetState('@talk.Guid', 'watched')" class="btn btn-primary btn-c3saction w-100" data-toggle="tooltip" data-placement="left" title="Mark watched">
<i class="fas fa-check"></i>
</button>
<button onclick="SetState('@talk.Guid', 'marked')" class="btn btn-primary btn-c3saction w-100" data-toggle="tooltip" data-placement="left" title="Add to watch later">
<i class="fas fa-clock"></i>
</button>
}
</div>
<p style="text-align: justify">
@Html.Raw(description.Replace("\n", "<br/>").Replace("<p>", "").Replace("</p>", ""))
@Html.Raw(description.Replace("\n", "<br/>").Replace("<p>", "").Replace("</p>", ""))
</p>
Share this talk:<br/>

View File

@ -1,12 +1,12 @@
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.Extensions.Logging;
namespace c3stream.Pages {
public class InfoModel : PageModel {
private readonly ILogger<InfoModel> _logger;
namespace c3stream.Pages;
public InfoModel(ILogger<InfoModel> logger) => _logger = logger;
public class InfoModel : PageModel {
private readonly ILogger<InfoModel> _logger;
public void OnGet() { }
}
public InfoModel(ILogger<InfoModel> logger) => _logger = logger;
public void OnGet() { }
}

View File

@ -1,12 +1,12 @@
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.Extensions.Logging;
namespace c3stream.Pages {
public class PrivacyModel : PageModel {
private readonly ILogger<PrivacyModel> _logger;
namespace c3stream.Pages;
public PrivacyModel(ILogger<PrivacyModel> logger) => _logger = logger;
public class PrivacyModel : PageModel {
private readonly ILogger<PrivacyModel> _logger;
public void OnGet() { }
}
public PrivacyModel(ILogger<PrivacyModel> logger) => _logger = logger;
public void OnGet() { }
}

View File

@ -1,38 +1,38 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<title>@ViewData["Title"] - c3stream</title>
<link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.min.css"/>
<link rel="stylesheet" href="~/css/fa.css" crossorigin="anonymous">
<link rel="stylesheet" href="~/css/site.css"/>
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<title>@ViewData["Title"] - c3stream</title>
<link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.min.css"/>
<link rel="stylesheet" href="~/css/fa.css" crossorigin="anonymous">
<link rel="stylesheet" href="~/css/site.css"/>
</head>
<body>
<header>
<nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-bottom box-shadow mb-3">
<div class="container-fluid" style="width: 90%">
<a class="navbar-brand" asp-area="" asp-page="/Index">c3stream <small style="font-size: x-small">v5</small></a>
<button class="navbar-toggler" role="button" data-toggle="collapse" data-target=".navbar-collapse" aria-controls="navbarSupportedContent"
aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
</div>
</nav>
<nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-bottom box-shadow mb-3">
<div class="container-fluid" style="width: 90%">
<a class="navbar-brand" asp-area="" asp-page="/Index">c3stream <small style="font-size: x-small">v5</small></a>
<button class="navbar-toggler" role="button" data-toggle="collapse" data-target=".navbar-collapse" aria-controls="navbarSupportedContent"
aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
</div>
</nav>
</header>
<div class="container-fluid" style="width: 90%">
<main role="main" class="pb-3">
@RenderBody()
</main>
<main role="main" class="pb-3">
@RenderBody()
</main>
</div>
<footer class="border-top footer">
<div class="container-fluid" style="width: 90%; text-align: center">
<a href="/Privacy">Privacy</a> -
<a href="mailto:c3stream-contact@zotan.email">Contact</a> -
<a href="https://git.zotan.services/zotan/c3stream/">Source Code</a> -
c3stream is not affiliated with media.ccc.de in any way. Mirrored video files display their license in the video, no rights reserved.
</div>
<div class="container-fluid" style="width: 90%; text-align: center">
<a href="/Privacy">Privacy</a> -
<a href="mailto:c3stream-contact@zotan.email">Contact</a> -
<a href="https://git.zotan.services/zotan/c3stream/">Source Code</a> -
c3stream is not affiliated with media.ccc.de in any way. Mirrored video files display their license in the video, no rights reserved.
</div>
</footer>
<script src="~/lib/jquery/dist/jquery.min.js"></script>
@ -41,4 +41,4 @@
@RenderSection("Scripts", false)
</body>
</html>
</html>

View File

@ -1,10 +1,8 @@
@page
@model WatchlistModel
@using System.Net
@using global::c3stream.DataModels
@using static WatchlistModel
@model WatchlistModel
@{
var cookie = c3stream.UpdateCookie(Request, Response, $"/Watchlist");
var cookie = c3stream.UpdateCookie(Request, Response, "/Watchlist");
ViewData["Title"] = "Watchlist";
await using var db = new Database.DbConn();
var states = db.States.ToList();

View File

@ -1,39 +1,37 @@
using System.Collections.Generic;
using System.Linq;
using System.Linq;
using c3stream.DataModels;
using c3stream.DataModels.Tables;
using LinqToDB;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
namespace c3stream.Pages {
public class WatchlistModel : PageModel {
private readonly ILogger<ConferenceModel> _logger;
namespace c3stream.Pages;
public WatchlistModel(ILogger<ConferenceModel> logger) => _logger = logger;
public class WatchlistModel : PageModel {
private readonly ILogger<ConferenceModel> _logger;
public void OnGet() {
var guid = Request.Query["guid"].ToString();
var state = Request.Query["state"].ToString();
var userid = Request.Cookies["bookmark"];
if (string.IsNullOrWhiteSpace(guid) || string.IsNullOrWhiteSpace(state) || !Request.Cookies.ContainsKey("bookmark"))
return;
public WatchlistModel(ILogger<ConferenceModel> logger) => _logger = logger;
using var db = new Database.DbConn();
var existing = db.States.FirstOrDefault(p => p.TalkId == guid && p.UserId == userid);
if (existing != null)
if (state == "unwatched")
db.States.Delete(p => p == existing);
else {
existing.State = state;
db.Update(existing);
}
else
db.Insert(new States {
State = state, TalkId = guid, UserId = userid
});
Response.Redirect("/");
}
public void OnGet() {
var guid = Request.Query["guid"].ToString();
var state = Request.Query["state"].ToString();
var userid = Request.Cookies["bookmark"];
if (string.IsNullOrWhiteSpace(guid) || string.IsNullOrWhiteSpace(state) || !Request.Cookies.ContainsKey("bookmark"))
return;
using var db = new Database.DbConn();
var existing = db.States.FirstOrDefault(p => p.TalkId == guid && p.UserId == userid);
if (existing != null)
if (state == "unwatched") {
db.States.Delete(p => p == existing);
}
else {
existing.State = state;
db.Update(existing);
}
else
db.Insert(new States { State = state, TalkId = guid, UserId = userid });
Response.Redirect("/");
}
}

View File

@ -1,3 +1,3 @@
@{
Layout = "_Layout";
Layout = "_Layout";
}

View File

@ -1 +1,2 @@
c3stream is a small proxy site meant for saving watched status & watch-later-lists for media.ccc.de talks. Test in production at https://c3stream.de
c3stream is a small proxy site meant for saving watched status & watch-later-lists for media.ccc.de talks. Test in
production at https://c3stream.de

View File

@ -4,32 +4,32 @@ using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
namespace c3stream {
public class Startup {
public Startup(IConfiguration configuration) => Configuration = configuration;
namespace c3stream;
public IConfiguration Configuration { get; }
public class Startup {
public Startup(IConfiguration configuration) => Configuration = configuration;
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services) {
services.AddRazorPages();
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env) {
if (env.IsDevelopment())
app.UseDeveloperExceptionPage();
else
app.UseExceptionHandler("/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services) {
services.AddRazorPages();
}
app.UseStaticFiles();
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env) {
if (env.IsDevelopment())
app.UseDeveloperExceptionPage();
else
app.UseExceptionHandler("/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseRouting();
app.UseStaticFiles();
app.UseAuthorization();
app.UseRouting();
app.UseEndpoints(endpoints => { endpoints.MapRazorPages(); });
}
app.UseAuthorization();
app.UseEndpoints(endpoints => { endpoints.MapRazorPages(); });
}
}