七天.NET 8操作SQLite入门到实战 - (2)第七天Blazor班级管理页面编写和接口对接

简介: 七天.NET 8操作SQLite入门到实战 - (2)第七天Blazor班级管理页面编写和接口对接

前言

上一章节我们引入BootstrapBlazor UI组件完成了EasySQLite后台界面的基本架子的搭建,本章节的主要内容是Blazor班级管理页面编写和接口对接。

七天.NET 8 操作 SQLite 入门到实战详细教程

EasySQLite 项目源码地址

Blazor简介和快速入门

不熟悉Blazor的同学可以先看这篇文章大概了解一下。

全面的ASP.NET Core Blazor简介和快速入门

前端Table页面和接口对接代码

主要是常见Table的数据展示、数据添加、数据删除、数据修改等操作。

@page "/SchoolClass"
@using Entity
@using WebUI.Common
@inject HttpClient _httpClient;
<Table TItem="SchoolClass"
       AutoGenerateColumns="true"
       ShowToolbar="true"
       IsMultipleSelect="true"
       OnSaveAsync="@OnSaveAsync"
       OnQueryAsync="@OnQueryAsync"
       OnDeleteAsync="@OnDeleteAsync"
       IsStriped="true"
       IsBordered="true"
       ShowSearch="true"
       IsPagination="true"
       ShowSearchText="true">
    <TableColumns>
        <TableColumn Sortable="true" Filterable="true" Searchable="true" @bind-Field="@context.ClassName" PlaceHolder="请输入班级名称" />
        <TableColumn @bind-Field="@context.ClassID" IsVisibleWhenAdd="false" IsVisibleWhenEdit="false" />
        <TableColumn @bind-Field="@context.CreateTime" IsVisibleWhenAdd="false" IsVisibleWhenEdit="false" />
    </TableColumns>
    <SearchTemplate>
        <GroupBox Title="搜索条件">
            <div class="row g-3 form-inline">
                <div class="col-12 col-sm-6">
                    <BootstrapInput @bind-Value="@context.ClassName" PlaceHolder="请输入班级名称" maxlength="50" ShowLabel="true" DisplayText="姓名" />
                </div>
            </div>
        </GroupBox>
    </SearchTemplate>
</Table>
@code {
    /// <summary>
    /// 数据查询
    /// </summary>
    /// <param name="options">options</param>
    /// <returns></returns>
    private async Task<QueryData<SchoolClass>> OnQueryAsync(QueryPageOptions options)
    {
        var getClass = new List<SchoolClass>();
        var getResults = await _httpClient.GetFromJsonAsync<ApiResponse<List<SchoolClass>>>("api/SchoolClass/GetClass").ConfigureAwait(false);
        if (getResults.Success)
        {
            // 数据模糊过滤筛选
            if (!string.IsNullOrWhiteSpace(options.SearchText))
            {
                getClass = getResults.Data.Where(x => x.ClassName.Contains(options.SearchText)).ToList();
            }
            else
            {
                getClass = getResults.Data.ToList();
            }
        }
        //假分页
        return await Task.FromResult(new QueryData<SchoolClass>()
            {
                Items = getClass.Skip((options.PageIndex - 1) * options.PageItems).Take(options.PageItems).ToList(),
                TotalCount = getClass.Count()
            });
    }
    /// <summary>
    /// 模拟数据增加和修改操作
    /// </summary>
    /// <param name="studentInfo">studentInfo</param>
    /// <param name="changedType">changedType</param>
    /// <returns></returns>
    public async Task<bool> OnSaveAsync(SchoolClass studentInfo, ItemChangedType changedType)
    {
        if (changedType.ToString() == "Update")
        {
            var addResult = await _httpClient.PutAsJsonAsync($"api/SchoolClass/UpdateClass/{studentInfo.ClassID}", studentInfo).ConfigureAwait(false);
            if (UtilityBusiness.CheckResponse(addResult))
            {
                return await Task.FromResult(true);
            }
            else
            {
                return await Task.FromResult(false);
            }
        }
        else if (changedType.ToString() == "Add")
        {
            var addResult = await _httpClient.PostAsJsonAsync("api/SchoolClass/CreateClass", studentInfo).ConfigureAwait(false);
            if (UtilityBusiness.CheckResponse(addResult))
            {
                return await Task.FromResult(true);
            }
            else
            {
                return await Task.FromResult(false);
            }
        }
        return await Task.FromResult(true);
    }
    /// <summary>
    /// 数据删除
    /// </summary>
    /// <param name="items">items</param>
    /// <returns></returns>
    private async Task<bool> OnDeleteAsync(IEnumerable<SchoolClass> items)
    {
        var deleteSuccessNum = 0;
        var schoolClassList = items.ToList();
        foreach (var item in schoolClassList)
        {
            var delResult = await _httpClient.DeleteAsync($"api/SchoolClass/DeleteClass/{item.ClassID}").ConfigureAwait(false);
            if (UtilityBusiness.CheckResponse(delResult))
            {
                deleteSuccessNum++;
            }
        }
        if (deleteSuccessNum > 0)
        {
            return await Task.FromResult(true);
        }
        else
        {
            return await Task.FromResult(false);
        }
    }
}

