added BlazorAppRadzenNet8UpgradeRadzen4to5

This commit is contained in:
M. Akif Tokatlioglu
2024-08-12 00:24:43 +03:00
parent 30ac4364bb
commit ee014e183a
30 changed files with 1129 additions and 0 deletions

View File

@@ -0,0 +1,25 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.10.35004.147
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BlazorAppRadzenNet8UpgradeRadzen4to5", "BlazorAppRadzenNet8UpgradeRadzen4to5\BlazorAppRadzenNet8UpgradeRadzen4to5.csproj", "{2A3D3409-F811-4BAD-81B1-10243349D26C}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{2A3D3409-F811-4BAD-81B1-10243349D26C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{2A3D3409-F811-4BAD-81B1-10243349D26C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2A3D3409-F811-4BAD-81B1-10243349D26C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2A3D3409-F811-4BAD-81B1-10243349D26C}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {E78B5F08-4975-4B9B-B9F8-DFDD0DAE2608}
EndGlobalSection
EndGlobal

View File

@@ -0,0 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Mapster" Version="7.4.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="8.0.7" />
<PackageReference Include="Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore" Version="8.0.7" />
<PackageReference Include="Radzen.Blazor" Version="5.0.8" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,22 @@
@inject NavigationManager NavigationManager
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<base href="@NavigationManager.BaseUri" />
<link rel="stylesheet" href="_content/Radzen.Blazor/css/standard-base.css" />
<link rel="stylesheet" href="css/site.css" />
<link rel="icon" href="favicon.ico" />
<HeadOutlet @rendermode="InteractiveServer" />
</head>
<body>
<Routes @rendermode="InteractiveServer" />
<script src="_framework/blazor.web.js"></script>
<script src="_content/Radzen.Blazor/Radzen.Blazor.js?v=@(typeof(Radzen.Colors).Assembly.GetName().Version)"></script>
</body>
</html>

View File

@@ -0,0 +1,59 @@
@inherits LayoutComponentBase
@inject IJSRuntime JSRuntime
@inject NavigationManager NavigationManager
@inject DialogService DialogService
@inject ContextMenuService ContextMenuService
@inject TooltipService TooltipService
@inject NotificationService NotificationService
<RadzenDialog />
<RadzenNotification />
<RadzenTooltip />
<RadzenContextMenu />
<RadzenComponents />
<RadzenLayout style="grid-template-areas: 'rz-sidebar rz-header' 'rz-sidebar rz-body';">
<RadzenHeader>
<RadzenRow JustifyContent="JustifyContent.Start" AlignItems="AlignItems.Center" Gap="0">
<RadzenColumn Size="5">
<RadzenSidebarToggle Click="@SidebarToggleClick"></RadzenSidebarToggle>
</RadzenColumn>
<RadzenColumn Size="7">
<RadzenStack AlignItems="AlignItems.Center" Orientation="Orientation.Horizontal" JustifyContent="JustifyContent.End"></RadzenStack>
</RadzenColumn>
</RadzenRow>
</RadzenHeader>
<RadzenBody Expanded="@sidebarExpanded">
<RadzenRow class="rz-mx-auto rz-px-4 rz-pt-2 rz-pt-md-4 rz-pt-lg-6 rz-pt-xl-12 rz-pb-2 rz-pb-lg-12" Style="max-width: 1440px;">
<RadzenColumn Size="12">
@Body
</RadzenColumn>
</RadzenRow>
</RadzenBody>
<RadzenSidebar Expanded="@sidebarExpanded" style="z-index: 2">
<RadzenStack AlignItems="Radzen.AlignItems.Center" class="rz-py-4 rz-py-lg-6" Style="padding: var(--rz-panel-menu-item-padding); border-bottom: var(--rz-panel-menu-item-border);">
<RadzenImage Path="images/logo.png" style="width: 48px; height: 48px;" AlternateText="Application logo"></RadzenImage>
<RadzenText Text="appname" TextStyle="Radzen.Blazor.TextStyle.Subtitle1" class="rz-mb-0" style="color: var(--rz-sidebar-color);" />
</RadzenStack>
<NavMenu />
<RadzenStack AlignItems="Radzen.AlignItems.Center" Gap="0" class="rz-py-4 rz-py-lg-6" Style="padding: var(--rz-panel-menu-item-padding);">
<RadzenText Text="appname v1.0.0" TextStyle="Radzen.Blazor.TextStyle.Caption" TagName="Radzen.Blazor.TagName.P" TextAlign="Radzen.TextAlign.Center" />
<RadzenText Text="Copyright Ⓒ 2024" TextStyle="Radzen.Blazor.TextStyle.Caption" class="rz-mb-0" TagName="Radzen.Blazor.TagName.P" TextAlign="Radzen.TextAlign.Center" />
</RadzenStack>
</RadzenSidebar>
</RadzenLayout>
@code {
bool sidebarExpanded = true;
void SidebarToggleClick()
{
sidebarExpanded = !sidebarExpanded;
}
}

View File

@@ -0,0 +1,7 @@
<RadzenPanelMenu>
<RadzenPanelMenuItem Text="Home" Path="/" />
<RadzenPanelMenuItem Text="Posts" Path="/BlogPost" />
</RadzenPanelMenu>

View File

@@ -0,0 +1,74 @@
@page "/BlogPost/Create"
<RadzenText Text="Create" TextStyle="TextStyle.H5" />
@if (blogPostViewModel == null)
{
<p>Loading...</p>
}
else
{
<RadzenStack>
<RadzenFieldset Text="New Post">
<RadzenStack Gap="2rem">
<RadzenTemplateForm TItem="BlogPostViewModel" Data="blogPostViewModel" Submit="HandleValidSubmit">
<RadzenRow Class="rz-mb-2">
<RadzenColumn Size="12" SizeMD="3" SizeLG="3">
<RadzenLabel Component="textBoxTitle" Text="Title" style="width: 100%" />
</RadzenColumn>
<RadzenColumn Size="12" SizeMD="9" SizeLG="9">
<RadzenTextBox Name="textBoxTitle" @bind-Value="@blogPostViewModel.Title" Placeholder="Title" style="width: 100%" />
<RadzenRequiredValidator Component="textBoxTitle" />
</RadzenColumn>
</RadzenRow>
<RadzenRow Class="rz-mb-2">
<RadzenColumn Size="12" SizeMD="3" SizeLG="3">
<RadzenLabel Component="textBoxContent" Text="Content" style="width: 100%" />
</RadzenColumn>
<RadzenColumn Size="12" SizeMD="9" SizeLG="9">
<RadzenTextBox Name="textBoxContent" @bind-Value="@blogPostViewModel.Content" Placeholder="Content" style="width: 100%" />
<RadzenRequiredValidator Component="textBoxContent" />
</RadzenColumn>
</RadzenRow>
<RadzenStack Orientation="Orientation.Horizontal" AlignItems="AlignItems.Center" JustifyContent="JustifyContent.Start">
<RadzenButton ButtonType="ButtonType.Submit" ButtonStyle="ButtonStyle.Success" Icon="save" Text="Save" Variant="Variant.Flat" />
</RadzenStack>
</RadzenTemplateForm>
</RadzenStack>
</RadzenFieldset>
</RadzenStack>
<RadzenButton Text="Back" Icon="arrow_back" Class="rz-mt-2"
Click="NavigatetoBlogPostIndex"
ButtonStyle="ButtonStyle.Primary" />
}
@code {
private BlogPostViewModel? blogPostViewModel;
protected override void OnInitialized()
{
blogPostViewModel = new();
}
protected async Task HandleValidSubmit()
{
if (blogPostViewModel == null) return;
var blogPost = Mapper.Map<BlogPostViewModel, BlogPost>(blogPostViewModel);
bool result = await BlogPostService.AddBlogPostAsync(blogPost);
if (result)
NavigationManager.NavigateTo("/BlogPost/");
}
private void NavigatetoBlogPostIndex() => NavigationManager.NavigateTo("/BlogPost");
}

View File

@@ -0,0 +1,89 @@
@page "/BlogPost/Delete/{id:int}"
<h3>Delete</h3>
@if (blogPostViewModel == null)
{
<p>Loading...</p>
}
else
{
<RadzenStack>
<RadzenFieldset Text="Post Delete">
<RadzenStack>
<RadzenRow AlignItems="AlignItems.Center" Class="rz-mb-2">
<RadzenColumn SizeSM="12" SizeMD="2" SizeLG="2">
<RadzenLabel Text="Id" for="id" />
</RadzenColumn>
<RadzenColumn SizeSM="12" SizeMD="10" SizeLG="10">
<RadzenTextBox id="id" Value="@blogPostViewModel.Id.ToString()"
ReadOnly=true Style="width:100%" />
</RadzenColumn>
</RadzenRow>
<RadzenRow AlignItems="AlignItems.Center" Class="rz-mb-2">
<RadzenColumn SizeSM="12" SizeMD="2" SizeLG="2">
<RadzenLabel Text="Title" for="title" />
</RadzenColumn>
<RadzenColumn SizeSM="12" SizeMD="10" SizeLG="10">
<RadzenTextBox id="title" Value="@blogPostViewModel.Title"
ReadOnly=true Style="width:100%" />
</RadzenColumn>
</RadzenRow>
<RadzenRow AlignItems="AlignItems.Center" Class="rz-mb-2">
<RadzenColumn SizeSM="12" SizeMD="2" SizeLG="2">
<RadzenLabel Text="Content" for="content" />
</RadzenColumn>
<RadzenColumn SizeSM="12" SizeMD="10" SizeLG="10">
<RadzenTextBox id="content" Value="@blogPostViewModel.Content"
ReadOnly=true Style="width:100%" />
</RadzenColumn>
</RadzenRow>
</RadzenStack>
<RadzenButton Text="REMOVE" Icon="delete_forever" ButtonStyle="ButtonStyle.Danger"
Click="RemoveButtonClick" />
</RadzenFieldset>
</RadzenStack>
<RadzenButton Text="Back" Icon="arrow_back" Class="rz-mt-2"
Click="NavigatetoBlogPostIndex"
ButtonStyle="ButtonStyle.Primary" />
}
@code {
[Parameter]
public int id { get; set; }
BlogPostViewModel? blogPostViewModel;
protected override async Task OnInitializedAsync()
{
if (blogPostViewModel == null)
{
var blogPost = await BlogPostService.GetbyId(id);
if (blogPost == null)
return;
blogPostViewModel = Mapper.Map<BlogPost, BlogPostViewModel>(blogPost);
}
}
private async void RemoveButtonClick()
{
bool result = await BlogPostService.DeletebyIdAsync(id);
if (result)
NavigationManager.NavigateTo("/BlogPost");
}
private void NavigatetoBlogPostIndex() => NavigationManager.NavigateTo("/BlogPost");
}

View File

@@ -0,0 +1,78 @@
@page "/BlogPost/Detail/{id:int}"
<h3>Detail</h3>
@if (blogPostViewModel == null)
{
<p>Loading...</p>
}
else
{
<RadzenStack>
<RadzenFieldset Text="Post Detail">
<RadzenStack>
<RadzenRow AlignItems="AlignItems.Center" Class="rz-mb-2">
<RadzenColumn SizeSM="12" SizeMD="2" SizeLG="2">
<RadzenLabel Text="Id" for="id" />
</RadzenColumn>
<RadzenColumn SizeSM="12" SizeMD="10" SizeLG="10">
<RadzenTextBox id="id" Value="@blogPostViewModel.Id.ToString()"
ReadOnly=true Style="width:100%" />
</RadzenColumn>
</RadzenRow>
<RadzenRow AlignItems="AlignItems.Center" Class="rz-mb-2">
<RadzenColumn SizeSM="12" SizeMD="2" SizeLG="2">
<RadzenLabel Text="Title" for="title" />
</RadzenColumn>
<RadzenColumn SizeSM="12" SizeMD="10" SizeLG="10">
<RadzenTextBox id="title" Value="@blogPostViewModel.Title"
ReadOnly=true Style="width:100%" />
</RadzenColumn>
</RadzenRow>
<RadzenRow AlignItems="AlignItems.Center" Class="rz-mb-2">
<RadzenColumn SizeSM="12" SizeMD="2" SizeLG="2">
<RadzenLabel Text="Content" for="content" />
</RadzenColumn>
<RadzenColumn SizeSM="12" SizeMD="10" SizeLG="10">
<RadzenTextBox id="content" Value="@blogPostViewModel.Content"
ReadOnly=true Style="width:100%" />
</RadzenColumn>
</RadzenRow>
</RadzenStack>
</RadzenFieldset>
</RadzenStack>
<RadzenButton Text="Back" Icon="arrow_back" Class="rz-mt-2"
Click="NavigatetoBlogPostIndex"
ButtonStyle="ButtonStyle.Primary" />
}
@code {
[Parameter]
public int id { get; set; }
BlogPostViewModel? blogPostViewModel;
protected override async Task OnInitializedAsync()
{
if (blogPostViewModel == null)
{
var blogPost = await BlogPostService.GetbyId(id);
if (blogPost == null)
return;
blogPostViewModel = Mapper.Map<BlogPost, BlogPostViewModel>(blogPost);
}
}
private void NavigatetoBlogPostIndex() => NavigationManager.NavigateTo("/BlogPost");
}

View File

@@ -0,0 +1,101 @@
@page "/BlogPost/Edit/{id:int}"
<h3>Edit</h3>
@if (blogPostViewModel == null)
{
<p>Loading...</p>
}
else
{
<RadzenStack>
<RadzenFieldset Text="Edit Post">
<RadzenStack Gap="2rem">
<RadzenTemplateForm TItem="BlogPostViewModel" Data="blogPostViewModel" Submit="HandleValidSubmit">
<RadzenRow Class="rz-mb-2">
<RadzenColumn Size="12" SizeMD="3" SizeLG="3">
<RadzenLabel Component="textBoxTitle" Text="Title" style="width: 100%" />
</RadzenColumn>
<RadzenColumn Size="12" SizeMD="9" SizeLG="9">
<RadzenTextBox Name="textBoxTitle" @bind-Value="@blogPostViewModel.Title" Placeholder="Title" style="width: 100%" />
<RadzenRequiredValidator Component="textBoxTitle" />
</RadzenColumn>
</RadzenRow>
<RadzenRow Class="rz-mb-2">
<RadzenColumn Size="12" SizeMD="3" SizeLG="3">
<RadzenLabel Component="textBoxContent" Text="Content" style="width: 100%" />
</RadzenColumn>
<RadzenColumn Size="12" SizeMD="9" SizeLG="9">
<RadzenTextBox Name="textBoxContent" @bind-Value="@blogPostViewModel.Content" Placeholder="Content" style="width: 100%" />
<RadzenRequiredValidator Component="textBoxContent" />
</RadzenColumn>
</RadzenRow>
<RadzenStack Orientation="Orientation.Horizontal" AlignItems="AlignItems.Center" JustifyContent="JustifyContent.Start">
<RadzenButton ButtonType="ButtonType.Submit" ButtonStyle="ButtonStyle.Success" Icon="save" Text="Save" Variant="Variant.Flat" />
</RadzenStack>
</RadzenTemplateForm>
</RadzenStack>
</RadzenFieldset>
</RadzenStack>
<RadzenButton Text="Back" Icon="arrow_back" Class="rz-mt-2"
Click="NavigatetoBlogPostIndex"
ButtonStyle="ButtonStyle.Primary" />
}
@code {
[Parameter]
public int id { get; set; }
BlogPostViewModel? blogPostViewModel;
protected override async Task OnInitializedAsync()
{
if (blogPostViewModel == null)
{
var blogPost = await BlogPostService.GetbyId(id);
if (blogPost == null)
return;
blogPostViewModel = Mapper.Map<BlogPost, BlogPostViewModel>(blogPost);
}
}
void OnPaste(HtmlEditorPasteEventArgs args)
{
}
void OnChange(string html)
{
}
void OnInput(string html)
{
}
void OnExecute(HtmlEditorExecuteEventArgs args)
{
}
protected async Task HandleValidSubmit()
{
if (blogPostViewModel == null) return;
var blogPost = Mapper.Map<BlogPostViewModel, BlogPost>(blogPostViewModel);
bool result = await BlogPostService.UpdateBlogPostAsync(id, blogPost);
if (result)
NavigationManager.NavigateTo("/BlogPost/");
}
private void NavigatetoBlogPostIndex() => NavigationManager.NavigateTo("/BlogPost");
}

View File

@@ -0,0 +1,81 @@
@page "/BlogPost"
<PageTitle>Posts</PageTitle>
<RadzenRow>
<RadzenColumn SizeSM="12" SizeMD="12" SizeLG="4">
<RadzenStack Orientation="Orientation.Horizontal" AlignItems="AlignItems.Center">
<RadzenText Text="Posts" TextStyle="TextStyle.H5" />
<RadzenButton Text="Create" Icon="add_circle_outline"
Click="NavigatetoCreate"
ButtonStyle="ButtonStyle.Success" class="rz-mb-2 rz-p-2" />
</RadzenStack>
</RadzenColumn>
</RadzenRow>
<RadzenDataGrid KeyProperty="Id" IsLoading="@isLoading" ShowPagingSummary=true
Count="@totalCount" Data="@blogPosts" LoadData="@LoadData"
FilterPopupRenderMode="PopupRenderMode.OnDemand"
FilterCaseSensitivity="FilterCaseSensitivity.CaseInsensitive"
FilterMode="FilterMode.Advanced" AllowSorting="true" AllowFiltering="true"
AllowPaging="true" PageSize="@itemPageSize" PagerHorizontalAlign="HorizontalAlign.Center"
TItem="BlogPostViewModel" ColumnWidth="200px">
<Columns>
<RadzenDataGridColumn TItem="BlogPostViewModel" Property="Id" Filterable="false" Title="Id" Frozen="true" Width="30px" MinWidth="30px" TextAlign="TextAlign.Center" />
<RadzenDataGridColumn TItem="BlogPostViewModel" Property="Title" Title="Title" />
<RadzenDataGridColumn TItem="BlogPostViewModel" Property="Content" Title="Content" />
<RadzenDataGridColumn TItem="BlogPostViewModel" Context="blogPost" Filterable="false" Sortable="false" Width="150px" TextAlign="TextAlign.Center">
<Template Context="blogPost">
<RadzenRow JustifyContent="JustifyContent.Center">
<RadzenButton Icon="pageview" ButtonStyle="ButtonStyle.Info" Variant="Variant.Flat" Size="ButtonSize.Medium"
Click="@(args => NavigatetoDetail(blogPost.Id))" @onclick:stopPropagation="true">
</RadzenButton>
<RadzenButton Icon="edit" ButtonStyle="ButtonStyle.Warning" Variant="Variant.Flat" Size="ButtonSize.Medium"
Click="@(args => NavigatetoEdit(blogPost.Id))" @onclick:stopPropagation="true">
</RadzenButton>
<RadzenButton Icon="delete_forever" ButtonStyle="ButtonStyle.Danger" Variant="Variant.Flat" Size="ButtonSize.Medium"
Click="@(args => NavigatetoDelete(blogPost.Id))" @onclick:stopPropagation="true">
</RadzenButton>
</RadzenRow>
</Template>
</RadzenDataGridColumn>
</Columns>
</RadzenDataGrid>
@code {
const int itemPageSize = 10;
private bool isLoading;
private int totalCount;
private IEnumerable<BlogPostViewModel>? blogPosts;
private async Task LoadData(LoadDataArgs args)
{
isLoading = true;
var result = await BlogPostService.GetBlogPostsAsync(filter: args.Filter, top: args.Top, skip: args.Skip, orderby: args.OrderBy, count: true);
blogPosts = Mapper.Map<IEnumerable<BlogPost>, IEnumerable<BlogPostViewModel>>(result.Result);
totalCount = result.TotalCount;
isLoading = false;
}
private void NavigatetoCreate() => NavigationManager.NavigateTo("/BlogPost/Create");
private void NavigatetoDetail(int id) => NavigationManager.NavigateTo($"/BlogPost/Detail/{id}");
private void NavigatetoEdit(int id) => NavigationManager.NavigateTo($"/BlogPost/Edit/{id}");
private void NavigatetoDelete(int id) => NavigationManager.NavigateTo($"/BlogPost/Delete/{id}");
}

View File

@@ -0,0 +1,7 @@
@using BlazorAppRadzenNet8UpgradeRadzen4to5.Data;
@using BlazorAppRadzenNet8UpgradeRadzen4to5.Models;
@using BlazorAppRadzenNet8UpgradeRadzen4to5.Services;
@using BlazorAppRadzenNet8UpgradeRadzen4to5.ViewModels;
@inject NavigationManager NavigationManager
@inject BlogPostService BlogPostService

View File

@@ -0,0 +1,36 @@
@page "/Error"
@using System.Diagnostics
<PageTitle>Error</PageTitle>
<h1 class="text-danger">Error.</h1>
<h2 class="text-danger">An error occurred while processing your request.</h2>
@if (ShowRequestId)
{
<p>
<strong>Request ID:</strong> <code>@RequestId</code>
</p>
}
<h3>Development Mode</h3>
<p>
Swapping to <strong>Development</strong> environment will display more 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.
</p>
@code{
[CascadingParameter]
private HttpContext? HttpContext { get; set; }
private string? RequestId { get; set; }
private bool ShowRequestId => !string.IsNullOrEmpty(RequestId);
protected override void OnInitialized() =>
RequestId = Activity.Current?.Id ?? HttpContext?.TraceIdentifier;
}

View File

@@ -0,0 +1,7 @@
@page "/"
<PageTitle>Home</PageTitle>
<h1>Hello, world!</h1>
Welcome to your new app.

View File

@@ -0,0 +1,17 @@
<Router AppAssembly="@typeof(Program).Assembly">
<Found Context="routeData">
<RouteView RouteData="routeData" DefaultLayout="typeof(Layout.MainLayout)" />
@* <FocusOnNavigate RouteData="routeData" Selector="h1" /> *@
</Found>
<NotFound>
<PageTitle>Not found</PageTitle>
<LayoutView Layout="@typeof(Layout.MainLayout)">
<RadzenRow>
<RadzenColumn Size="12" style="margin-top: 5rem; margin-bottom: 5rem">
<RadzenText Text="Page not found" TextStyle="TextStyle.DisplayH1" style="margin: 0; margin-bottom: 2rem" TextAlign="TextAlign.Center" />
<RadzenText Text="Sorry, but there's nothing here!" TextStyle="TextStyle.H6" style="margin: 0" TextAlign="TextAlign.Center" TagName="TagName.P" />
</RadzenColumn>
</RadzenRow>
</LayoutView>
</NotFound>
</Router>

View File

@@ -0,0 +1,16 @@
@using System.Net.Http
@using System.Net.Http.Json
@using Microsoft.AspNetCore.Components.Forms
@using Microsoft.AspNetCore.Components.Routing
@using Microsoft.AspNetCore.Components.Web
@using static Microsoft.AspNetCore.Components.Web.RenderMode
@using Microsoft.AspNetCore.Components.Web.Virtualization
@using Microsoft.JSInterop
@using BlazorAppRadzenNet8UpgradeRadzen4to5
@using BlazorAppRadzenNet8UpgradeRadzen4to5.Components
@using MapsterMapper
@using Radzen
@using Radzen.Blazor
@inject IMapper Mapper

View File

@@ -0,0 +1,19 @@
using BlazorAppRadzenNet8UpgradeRadzen4to5.Models;
using Microsoft.EntityFrameworkCore;
namespace BlazorAppRadzenNet8UpgradeRadzen4to5.Data;
public class ApplicationDbContext : DbContext
{
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
: base(options)
{
}
public DbSet<BlogPost> BlogPosts => Set<BlogPost>();
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
}
}

