diff --git a/MyWebsite/MyWebsite.sln b/MyWebsite/MyWebsite.sln
index 5e4e7ad..10998cf 100644
--- a/MyWebsite/MyWebsite.sln
+++ b/MyWebsite/MyWebsite.sln
@@ -1,25 +1,25 @@
-
-Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio Version 16
-VisualStudioVersion = 16.0.29519.181
-MinimumVisualStudioVersion = 10.0.40219.1
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MyWebsite", "MyWebsite\MyWebsite.csproj", "{9FB2B925-DC18-4081-AC91-96F2C49415F9}"
-EndProject
-Global
- GlobalSection(SolutionConfigurationPlatforms) = preSolution
- Debug|Any CPU = Debug|Any CPU
- Release|Any CPU = Release|Any CPU
- EndGlobalSection
- GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {9FB2B925-DC18-4081-AC91-96F2C49415F9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {9FB2B925-DC18-4081-AC91-96F2C49415F9}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {9FB2B925-DC18-4081-AC91-96F2C49415F9}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {9FB2B925-DC18-4081-AC91-96F2C49415F9}.Release|Any CPU.Build.0 = Release|Any CPU
- EndGlobalSection
- GlobalSection(SolutionProperties) = preSolution
- HideSolutionNode = FALSE
- EndGlobalSection
- GlobalSection(ExtensibilityGlobals) = postSolution
- SolutionGuid = {DBEA98A5-43F1-4B55-B5E0-F2913A985494}
- EndGlobalSection
-EndGlobal
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.29519.181
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MyWebsite", "MyWebsite\MyWebsite.csproj", "{9FB2B925-DC18-4081-AC91-96F2C49415F9}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {9FB2B925-DC18-4081-AC91-96F2C49415F9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {9FB2B925-DC18-4081-AC91-96F2C49415F9}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {9FB2B925-DC18-4081-AC91-96F2C49415F9}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {9FB2B925-DC18-4081-AC91-96F2C49415F9}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {DBEA98A5-43F1-4B55-B5E0-F2913A985494}
+ EndGlobalSection
+EndGlobal
diff --git a/MyWebsite/MyWebsite/Areas/Admin/Controllers/ShortenerController.cs b/MyWebsite/MyWebsite/Areas/Admin/Controllers/ShortenerController.cs
new file mode 100644
index 0000000..4e3139a
--- /dev/null
+++ b/MyWebsite/MyWebsite/Areas/Admin/Controllers/ShortenerController.cs
@@ -0,0 +1,72 @@
+using System;
+using System.Linq;
+using Microsoft.AspNetCore.Authorization;
+using Microsoft.AspNetCore.Mvc;
+using MyWebsite.Controllers;
+using MyWebsite.Models;
+using MyWebsite.Models.Databases;
+
+namespace MyWebsite.Areas.Admin.Controllers
+{
+ [Area("Admin")]
+ [Authorize]
+ public class ShortenerController : ExtendedController
+ {
+ const string ViewPath = "Areas/Admin/Views/Shared/LinkShortener.cshtml";
+ public ShortenerController(DatabaseContext context) : base(context) { }
+
+ [HttpGet]
+ public IActionResult Index() =>
+ View(ViewPath, Database.ShortLinks.ToList());
+
+ [HttpPost]
+ public IActionResult Create(string url, string id = "")
+ {
+ if (!string.IsNullOrWhiteSpace(id) && Database.ShortLinks.Find(id) != null)
+ {
+ ModelState.AddModelError("Duplicate", "Link with such ID already exists");
+ return View(ViewPath, Database.ShortLinks.ToList());
+ }
+
+ if (!Uri.TryCreate(url, UriKind.RelativeOrAbsolute, out Uri uri))
+ {
+ ModelState.AddModelError("InvalidLink", "Provided link for shortening is invalid");
+ return View(ViewPath, Database.ShortLinks.ToList());
+ }
+
+ Database.ShortLinks.Add(new ShortLinkModel
+ {
+ Uri = uri,
+ LinkId = string.IsNullOrWhiteSpace(id) ? RandomString(6) : id
+ });
+ Database.SaveChanges();
+ return RedirectToAction("Index");
+ }
+
+ [HttpGet]
+ public IActionResult Delete(string id)
+ {
+ if (Database.ShortLinks.Find(id) is ShortLinkModel link)
+ {
+ Database.ShortLinks.Remove(link);
+ Database.SaveChanges();
+ }
+
+ return RedirectToAction("Index");
+ }
+
+ private string RandomString(int length)
+ {
+ string key = string.Empty;
+ Random random = new Random();
+ const string chars = "abcdefghijklmnopqrstuvwxyz0123456789";
+ do
+ {
+ key = new string(Enumerable.Repeat(chars, length)
+ .Select(s => s[random.Next(s.Length)]).ToArray());
+ } while (Database.ShortLinks.Any(i => i.LinkId == key));
+
+ return key;
+ }
+ }
+}
\ No newline at end of file
diff --git a/MyWebsite/MyWebsite/Areas/Admin/Views/Shared/GUTSchedule.cshtml b/MyWebsite/MyWebsite/Areas/Admin/Views/Shared/GUTSchedule.cshtml
index fbe69a1..e0be6f0 100644
--- a/MyWebsite/MyWebsite/Areas/Admin/Views/Shared/GUTSchedule.cshtml
+++ b/MyWebsite/MyWebsite/Areas/Admin/Views/Shared/GUTSchedule.cshtml
@@ -27,7 +27,7 @@
- Langauge
+ Language
Last update
Actions
diff --git a/MyWebsite/MyWebsite/Areas/Admin/Views/Shared/LinkShortener.cshtml b/MyWebsite/MyWebsite/Areas/Admin/Views/Shared/LinkShortener.cshtml
new file mode 100644
index 0000000..12ade19
--- /dev/null
+++ b/MyWebsite/MyWebsite/Areas/Admin/Views/Shared/LinkShortener.cshtml
@@ -0,0 +1,46 @@
+@model List
+@{
+ ViewData["Title"] = "Link shortener";
+}
+
+
+
+
+
+
+ Create new link
+
+
+ Shortened links
+
+
+
+ Original link
+ Short link
+
+
+
+ @foreach (ShortLinkModel link in Model)
+ {
+
+ @link.Uri.OriginalString
+ //xfox111.net/@link.LinkId
+
+ Delete
+
+
+ }
+
+
+
\ No newline at end of file
diff --git a/MyWebsite/MyWebsite/Controllers/HomeController.cs b/MyWebsite/MyWebsite/Controllers/HomeController.cs
index 69d49f1..affaa67 100644
--- a/MyWebsite/MyWebsite/Controllers/HomeController.cs
+++ b/MyWebsite/MyWebsite/Controllers/HomeController.cs
@@ -1,65 +1,71 @@
-using Microsoft.AspNetCore.Http;
-using Microsoft.AspNetCore.Localization;
-using Microsoft.AspNetCore.Mvc;
-using MyWebsite.Models.Databases;
-using MyWebsite.ViewModels;
-using System;
-using System.Globalization;
-
-namespace MyWebsite.Controllers
-{
- public class HomeController : ExtendedController
- {
- public HomeController(DatabaseContext context) : base(context) { }
-
- [Route("")]
- public IActionResult Index() =>
- View();
-
- [Route("Contacts")]
- public IActionResult Contacts() =>
- View();
-
- [Route("Projects")]
- public IActionResult Projects() =>
- View(new ProjectsViewModel(Database));
-
- [Route("Construction")]
- public IActionResult Construction() =>
- View();
-
- [Route("Error")]
- [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
- public IActionResult Error() =>
- View();
-
- [Route("GetError")]
- public IActionResult GetError(int errorCode = 404) =>
- StatusCode(errorCode);
-
- [Route("SwitchLanguage")]
- public IActionResult SwitchLanguage()
- {
- Response.Cookies.Append(
- CookieRequestCultureProvider.DefaultCookieName,
- CookieRequestCultureProvider.MakeCookieValue(new RequestCulture(
- CultureInfo.CurrentCulture.TwoLetterISOLanguageName.ToUpperInvariant() == "RU" ?
- "en-US" : "ru"
- )),
- new CookieOptions { Expires = DateTimeOffset.UtcNow.AddYears(1) });
-
- return Redirect(Extensions.CheckNullOrWhitespace(Request.Headers["Referer"], "/"));
- }
-
- [Route("ComicSans")]
- public IActionResult ComicSans()
- {
- if (Request.Cookies.ContainsKey("useComicSans"))
- Response.Cookies.Delete("useComicSans");
- else
- Response.Cookies.Append("useComicSans", "true");
-
- return Redirect(Extensions.CheckNullOrWhitespace(Request.Headers["Referer"], "/"));
- }
- }
+using Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Localization;
+using Microsoft.AspNetCore.Mvc;
+using MyWebsite.Models;
+using MyWebsite.Models.Databases;
+using MyWebsite.ViewModels;
+using System;
+using System.Globalization;
+
+namespace MyWebsite.Controllers
+{
+ public class HomeController : ExtendedController
+ {
+ public HomeController(DatabaseContext context) : base(context) { }
+
+ [Route("/{id?}")]
+ public IActionResult Index(string id = "")
+ {
+ if (!string.IsNullOrWhiteSpace(id) && Database.ShortLinks.Find(id) is ShortLinkModel link)
+ return Redirect(link.Uri.OriginalString);
+ else
+ return View();
+ }
+
+ [Route("Contacts")]
+ public IActionResult Contacts() =>
+ View();
+
+ [Route("Projects")]
+ public IActionResult Projects() =>
+ View(new ProjectsViewModel(Database));
+
+ [Route("Construction")]
+ public IActionResult Construction() =>
+ View();
+
+ [Route("Error")]
+ [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
+ public IActionResult Error() =>
+ View();
+
+ [Route("GetError")]
+ public IActionResult GetError(int errorCode = 404) =>
+ StatusCode(errorCode);
+
+ [Route("SwitchLanguage")]
+ public IActionResult SwitchLanguage()
+ {
+ Response.Cookies.Append(
+ CookieRequestCultureProvider.DefaultCookieName,
+ CookieRequestCultureProvider.MakeCookieValue(new RequestCulture(
+ CultureInfo.CurrentCulture.TwoLetterISOLanguageName.ToUpperInvariant() == "RU" ?
+ "en-US" : "ru"
+ )),
+ new CookieOptions { Expires = DateTimeOffset.UtcNow.AddYears(1) });
+
+ return Redirect(Extensions.CheckNullOrWhitespace(Request.Headers["Referer"], "/"));
+ }
+
+ [Route("ComicSans")]
+ public IActionResult ComicSans()
+ {
+ if (Request.Cookies.ContainsKey("useComicSans"))
+ Response.Cookies.Delete("useComicSans");
+ else
+ Response.Cookies.Append("useComicSans", "true");
+
+ return Redirect(Extensions.CheckNullOrWhitespace(Request.Headers["Referer"], "/"));
+ }
+ }
}
\ No newline at end of file
diff --git a/MyWebsite/MyWebsite/Models/Databases/DatabaseContext.cs b/MyWebsite/MyWebsite/Models/Databases/DatabaseContext.cs
index e223c1a..bde2171 100644
--- a/MyWebsite/MyWebsite/Models/Databases/DatabaseContext.cs
+++ b/MyWebsite/MyWebsite/Models/Databases/DatabaseContext.cs
@@ -1,18 +1,19 @@
-using Microsoft.EntityFrameworkCore;
-
-namespace MyWebsite.Models.Databases
-{
- public class DatabaseContext : DbContext
- {
- public DbSet Links { get; set; }
- public DbSet Gallery { get; set; }
- public DbSet Projects { get; set; }
- public DbSet Users { get; set; }
- public DbSet Badges { get; set; }
- public DbSet Resume { get; set; }
- public DbSet CustomData { get; set; }
-
- public DatabaseContext(DbContextOptions options) : base(options) =>
- Database.EnsureCreated();
- }
+using Microsoft.EntityFrameworkCore;
+
+namespace MyWebsite.Models.Databases
+{
+ public class DatabaseContext : DbContext
+ {
+ public DbSet Links { get; set; }
+ public DbSet Gallery { get; set; }
+ public DbSet Projects { get; set; }
+ public DbSet Users { get; set; }
+ public DbSet Badges { get; set; }
+ public DbSet Resume { get; set; }
+ public DbSet ShortLinks { get; set; }
+ public DbSet CustomData { get; set; }
+
+ public DatabaseContext(DbContextOptions options) : base(options) =>
+ Database.EnsureCreated();
+ }
}
\ No newline at end of file
diff --git a/MyWebsite/MyWebsite/Models/ShortLinkModel.cs b/MyWebsite/MyWebsite/Models/ShortLinkModel.cs
new file mode 100644
index 0000000..e5ca37b
--- /dev/null
+++ b/MyWebsite/MyWebsite/Models/ShortLinkModel.cs
@@ -0,0 +1,18 @@
+using System;
+using System.ComponentModel.DataAnnotations;
+using System.ComponentModel.DataAnnotations.Schema;
+
+namespace MyWebsite.Models
+{
+ public class ShortLinkModel
+ {
+ [Key]
+ [Required]
+ [Column(TypeName = "varchar(255)")]
+ public string LinkId { get; set; }
+
+ [Required]
+ [Column(TypeName = "varchar(255)")]
+ public Uri Uri { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/MyWebsite/MyWebsite/Views/Admin/Index.cshtml b/MyWebsite/MyWebsite/Views/Admin/Index.cshtml
index 908550e..1a7a2a2 100644
--- a/MyWebsite/MyWebsite/Views/Admin/Index.cshtml
+++ b/MyWebsite/MyWebsite/Views/Admin/Index.cshtml
@@ -1,32 +1,35 @@
-@{
- ViewData["Title"] = "Admin panel";
-}
-
-
-
-
-
-@section Imports
-{
-
+@{
+ ViewData["Title"] = "Admin panel";
+}
+
+
+
+
+
+@section Imports
+{
+
}
\ No newline at end of file
diff --git a/MyWebsite/MyWebsite/Views/Blog/Index.cshtml b/MyWebsite/MyWebsite/Views/Blog/Index.cshtml
index b2fce0f..e962dfe 100644
--- a/MyWebsite/MyWebsite/Views/Blog/Index.cshtml
+++ b/MyWebsite/MyWebsite/Views/Blog/Index.cshtml
@@ -1,10 +1,10 @@
-@model BlogListViewModel
-@{
- ViewData["Title"] = "Fox, Coffee and Science - " + SharedLocalizer["Blog"];
-}
-
-@section OpenGraph
-{
+@model BlogListViewModel
+@{
+ ViewData["Title"] = "Fox, Coffee and Science - " + SharedLocalizer["Blog"];
+}
+
+@section OpenGraph
+{
@@ -14,89 +14,89 @@
@* *@
-
-}
-
-
- @if (string.IsNullOrWhiteSpace(Model.SearchTerm))
- {
- Fox, Coffee and Science - @SharedLocalizer["Blog"]
- }
- else
- {
- @SharedLocalizer["Search results for"] @Model.SearchTerm
- }
- @Localizer["Visit on"] Blogspot
-
-
-
-
-
-
- @if (Model.Posts.Items == null || Model.Posts.Items.Count < 1)
- {
-
- }
- else
- foreach (Google.Apis.Blogger.v3.Data.Post post in Model.Posts.Items)
- {
-
- @if (post.Images != null && post.Images.Count > 0)
- {
-
- }
-
-
- @DateTime.Parse(post.Published).ToShortDateString() | @post.Author.DisplayName
- @if (post.Labels != null && post.Labels.Count > 0)
- {
-
- }
-
-
-
-
- }
-
-
- @if ((string.IsNullOrWhiteSpace(Model.SearchTerm) || Model.SearchTerm.StartsWith("#")) && (Model.PageNumber > 0 || !string.IsNullOrWhiteSpace(Model.Posts.NextPageToken)))
- {
-
- @if (Model.PageNumber > 0)
- {
-
@Localizer["Prev"]
- }
-
@(Model.PageNumber + 1)
- @if (!string.IsNullOrWhiteSpace(Model.Posts.NextPageToken))
- {
-
@Localizer["Next"]
- }
-
- }
-
-
-
-
-@section Imports
-{
-
-
+
+}
+
+
+ @if (string.IsNullOrWhiteSpace(Model.SearchTerm))
+ {
+ Fox, Coffee and Science - @SharedLocalizer["Blog"]
+ }
+ else
+ {
+ @SharedLocalizer["Search results for"] @Model.SearchTerm
+ }
+ @Localizer["Visit on"] Blogspot
+
+
+
+
+
+
+ @if (Model.Posts.Items == null || Model.Posts.Items.Count < 1)
+ {
+
+ }
+ else
+ foreach (Google.Apis.Blogger.v3.Data.Post post in Model.Posts.Items)
+ {
+
+ @if (post.Images != null && post.Images.Count > 0)
+ {
+
+ }
+
+
+ @DateTime.Parse(post.Published).ToShortDateString() | @post.Author.DisplayName
+ @if (post.Labels != null && post.Labels.Count > 0)
+ {
+
+ }
+
+
+
+
+ }
+
+
+ @if ((string.IsNullOrWhiteSpace(Model.SearchTerm) || Model.SearchTerm.StartsWith("#")) && (Model.PageNumber > 0 || !string.IsNullOrWhiteSpace(Model.Posts.NextPageToken)))
+ {
+
+ @if (Model.PageNumber > 0)
+ {
+
@Localizer["Prev"]
+ }
+
@(Model.PageNumber + 1)
+ @if (!string.IsNullOrWhiteSpace(Model.Posts.NextPageToken))
+ {
+
@Localizer["Next"]
+ }
+
+ }
+
+
+
+
+@section Imports
+{
+
+
}
\ No newline at end of file
diff --git a/MyWebsite/MyWebsite/Views/Blog/Post.cshtml b/MyWebsite/MyWebsite/Views/Blog/Post.cshtml
index 445ca2c..1a1ddb9 100644
--- a/MyWebsite/MyWebsite/Views/Blog/Post.cshtml
+++ b/MyWebsite/MyWebsite/Views/Blog/Post.cshtml
@@ -26,7 +26,7 @@
}
-