后端API接口

using Entity;
using Microsoft.AspNetCore.Mvc;
using Utility;
namespace WebApi.Controllers
{
    /// <summary>
    /// 学校班级管理
    /// </summary>
    [ApiController]
    [Route("api/[controller]/[action]")]
    public class SchoolClassController : ControllerBase
    {
        private readonly SQLiteAsyncHelper<SchoolClass> _schoolClassHelper;
        /// <summary>
        /// 依赖注入
        /// </summary>
        /// <param name="schoolClassHelper">schoolClassHelper</param>
        public SchoolClassController(SQLiteAsyncHelper<SchoolClass> schoolClassHelper)
        {
            _schoolClassHelper = schoolClassHelper;
        }
        /// <summary>
        /// 班级创建
        /// </summary>
        /// <param name="schoolClass">创建班级信息</param>
        /// <returns></returns>
        [HttpPost]
        public async Task<ApiResponse<int>> CreateClass([FromBody] SchoolClass schoolClass)
        {
            try
            {
                var querySchoolClass = await _schoolClassHelper.QuerySingleAsync(c => c.ClassName == schoolClass.ClassName).ConfigureAwait(false);
                if (querySchoolClass != null)
                {
                    return new ApiResponse<int>
                    {
                        Success = false,
                        Message = $"创建班级失败,班级{schoolClass.ClassName}已存在"
                    };
                }
                schoolClass.CreateTime = DateTime.Now;
                int insertNumbers = await _schoolClassHelper.InsertAsync(schoolClass);
                if (insertNumbers > 0)
                {
                    return new ApiResponse<int>
                    {
                        Success = true,
                        Message = "创建班级成功"
                    };
                }
                else
                {
                    return new ApiResponse<int>
                    {
                        Success = false,
                        Message = "创建班级失败"
                    };
                }
            }
            catch (Exception ex)
            {
                return new ApiResponse<int>
                {
                    Success = false,
                    Message = ex.Message
                };
            }
        }
        /// <summary>
        /// 获取所有班级信息
        /// </summary>
        [HttpGet]
        public async Task<ApiResponse<List<SchoolClass>>> GetClass()
        {
            try
            {
                var classes = await _schoolClassHelper.QueryAllAsync().ConfigureAwait(false);
                return new ApiResponse<List<SchoolClass>>
                {
                    Success = true,
                    Data = classes
                };
            }
            catch (Exception ex)
            {
                return new ApiResponse<List<SchoolClass>>
                {
                    Success = false,
                    Message = ex.Message
                };
            }
        }
        /// <summary>
        /// 根据班级ID获取班级信息
        /// </summary>
        /// <param name="classId">班级ID</param>
        /// <returns></returns>
        [HttpGet("{classId}")]
        public async Task<ApiResponse<SchoolClass>> GetClass(int classId)
        {
            try
            {
                var schoolClass = await _schoolClassHelper.QuerySingleAsync(c => c.ClassID == classId).ConfigureAwait(false);
                if (schoolClass != null)
                {
                    return new ApiResponse<SchoolClass>
                    {
                        Success = true,
                        Data = schoolClass
                    };
                }
                else
                {
                    return new ApiResponse<SchoolClass>
                    {
                        Success = false,
                        Message = "班级不存在"
                    };
                }
            }
            catch (Exception ex)
            {
                return new ApiResponse<SchoolClass>
                {
                    Success = false,
                    Message = ex.Message
                };
            }
        }
        /// <summary>
        /// 更新班级信息
        /// </summary>
        /// <param name="classId">班级ID</param>
        /// <param name="updatedClass">更新的班级信息</param>
        /// <returns></returns>
        [HttpPut("{classId}")]
        public async Task<ApiResponse<int>> UpdateClass(int classId, [FromBody] SchoolClass updatedClass)
        {
            try
            {
                var existingClass = await _schoolClassHelper.QuerySingleAsync(c => c.ClassID == classId).ConfigureAwait(false);
                if (existingClass != null)
                {
                    existingClass.ClassName = updatedClass.ClassName;
                    var updateResult = await _schoolClassHelper.UpdateAsync(existingClass).ConfigureAwait(false);
                    if (updateResult > 0)
                    {
                        return new ApiResponse<int>
                        {
                            Success = true,
                            Message = "班级信息更新成功"
                        };
                    }
                    else
                    {
                        return new ApiResponse<int>
                        {
                            Success = false,
                            Message = "班级信息更新失败"
                        };
                    }
                }
                else
                {
                    return new ApiResponse<int>
                    {
                        Success = false,
                        Message = "班级不存在"
                    };
                }
            }
            catch (Exception ex)
            {
                return new ApiResponse<int>
                {
                    Success = false,
                    Message = ex.Message
                };
            }
        }
        /// <summary>
        /// 班级删除
        /// </summary>
        /// <param name="classId">班级ID</param>
        /// <returns></returns>
        [HttpDelete("{classId}")]
        public async Task<ApiResponse<int>> DeleteClass(int classId)
        {
            try
            {
                var deleteResult = await _schoolClassHelper.DeleteAsync(classId).ConfigureAwait(false);
                if (deleteResult > 0)
                {
                    return new ApiResponse<int>
                    {
                        Success = true,
                        Message = "班级删除成功"
                    };
                }
                else
                {
                    return new ApiResponse<int>
                    {
                        Success = true,
                        Message = "班级删除失败"
                    };
                }
            }
            catch (Exception ex)
            {
                return new ApiResponse<int>
                {
                    Success = false,
                    Message = ex.Message
                };
            }
        }
    }
}