View File

@@ -0,0 +1,101 @@
using BlazorAppRadzenNet8UpgradeRadzen4to5.Models;
namespace BlazorAppRadzenNet8UpgradeRadzen4to5.Data;
public class SeedData
{
private readonly ApplicationDbContext _context;
public SeedData(ApplicationDbContext context)
{
_context = context;
}
public async Task CreateInitialData()
{
var posts = GetAllBlogPosts();
await _context.BlogPosts.AddRangeAsync(posts);
await _context.SaveChangesAsync();
}
private static IEnumerable<BlogPost> GetAllBlogPosts()
{
List<BlogPost> posts = new();
for (int i = 0; i < 50; i++)
{
BlogPost post = new() { Id = i + 1, Title = titles[i], Content = contents[i % 10] };
posts.Add(post);
}
return posts;
}
private static readonly string[] titles = {
"Introduction to Object-Oriented Programming",
"Mastering Data Structures and Algorithms",
"Building Web Applications with ASP.NET",
"Creating Mobile Apps with Xamarin",
"Exploring Artificial Intelligence and Machine Learning",
"Understanding Functional Programming Concepts",
"Developing Games with Unity",
"Securing Web Applications from Cyber Attacks",
"Optimizing Code Performance for Better Efficiency",
"Implementing Design Patterns in Software Development",
"Testing and Debugging Strategies for Reliable Software",
"Working with Databases and SQL",
"Building Responsive User Interfaces with HTML and CSS",
"Exploring Cloud Computing and Serverless Architecture",
"Developing Cross-Platform Applications with React Native",
"Introduction to Internet of Things (IoT)",
"Creating Scalable Microservices with Docker and Kubernetes",
"Understanding Network Protocols and TCP/IP",
"Building RESTful APIs with Node.js and Express",
"Exploring Big Data Analytics and Apache Hadoop",
"Mastering Version Control with Git and GitHub",
"Developing Desktop Applications with WPF",
"Securing Mobile Applications from Malicious Attacks",
"Optimizing Database Performance with Indexing",
"Implementing Continuous Integration and Deployment",
"Testing Mobile Apps on Different Platforms",
"Working with NoSQL Databases like MongoDB",
"Building Progressive Web Apps with React",
"Exploring Quantum Computing and Quantum Algorithms",
"Introduction to Cybersecurity and Ethical Hacking",
"Creating Chatbots with Natural Language Processing",
"Understanding Software Development Life Cycle",
"Developing Augmented Reality (AR) Applications",
"Securing Web APIs with OAuth and JWT",
"Optimizing Front-End Performance for Better User Experience",
"Implementing Machine Learning Models with TensorFlow",
"Testing Web Applications for Cross-Browser Compatibility",
"Working with Blockchain Technology and Smart Contracts",
"Building Real-Time Applications with SignalR",
"Exploring Cryptography and Encryption Techniques",
"Introduction to Agile Software Development",
"Creating Voice User Interfaces with Amazon Alexa",
"Understanding Web Accessibility and Inclusive Design",
"Developing Natural Language Processing Applications",
"Securing Cloud Infrastructure and Services",
"Optimizing Backend Performance for Scalability",
"Implementing Continuous Monitoring and Alerting",
"Testing APIs with Postman and Swagger",
"Working with Data Visualization Libraries like D3.js",
"Building E-commerce Applications with Shopify",
"Exploring Robotic Process Automation (RPA)",
"Introduction to DevOps and CI/CD Pipelines"
};
private static readonly string[] contents = new string[]
{
"Lorem ipsum dolor sit amet, consectetur t.",
"Sed ut perspiciatis unde omnis iste natuccusantium doloremque laudantium.",
"Nemo enim ipsam voluptatem quia voluptas aut fugit.",
"Quis autem vel eum iure reprehenderit quesse quam nihil molestiae consequatur.",
"At vero eos et accusamus et iusto odio d.",
"Similique sunt in culpa qui officia de.",
"Et harum quidem rerum facilis est et expio.",
"Nam libero tempore, cum soluta nobis est.",
"Omnis voluptas assumenda est, omnis dolo",
"Temporibus autem quibusdam et aut offic"
};
}

