using System.ComponentModel;
using System.Web;
using AngleSharp;
using Dpz.Core.Entity.Base;
using Dpz.Core.EnumLibrary;
using Dpz.Core.Public.ViewModel.Response;
using Dpz.Core.Service.ObjectStorage.Services;
using Markdig;
using Microsoft.AspNetCore.Mvc.ModelBinding;
#pragma warning disable CS0162
namespace Dpz.Core.Web.Library;
public static class WebToolsExtensions
{
public const string DefaultGroupId = "5e09be6ae22e4d3b7810b6c7";
public static readonly Dictionary<int, string> Wind = new()
{
{ 0, "静风" },
{ 1, "软风" },
{ 2, "轻风" },
{ 3, "微风" },
{ 4, "和风" },
{ 5, "清风" },
{ 6, "强风" },
{ 7, "疾风" },
{ 8, "大风" },
{ 9, "强大风" },
{ 10, "超强大风" },
{ 11, "暴风" },
{ 12, "飓风" },
};
/// <summary>
/// 系统启动时间
/// </summary>
public static readonly DateTime StartTime = new(2018, 2, 11, 13, 56, 24, DateTimeKind.Local);
/// <summary>
/// 设置标题
/// </summary>
/// <param name="controller"></param>
/// <param name="title"></param>
public static void SetTitle(this Controller controller, string title)
{
controller.ViewData["Title"] = $"{title} - 叫我阿胖";
}
/// <summary>
/// 判断客户端是否期望 JSON 响应
/// </summary>
/// <param name="request"></param>
/// <returns></returns>
public static bool ExpectsJsonResponse(this HttpRequest request)
{
// 检查 Accept 头,客户端期望 JSON 响应
var accept = request.Headers.Accept.ToString();
if (accept.Contains("application/json", StringComparison.OrdinalIgnoreCase))
{
return true;
}
// 检查 Content-Type,请求体是 JSON
var contentType = request.ContentType;
if (contentType?.Contains("application/json", StringComparison.OrdinalIgnoreCase) == true)
{
return true;
}
// 保持对老式 AJAX 请求的兼容性
var with = request.Headers["X-Requested-With"];
return string.Equals(with, "XMLHttpRequest", StringComparison.OrdinalIgnoreCase);
}
/// <summary>
/// 获取枚举描述
/// </summary>
/// <param name="e"></param>
/// <returns></returns>
public static string GetDescription(this Enum e)
{
var value = e.ToString();
var attribute = e.GetType().GetField(value)?.GetCustomAttribute<DescriptionAttribute>();
return attribute?.Description ?? "";
}
/// <summary>
/// 显示文件可读大小
/// </summary>
/// <param name="length"></param>
/// <returns></returns>
public static string FileSize(this long length)
{
var sizeText = length + " bytes";
if (length > 1024m && length < 1024m * 1024m * 3)
{
sizeText = (length / 1024m).ToString("F") + " KB";
}
else if (length > 1024m * 1024m * 3 && length < 1024m * 1024m * 1024m)
{
sizeText = (length / 1024m / 1024m).ToString("F") + " MB";
}
else if (length > 1024m * 1024m * 1024m)
{
sizeText = (length / 1024m / 1024m / 1024m).ToString("F") + " GB";
}
return sizeText;
}
/// <summary>
/// 从markdown转成html,并从html内容中清除链接的跳转平台,并且在新标签页打开
/// </summary>
/// <param name="content"></param>
/// <returns></returns>
public static async Task<string> ClearLinkAsync(this string content)
{
var pipeline = new MarkdownPipelineBuilder()
.UsePipeTables()
.UseTaskLists()
.UseEmphasisExtras()
.UseAutoIdentifiers()
.UseAdvancedExtensions()
.DisableHtml()
.Build();
var detail = Markdown.ToHtml(content, pipeline);
var context = BrowsingContext.New(Configuration.Default);
var document = await context.OpenAsync(y => y.Content(detail));
var images = document.GetElementsByTagName("img");
foreach (var image in images)
{
var src = image.GetAttribute("src");
image.SetAttribute("class", "lazy");
image.SetAttribute("loading", "lazy");
image.SetAttribute("src", $"{Program.LibraryHost}/loaders/bars.svg");
image.SetAttribute("data-src", src ?? $"{Program.AssetsHost}/images/notfound.png");
}
var links = document.GetElementsByTagName("a");
foreach (var item in links)
{
var href = item.GetAttribute("href");
if (href != null)
{
var uri = new Uri(href);
var parameters = HttpUtility.ParseQueryString(uri.Query);
var target = parameters["target"];
if (!string.IsNullOrEmpty(target))
{
item.SetAttribute("href", target);
}
item.SetAttribute("target", "_blank");
}
}
return document.Body?.InnerHtml ?? "";
}
public static async Task DeleteMusicAsync(
this IObjectStorageOperation objectStorageService,
MusicResponse musicResponse
)
{
if (musicResponse == null)
{
throw new ArgumentNullException(nameof(musicResponse));
}
if (string.IsNullOrEmpty(musicResponse.MusicUrl))
{
throw new ArgumentException(
"property MusicUrl is empty or null",
nameof(musicResponse.MusicUrl)
);
}
await objectStorageService.DeleteAsync(musicResponse.MusicUrl);
if (!string.IsNullOrEmpty(musicResponse.CoverUrl))
{
await objectStorageService.DeleteAsync(musicResponse.CoverUrl);
}
if (!string.IsNullOrEmpty(musicResponse.LyricUrl))
{
await objectStorageService.DeleteAsync(musicResponse.LyricUrl);
}
}
public static ModelStateResult CheckModelState(this ModelStateDictionary modelState)
{
if (modelState.IsValid)
{
var messages = modelState
.SelectMany(x => x.Value?.Errors ?? new ModelErrorCollection())
.Select(x => x.ErrorMessage)
.Where(x => !string.IsNullOrEmpty(x))
.ToList();
if (messages.Count == 0)
{
return new ModelStateResult(false, []);
}
return new ModelStateResult(true, messages);
}
return new ModelStateResult(false, []);
}
}
⚠⚠ 以下内容为AI分析的结果,请根据实际情况进行判断。
代码解释
这是一个 C# 静态扩展类 WebToolsExtensions,包含了多个工具方法和常量,用于 ASP.NET Core Web 应用程序。以下是详细解释:
常量定义
- DefaultGroupId: 默认分组ID字符串
- Wind: 风力等级字典(0-12级,对应中文描述)
- StartTime: 系统启动时间(2018年2月11日)
扩展方法
1. SetTitle
为控制器设置页面标题,格式为 "{title} - 叫我阿胖"
2. ExpectsJsonResponse
判断HTTP请求是否期望JSON响应,通过检查:
- Accept 头是否包含 "application/json"
- Content-Type 是否为 JSON
- X-Requested-With 是否为 "XMLHttpRequest"(兼容旧式AJAX)
3. GetDescription
获取枚举值的 DescriptionAttribute 描述文本
4. FileSize
将字节数转换为可读的文件大小格式:
- < 3MB: 显示为 KB
- 3MB - 1GB: 显示为 MB
- > 1GB: 显示为 GB
5. ClearLinkAsync
处理 Markdown 内容:
- 使用 Markdig 将 Markdown 转换为 HTML
- 使用 AngleSharp 解析 HTML
- 为图片添加懒加载属性(lazy loading)
- 设置图片占位符
- 修改链接在新标签页打开
- 清理链接中的跳转平台参数
6. DeleteMusicAsync
删除音乐相关的对象存储文件:
- 删除音乐文件(必需)
- 删除封面图片(如果存在)
- 删除歌词文件(如果存在)
- 包含参数验证
7. CheckModelState
检查 ASP.NET Core 的模型状态验证结果:
- 提取所有验证错误消息
- 返回
ModelStateResult对象包含验证状态和错误列表
技术特点
- 使用扩展方法模式增强现有类型功能
- 集成第三方库(Markdig、AngleSharp)
- 支持异步操作
- 包含空值检查和参数验证
- 禁用了 CS0162 编译警告(可能存在不可达代码)
AI 正在分析代码…
评论加载中...