接口对接所遇问题及其解决方案

跨源请求 (CORS)问题

在API服务端启用跨源请求 (CORS):

调用 UseCors 扩展方法并指定 PolicyCorsName CORS 策略。UseCors 添加 CORS 中间件。对 UseCors 的调用必须放在 UseRouting 之后,但在 UseAuthorization 之前。

Program.cs添加如下代码(注意中间件顺序)

var builder = WebApplication.CreateBuilder(args);
            var PolicyCorsName = "EasySQLitePolicy";
            builder.Services.AddCors(option =>
            {
                option.AddPolicy(PolicyCorsName, builder =>
                {
                    builder.AllowAnyOrigin()
                      .AllowAnyMethod()
                      .AllowAnyHeader();
                });
            });
            
           var app = builder.Build();
           
           app.UseCors(PolicyCorsName);
            app.UseAuthorization();
            app.MapControllers();
            app.Run();

System.Text.Json 反序列化时间异常问题

异常:

Microsoft.AspNetCore.Components.Web.ErrorBoundary[0]
      System.Text.Json.JsonException: The JSON value could not be converted to System.DateTime. Path: $.Data[0].CreateTime | LineNumber: 0 | BytePositionInLine: 113.
       ---> System.FormatException: The JSON value is not in a supported DateTime format.
         at System.Text.Json.ThrowHelper.ThrowFormatException(DataType dataType)
         at System.Text.Json.Utf8JsonReader.GetDateTime()
         at System.Text.Json.Serialization.Converters.DateTimeConverter.Read(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options)