View File

@@ -0,0 +1,8 @@
namespace BlazorAppRadzenNet8UpgradeRadzen4to5.Models;
public class BlogPost
{
public int Id { get; set; }
public string Title { get; set; } = string.Empty;
public string Content { get; set; } = string.Empty;
}

View File

@@ -0,0 +1,94 @@
using BlazorAppRadzenNet8UpgradeRadzen4to5.Components;
using BlazorAppRadzenNet8UpgradeRadzen4to5.Data;
using BlazorAppRadzenNet8UpgradeRadzen4to5.Services;
using BlazorAppRadzenNet8UpgradeRadzen4to5.ViewModels;
using Mapster;
using MapsterMapper;
using Microsoft.EntityFrameworkCore;
using Radzen;
using System.Reflection;
internal class Program
{
private static void Main(string[] args)
{
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddDbContext<ApplicationDbContext>(options =>
options.UseInMemoryDatabase("ConnectionInMemory")
);
builder.Services.AddScoped<SeedData>();
builder.Services.AddScoped<BlogPostService>();
// Radzen Services
builder.Services.AddScoped<DialogService>();
builder.Services.AddScoped<NotificationService>();
builder.Services.AddScoped<TooltipService>();
builder.Services.AddScoped<ContextMenuService>();
// Add mapster mapper
builder.Services.AddMapster();
builder.Services.CreateDatabase().GetAwaiter().GetResult();
builder.Services.AddDatabaseDeveloperPageExceptionFilter();
// Add services to the container.
// Add services to the container.
builder.Services.AddRazorComponents()
.AddInteractiveServerComponents().AddHubOptions(options => options.MaximumReceiveMessageSize = 10 * 1024 * 1024);
builder.Services.AddControllers();
builder.Services.AddRadzenComponents();
builder.Services.AddHttpClient();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error", createScopeForErrors: true);
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.MapControllers();
app.UseStaticFiles();
app.UseAntiforgery();
app.MapRazorComponents<App>()
.AddInteractiveServerRenderMode();
app.Run();
}
}
public static class ServiceCollectionExtensions
{
public static async Task CreateDatabase(this IServiceCollection services)
{
using (IServiceScope tmp = services.BuildServiceProvider().CreateScope())
{
await using var _context = tmp.ServiceProvider.GetRequiredService<ApplicationDbContext>();
var seedData = tmp.ServiceProvider.GetRequiredService<SeedData>();
await seedData.CreateInitialData();
}
}
}
public static class MapsterConfiguration
{
public static void AddMapster(this IServiceCollection services)
{
var typeAdapterConfig = TypeAdapterConfig.GlobalSettings;
Assembly applicationAssembly = typeof(BaseViewModel<,>).Assembly;
typeAdapterConfig.Scan(applicationAssembly);
var mapperConfig = new Mapper(typeAdapterConfig);
services.AddSingleton<IMapper>(mapperConfig);
}
}