异常原因:

System.Text.Json 时间是认标准的. yyyy-MM-ddTHH:mm:ss 中间得有个T

解决方案:

注释掉服务端对时间日期类型默认格式化处理!

参考文章

相关文章
|
6天前
|
开发框架 安全 .NET
ASP.NET三甲医院手术麻醉信息管理系统源码 对接麻醉机、监护仪、血气分析仪
辅助医院建设 •支持三级医院评级需求 •支持智慧医院评级需求 •支持互联互通评级需求 •支持电子病历评级需求
23 0
|
6天前
|
开发框架 前端开发 .NET
七天.NET 8操作SQLite入门到实战 - (1)第七天BootstrapBlazor UI组件库引入
七天.NET 8操作SQLite入门到实战 - (1)第七天BootstrapBlazor UI组件库引入
|
6天前
|
存储 监控 安全
内网屏幕监控软件的数据存储与管理:使用SQLite数据库保存监控记录和配置信息
在当今数字化时代,安全和监控在企业和组织中变得至关重要。内网屏幕监控软件作为一种关键工具,帮助组织监视员工的活动并确保信息安全。这种软件不仅需要高效地记录和管理监控数据,还需要能够方便地进行配置和调整。本文将讨论如何使用SQLite数据库来保存监控记录和配置信息,并介绍如何通过自动化机制将监控到的数据提交到指定网站。
188 2
|
6天前
|
机器学习/深度学习 数据挖掘 Go
中科院二区7.4分|NET基因肿瘤分型+生存预后模型+分子对接
在《Journal of Translational Medicine》上发表的最新研究中,科学家们鉴定了一种新的NET相关基因签名,用于预测弥漫性大B细胞淋巴瘤(DLBCL)患者的预后。他们发现8个基因(PARVB,LYZ,PPARGC1A,HIF1A,SPP1,CDH1,S100A9和CXCL2)与DLBCL生存率显著相关,建立了NRG遗传风险模型,该模型可能有助于指导DLBCL的治疗选择。研究包括基因表达数据的分析、预后特征的构建和验证,以及与免疫微环境和潜在治疗靶点的相关性探索。
27 0
|
6天前
|
开发框架 .NET 物联网
.NET从入门到精通,零基础也能搞定的基础知识教程
.NET从入门到精通,零基础也能搞定的基础知识教程
26 0
|
6天前
|
开发框架 .NET 程序员
C#/.NET该如何自学入门?
C#/.NET该如何自学入门?
|
6天前
|
存储 数据库连接 数据库
Android数据存储:解释SQLite数据库在Android中的使用。
Android数据存储:解释SQLite数据库在Android中的使用。
47 0
|
9月前
|
API 数据库 Android开发
Android 中SQLite数据库的使用详解
Android 中SQLite数据库的使用详解
64 0
|
9月前
|
数据库 Android开发 数据库管理
Android使用Room操作SQLite数据库让其变得无比高效和简洁(进一步完善用RecyclerView显示数据库中的数据)
Android使用Room操作SQLite数据库让其变得无比高效和简洁(进一步完善用RecyclerView显示数据库中的数据)
53 0