View File

@@ -0,0 +1,14 @@
{
"$schema": "http://json.schemastore.org/launchsettings.json",
"profiles": {
"https": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"applicationUrl": "https://localhost:5001;http://localhost:5000",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}

View File

@@ -0,0 +1,90 @@
using BlazorAppRadzenNet8UpgradeRadzen4to5.Data;
using BlazorAppRadzenNet8UpgradeRadzen4to5.Models;
using Microsoft.EntityFrameworkCore;
using Radzen;
using System.Linq.Dynamic.Core;
namespace BlazorAppRadzenNet8UpgradeRadzen4to5.Services;
public class BlogPostService
{
private readonly ApplicationDbContext _context;
public BlogPostService(ApplicationDbContext context)
{
_context = context;
}
public Task<BlogPost?> GetbyId(int id)
{
return _context.BlogPosts.FirstOrDefaultAsync(x => x.Id == id);
}
public async Task<(IEnumerable<BlogPost> Result, int TotalCount)> GetBlogPostsAsync(string? filter = default, int? top = default, int? skip = default, string? orderby = default, string? expand = default, string? select = default, bool? count = default)
{
var query = _context.BlogPosts.AsQueryable();
if (!string.IsNullOrEmpty(filter))
query = query.Where(filter);
if (!string.IsNullOrEmpty(orderby))
query = query.OrderBy(orderby);
int totalCount = 0;
if (count == true)
totalCount = query.Count();
IEnumerable<BlogPost>? result;
if (skip == null || top == null)
result = await query.ToListAsync();
else
result = await query.Skip(skip.Value).Take(top.Value).ToListAsync();
return (result, totalCount);
}
public async Task<bool> AddBlogPostAsync(BlogPost blogPost)
{
try
{
await _context.BlogPosts.AddAsync(blogPost);
await _context.SaveChangesAsync();
}
catch (Exception ex)
{
return false;
}
return true;
}
public async Task<bool> UpdateBlogPostAsync(int id, BlogPost blogPost)
{
try
{
var oldBlogPost = _context.BlogPosts.FirstOrDefault(x => x.Id == id);
if (oldBlogPost == null) return false;
oldBlogPost.Title = blogPost.Title;
oldBlogPost.Content = blogPost.Content;
await _context.SaveChangesAsync();
}
catch (Exception ex)
{
return false;
}
return true;
}
public async Task<bool> DeletebyIdAsync(int id)
{
var blogPost = await _context.BlogPosts.FirstOrDefaultAsync(x => x.Id == id);
if (blogPost == null)
return false;
_context.BlogPosts.Remove(blogPost);
await _context.SaveChangesAsync();
return true;
}
}

View File

@@ -0,0 +1,46 @@
using Mapster;
namespace BlazorAppRadzenNet8UpgradeRadzen4to5.ViewModels;
/// <summary>
/// Model <-> ViewModel Mapping
/// </summary>
/// <typeparam name="TViewModel">ViewModel</typeparam>
/// <typeparam name="TModel">Model</typeparam>
public abstract class BaseViewModel<TViewModel, TModel> : IRegister
where TViewModel : class, new()
where TModel : class, new()
{
public TModel ToModel()
{
return this.Adapt<TModel>();
}
public TModel ToModel(TModel model)
{
return (this as TViewModel).Adapt(model);
}
public static TViewModel FromModel(TModel model)
{
return model.Adapt<TViewModel>();
}
private TypeAdapterConfig Config { get; set; }
public virtual void AddCustomMappings() { }
protected TypeAdapterSetter<TViewModel, TModel> SetCustomMappings()
=> Config.ForType<TViewModel, TModel>();
protected TypeAdapterSetter<TModel, TViewModel> SetCustomMappingsInverse()
=> Config.ForType<TModel, TViewModel>();
public void Register(TypeAdapterConfig config)
{
Config = config;
AddCustomMappings();
}
}

View File

@@ -0,0 +1,19 @@
using BlazorAppRadzenNet8UpgradeRadzen4to5.Models;
using System.ComponentModel.DataAnnotations;
namespace BlazorAppRadzenNet8UpgradeRadzen4to5.ViewModels;
public class BlogPostViewModel : BaseViewModel<BlogPostViewModel, BlogPost>
{
public int Id { get; set; }
[Required(AllowEmptyStrings = false, ErrorMessage = "Title can not be empty")]
public string Title { get; set; } = string.Empty;
[Required(AllowEmptyStrings = false, ErrorMessage = "Content can not be empty")]
public string Content { get; set; } = string.Empty;
public string TitleShort { get; set; } = string.Empty;
public string ContentShort { get; set; } = string.Empty;
}

View File

@@ -0,0 +1,8 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
}
}

View File

@@ -0,0 +1,9 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*"
}

View File

@@ -0,0 +1,86 @@
#blazor-error-ui {
background: lightyellow;
bottom: 0;
box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.2);
display: none;
left: 0;
padding: 0.6rem 1.25rem 0.7rem 1.25rem;
position: fixed;
width: 100%;
z-index: 1000;
}
#blazor-error-ui .dismiss {
cursor: pointer;
position: absolute;
right: 0.75rem;
top: 0.5rem;
}
:root {
font-size: var(--rz-root-font-size);
}
body {
font-family: var(--rz-text-font-family);
color: var(--rz-text-color);
font-size: var(--rz-body-font-size);
line-height: var(--rz-body-line-height);
background-color: var(--rz-body-background-color);
}
.rz-body {
--rz-body-padding: 0;
}
a {
color: var(--rz-link-color);
}
a:hover,
a:focus {
color: var(--rz-link-hover-color);
}
.blazor-error-boundary {
background: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTYiIGhlaWdodD0iNDkiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIG92ZXJmbG93PSJoaWRkZW4iPjxkZWZzPjxjbGlwUGF0aCBpZD0iY2xpcDAiPjxyZWN0IHg9IjIzNSIgeT0iNTEiIHdpZHRoPSI1NiIgaGVpZ2h0PSI0OSIvPjwvY2xpcFBhdGg+PC9kZWZzPjxnIGNsaXAtcGF0aD0idXJsKCNjbGlwMCkiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0yMzUgLTUxKSI+PHBhdGggZD0iTTI2My41MDYgNTFDMjY0LjcxNyA1MSAyNjUuODEzIDUxLjQ4MzcgMjY2LjYwNiA1Mi4yNjU4TDI2Ny4wNTIgNTIuNzk4NyAyNjcuNTM5IDUzLjYyODMgMjkwLjE4NSA5Mi4xODMxIDI5MC41NDUgOTIuNzk1IDI5MC42NTYgOTIuOTk2QzI5MC44NzcgOTMuNTEzIDI5MSA5NC4wODE1IDI5MSA5NC42NzgyIDI5MSA5Ny4wNjUxIDI4OS4wMzggOTkgMjg2LjYxNyA5OUwyNDAuMzgzIDk5QzIzNy45NjMgOTkgMjM2IDk3LjA2NTEgMjM2IDk0LjY3ODIgMjM2IDk0LjM3OTkgMjM2LjAzMSA5NC4wODg2IDIzNi4wODkgOTMuODA3MkwyMzYuMzM4IDkzLjAxNjIgMjM2Ljg1OCA5Mi4xMzE0IDI1OS40NzMgNTMuNjI5NCAyNTkuOTYxIDUyLjc5ODUgMjYwLjQwNyA1Mi4yNjU4QzI2MS4yIDUxLjQ4MzcgMjYyLjI5NiA1MSAyNjMuNTA2IDUxWk0yNjMuNTg2IDY2LjAxODNDMjYwLjczNyA2Ni4wMTgzIDI1OS4zMTMgNjcuMTI0NSAyNTkuMzEzIDY5LjMzNyAyNTkuMzEzIDY5LjYxMDIgMjU5LjMzMiA2OS44NjA4IDI1OS4zNzEgNzAuMDg4N0wyNjEuNzk1IDg0LjAxNjEgMjY1LjM4IDg0LjAxNjEgMjY3LjgyMSA2OS43NDc1QzI2Ny44NiA2OS43MzA5IDI2Ny44NzkgNjkuNTg3NyAyNjcuODc5IDY5LjMxNzkgMjY3Ljg3OSA2Ny4xMTgyIDI2Ni40NDggNjYuMDE4MyAyNjMuNTg2IDY2LjAxODNaTTI2My41NzYgODYuMDU0N0MyNjEuMDQ5IDg2LjA1NDcgMjU5Ljc4NiA4Ny4zMDA1IDI1OS43ODYgODkuNzkyMSAyNTkuNzg2IDkyLjI4MzcgMjYxLjA0OSA5My41Mjk1IDI2My41NzYgOTMuNTI5NSAyNjYuMTE2IDkzLjUyOTUgMjY3LjM4NyA5Mi4yODM3IDI2Ny4zODcgODkuNzkyMSAyNjcuMzg3IDg3LjMwMDUgMjY2LjExNiA4Ni4wNTQ3IDI2My41NzYgODYuMDU0N1oiIGZpbGw9IiNGRkU1MDAiIGZpbGwtcnVsZT0iZXZlbm9kZCIvPjwvZz48L3N2Zz4=) no-repeat 1rem/1.8rem, #b32121;
padding: 1rem 1rem 1rem 3.7rem;
color: white;
}
.blazor-error-boundary::after {
content: "An error has occurred."
}
.loading-progress {
position: relative;
display: block;
width: 8rem;
height: 8rem;
margin: 20vh auto 1rem auto;
}
.loading-progress circle {
fill: none;
stroke: #e0e0e0;
stroke-width: 0.6rem;
transform-origin: 50% 50%;
transform: rotate(-90deg);
}
.loading-progress circle:last-child {
stroke: #1b6ec2;
stroke-dasharray: calc(3.141 * var(--blazor-load-percentage, 0%) * 0.8), 500%;
transition: stroke-dasharray 0.05s ease-in-out;
}
.loading-progress-text {
position: absolute;
text-align: center;
font-weight: bold;
inset: calc(20vh + 3.25rem) 0 auto 0.2rem;
}
.loading-progress-text:after {
content: var(--blazor-load-percentage-text, "Loading");
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 164 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB