AI Agent在CRM与ERP系统中的集成方法及应用实证-云社区-华为云

mikel阅读(111)

来源: AI Agent在CRM与ERP系统中的集成方法及应用实证-云社区-华为云

AI Agent 工作流集成:与业务系统协作的实现方式

随着大型语言模型(LLM)与多模态模型的发展,AI Agent 不再只是独立的对话机器人,而成为可感知、可行动、可编排的智能执行体。将其有效地集成入企业级业务系统,是推动智能化办公、自动化处理和个性化服务的关键。

本文将系统性地探讨 AI Agent 如何与现有业务系统集成,涵盖工作流设计、系统架构、关键模块开发以及集成案例,并附带代码实现。

image.png

1. AI Agent 系统集成的背景与需求

1.1 为什么需要将 AI Agent 与业务系统集成?

  • 业务驱动:自动处理工单、客户服务、报告生成、风险预警等任务。
  • 智能增强:赋能原有系统,实现更智能的决策辅助与流程自动化。
  • 成本效率:减少人工干预,提升运行效率,降低服务成本。

1.2 常见的业务系统类型

  • CRM(客户关系管理系统)
  • ERP(企业资源计划系统)
  • 工单系统(如 Jira、Zendesk)
  • 数据仓库与BI平台(如 Snowflake、Tableau)
  • API服务(如第三方支付、邮件系统)

2. AI Agent 工作流的架构设计

2.1 总体架构图

用户指令 → LLM/Agent → 工作流引擎(LangGraph)→ 调用业务系统 API → 返回结果/触发操作

2.2 模块划分

  • 自然语言理解层(LLM)
  • Agent 执行策略层(如 ReAct, MRKL, Plan-and-Execute)
  • 工作流控制器(如 LangGraph, LangChain Expression Language)
  • 系统 API 适配器
  • 日志监控与安全机制

3. 工作流实现:LangGraph + OpenAI Function Calling 示例

我们通过 LangGraph 构建一个简单的 AI Agent 流程,实现对 CRM 系统的客户信息查询和更新。

3.1 环境准备

pip install langgraph openai requests

3.2 CRM 模拟 API

# mock_crm_api.py
import time

DB = {
    "Alice": {"email": "alice@example.com", "status": "active"},
    "Bob": {"email": "bob@example.com", "status": "inactive"}
}

def get_customer_info(name):
    time.sleep(0.5)
    return DB.get(name, None)

def update_customer_status(name, status):
    if name in DB:
        DB[name]["status"] = status
        return {"success": True}
    return {"success": False}

3.3 构建 LangGraph 工作流

from langgraph.graph import StateGraph, END
from langgraph.prebuilt import ToolExecutor
from langchain.agents import tool
from openai import OpenAI
from mock_crm_api import get_customer_info, update_customer_status

# 工具定义
@tool
def get_customer(name: str) -> str:
    """获取客户信息"""
    data = get_customer_info(name)
    return str(data) if data else "未找到用户"

@tool
def change_status(name: str, status: str) -> str:
    """更新客户状态"""
    result = update_customer_status(name, status)
    return "更新成功" if result["success"] else "更新失败"

tools = [get_customer, change_status]
tool_executor = ToolExecutor(tools)

# LLM Agent 回调函数
def call_llm_agent(state):
    user_input = state["input"]
    tool_result = tool_executor.invoke({"input": user_input})
    return {"output": tool_result["output"]}

# 构建状态机
workflow = StateGraph()
workflow.add_node("run_agent", call_llm_agent)
workflow.set_entry_point("run_agent")
workflow.set_finish_point("run_agent")

app = workflow.compile()

3.4 测试示例

result = app.invoke({"input": "请把 Alice 的状态更新为 inactive"})
print(result["output"])

4. 与真实业务系统的对接方法

4.1 API 适配层的设计

class CRMAdapter:
    def __init__(self, base_url, token):
        self.base_url = base_url
        self.token = token

    def get_user(self, name):
        return requests.get(f"{self.base_url}/user?name={name}",
                            headers={"Authorization": f"Bearer {self.token}"})

    def update_user(self, name, status):
        return requests.post(f"{self.base_url}/user/update",
                             json={"name": name, "status": status},
                             headers={"Authorization": f"Bearer {self.token}"})

4.2 身份验证与权限控制

  • 支持 OAuth2 或 API Key 鉴权
  • Agent 权限角色隔离(只读、可写、审计员)
  • 请求日志全量记录(用于审计和追责)

5. 案例分享:智能工单处理 Agent 集成

5.1 背景场景

客户提交 IT 故障工单,Agent 自动分析问题、查询知识库、生成处理建议并填入 Jira 工单系统。

5.2 Agent 流程描述

  1. 识别问题关键词
  2. 调用知识库 API 查找类似问题
  3. 汇总建议
  4. 生成 Jira 工单内容
  5. 通过 API 提交

5.3 工作流调用示意

{
  "task": "创建工单",
  "summary": "用户无法连接 VPN",
  "priority": "High",
  "component": "Network",
  "recommendation": "请检查用户本地网络与认证配置"
}

6. 持续集成与部署建议

6.1 推荐的开发与部署方式

  • 使用 FastAPI 封装 Agent API
  • 结合 Docker + CI/CD(如 GitHub Actions) 实现自动部署
  • 与监控平台(如 Prometheus + Grafana)联动,监控任务流成功率与异常日志

6.2 安全与审计

  • 设置 Rate Limiting,防止滥用
  • 记录每次调用的 LLM Input/Output 以供追踪
  • 接入企业日志审计系统

7. 总结与展望

将 AI Agent 集成入业务系统,关键在于三方面:

  • 明确流程结构:拆分 Agent 任务,定义工具边界
  • 连接外部系统:通过 API 抽象与权限控制对接业务逻辑
  • 可控可追溯:具备日志记录、权限管理和调试能力

未来,结合多模态输入(语音、图像)、AutoGPT 自动任务分解和企业大模型私有化部署,AI Agent 的业务协作能力将更强、落地更深。

DeploySharp开源发布:让C#部署深度学习模型更加简单 - 椒颜皮皮虾 - 博客园

mikel阅读(227)

来源: DeploySharp开源发布:让C#部署深度学习模型更加简单 – 椒颜皮皮虾 – 博客园

1. 简介

DeploySharp 是一个专为 C# 开发者设计的跨平台模型部署框架,提供从模型加载、配置管理到推理执行的端到端解决方案。其核心架构采用模块化命名空间设计,显著降低了 C# 生态中深度学习模型的集成复杂度,

1. 架构设计与功能分层

  • 根命名空间 DeploySharp 作为统一入口,集成模型加载、推理执行等核心功能
  • 通过子命名空间(如 DeploySharp.Engine)实现模块化分层设计
  • 关键类采用泛型设计,支持图像处理/分类/检测等多任务标准数据交互

2. 多引擎支持与扩展能力

  • 原生支持 OpenVINO(通过OpenVinoSharp)、ONNX Runtime 推理引擎
  • 支持 YOLOv5-v12全系列模型、Anomaly及其他主流模型部署

3. 跨平台运行时支持

  • 兼容 .NET Framework 4.8 及 .NET 6/7/8/9
  • 深度集成 .NET 运行时生态(NuGet 包管理)

4. 高性能推理能力

  • 异步推理支持(System.Threading.Tasks
  • 支持单张/批量图片推理模式
  • 丰富的预处理(ImageSharp/OpenCvSharp)和后处理操作

5. 开发者支持体系

  • 中英双语代码注释与技术文档
  • log4net 分级日志系统(错误/警告/调试)
  • 提供可视化结果展示方案
  • 提供完善的示例代码库

该项目开源遵循 Apache License 2.0 协议,开发者可通过 QQ 群、微信公众号等渠道获取支持。未来版本计划扩展 TensorRT 支持并优化现有引擎的异构计算能力。

项目链接:

https://github.com/guojin-yan/DeploySharp.git

2. 模型支持列表

Model Name Model Type OpenVINO ONNX Runtime TensorRT
YOLOv5 Detection ing…
YOLOv5 Segmentation ing…
YOLOv6 Detection ing…
YOLOv7 Detection ing…
YOLOv8 Detection ing…
YOLOv8 Segmentation ing…
YOLOv8 Pose ing…
YOLOv8 Oriented Bounding Boxes ing…
YOLOv9 Detection ing…
YOLOv9 Segmentation ing…
YOLOv10 Detection ing…
YOLOv11 Detection ing…
YOLOv11 Segmentation ing…
YOLOv11 Pose ing…
YOLOv11 Oriented Bounding Boxes ing…
YOLOv12 Detection ing…
Anomalib Segmentation ing…

3. NuGet Package

3.1 Core Managed Libraries

Package Description Link
JYPPX.DeploySharp DeploySharp API core libraries https://www.nuget.org/packages/JYPPX.DeploySharp/

3.2 Native Runtime Libraries

Package Description Link
JYPPX.DeploySharp.ImageSharp An assembly that uses ImageSharp as an image processing tool. https://www.nuget.org/packages/JYPPX.DeploySharp.ImageSharp/
JYPPX.DeploySharp.OpenCvSharp An assembly that uses OpenCvSharp as an image processing tool. https://www.nuget.org/packages/JYPPX.DeploySharp.OpenCvSharp/

4. 如何安装

4.1 获取方式

大家可以直接在NuGet Gallery官网上进行查找使用:

image-20251002125042083

或者在Visual Studio的NuGet程序包中进行查找安装:

image-20251002125313962

4.2 NuGet Package组合使用方式

DeploySharp包含了OpenCvSharp、ImageSharp等图像处理方式,同时支持OpenVINO、ONNX Runtime模型部署引擎,因此用户可以根据自己需求自行组合,并安装对应的NuGet Package即可开箱使用。以下总结了常用的一些使用情况的NuGet Package安装场景:

  • OpenVINO推理+OpenCvSharp图像处理
JYPPX.DeploySharp
JYPPX.DeploySharp.OpenCvSharp

OpenVINO.runtime.win
OpenCvSharp4.runtime.win 
  • OpenVINO推理+ImageSharp图像处理
JYPPX.DeploySharp
JYPPX.DeploySharp.ImageSharp

OpenVINO.runtime.win
  • ONNX Runtime推理+OpenCvSharp图像处理
JYPPX.DeploySharp
JYPPX.DeploySharp.OpenCvSharp

OpenCvSharp4.runtime.win 
  • ONNX Runtime推理+ImageSharp图像处理
JYPPX.DeploySharp
JYPPX.DeploySharp.OpenCvSharp
  • ONNX Runtime(OpenVINO加速)推理+ImageSharp图像处理
JYPPX.DeploySharp
JYPPX.DeploySharp.ImageSharp

Intel.ML.OnnxRuntime.OpenVino
  • ONNX Runtime(DML加速)推理+ImageSharp图像处理
JYPPX.DeploySharp
JYPPX.DeploySharp.ImageSharp

Microsoft.ML.OnnxRuntime.DirectML
  • ONNX Runtime(CUDA加速)推理+ImageSharp图像处理
JYPPX.DeploySharp
JYPPX.DeploySharp.ImageSharp

Microsoft.ML.OnnxRuntime.DirectML

由于使用CUDA对ONNX Runtime加速受GPU设备型号以及软件版本影响,因此需要按照ONNX Runtime官方提供的版本对应关系进行下载使用,其中ONNX Runtime与CUDA、cuDNN对应关系请参考一下以下链接:

https://runtime.onnx.org.cn/docs/execution-providers/CUDA-ExecutionProvider.html#requirements

以上所列出的使用方式均可以通过NuGet Package一键安装,同样的,ONNX Runtime还支持更多加速方式,但需要用户自己进行代码构建,其构建流程与方式,参考官方教程即可,链接为:

https://runtime.onnx.org.cn/docs/execution-providers/

5. 开始使用

如果你不知道如何使用,通过下面代码简单了解使用方法。

5.1 ImageSharp图像处理

using DeploySharp.Data;
using DeploySharp.Engine;
using DeploySharp.Model;
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.PixelFormats;
using System;

namespace DeploySharp.ImageSharp.Demo
{
    public class YOLOv5DetDemo
    {
        public static void Run()
        {
            // 模型和测试图片可以前往QQ群(945057948)下载
            // 将下面的模型路径替换为你自己的模型路径
            string modelPath = @"E:\Model\Yolo\yolov5s.onnx";
            // 将下面的图片路径替换为你自己的图片路径
            string imagePath = @"E:\Data\image\bus.jpg";
            Yolov5DetConfig config = new Yolov5DetConfig(modelPath);
            //config.SetTargetInferenceBackend(InferenceBackend.OnnxRuntime);
            Yolov5DetModel model = new Yolov5DetModel(config);
            var img = Image.Load(imagePath);
            var result = model.Predict(img);
            model.ModelInferenceProfiler.PrintAllRecords();
            var resultImg = Visualize.DrawDetResult(result, img as Image<Rgb24>, new VisualizeOptions(1.0f));
            resultImg.Save(@$"./result_{ModelType.YOLOv5Det.ToString()}.jpg");
        }
    }
}

5.2 OpenCvSharp图像处理

using OpenCvSharp;
using System.Diagnostics;
using DeploySharp.Model;
using DeploySharp.Data;
using DeploySharp.Engine;
using DeploySharp;
using System.Net.Http.Headers;

namespace DeploySharp.OpenCvSharp.Demo
{
    public class YOLOv5DetDemo
    {
        public static void Run()
        {
            // 模型和测试图片可以前往QQ群(945057948)下载
            // 将下面的模型路径替换为你自己的模型路径
            string modelPath = @"E:\Model\Yolo\yolov5s.onnx";
            // 将下面的图片路径替换为你自己的图片路径
            string imagePath = @"E:\Data\image\bus.jpg";
            Yolov5DetConfig config = new Yolov5DetConfig(modelPath);
            config.SetTargetInferenceBackend(InferenceBackend.OnnxRuntime);
            Yolov5DetModel model = new Yolov5DetModel(config);
            Mat img = Cv2.ImRead(imagePath);
            var result = model.Predict(img);
            model.ModelInferenceProfiler.PrintAllRecords();
            var resultImg = Visualize.DrawDetResult(result, img, new VisualizeOptions(1.0f));
            Cv2.ImShow("image", resultImg);
            Cv2.WaitKey();
        }
    }
}

6.应用案例

获取更多应用案例请参考:

image-20251002124851175

后续会推出更多的应用案例使用介绍,敬请关注。

7. API文档

如果想了解更多信息,可以参阅:DeploySharp API Documented

image-20251002124938166

8. 贡献

如果您对DeploySharp在C#使用感兴趣,有兴趣对开源社区做出自己的贡献,欢迎加入我们,一起开发DeploySharp

如果你对该项目有一些想法或改进思路,欢迎联系我们,指导下我们的工作。

9. 许可证书

本项目的发布受Apache 2.0 license许可认证。

最后如果各位开发者在使用中有任何问题,欢迎大家与我联系。

image-20250224211044113

Win11共享打印0x0000bc4,三步解决共享难题 - AganTee - 博客园

mikel阅读(161)

来源: Win11共享打印0x0000bc4,三步解决共享难题 – AganTee – 博客园

在多人办公场景中,共享打印机能大幅提升效率,但Win11系统常因驱动、网络或权限问题出现错误,其中Win11共享打印0x0000bc4最为常见。这个错误通常提示找不到打印机,本文将给大家分享三种解决方法,帮你恢复打印机共享功能。

一、检查共享设置与网络配置

Win11共享打印0x0000bc4可先从基础设置错误,多数情况是网络或权限配置遗漏导致。

2.1 启用共享基础功能

  1. 设置网络配置文件:
    打开「设置→网络和Internet→高级网络设置」,将当前网络设为「专用」,公用网络会阻止打印机共享;

4c94a041425adf44bc1114bf541628cc.png

  1. 开启共享权限:
    进入「控制面板→网络和共享中心→更改高级共享设置」,勾选「启用网络发现」和「启用文件和打印机共享」,保存设置后重启电脑。

 

2.2 手动添加共享打印机

若系统自动搜索不到共享打印机,可通过IP地址直连:

  1. 在连接打印机的主机上,按 Win+R 输入 cmd,执行 ipconfig 获取IPv4地址;
  2. 在客户端电脑按 Win+R 输入 \\192.168.1.100,回车后找到共享打印机图标,右键「连接」

735c2cdf225729ed82801ee9df201651.png

 

二、修改组策略与服务配置

如果基础设置没问题,Win11共享打印0x0000bc4的原因可能是系统策略限制或服务异常,需要通过组策略编辑器调整。

3.1 配置RPC连接

  1. 按 Win+R 输入 gpedit.msc 打开组策略编辑器;
  2. 依次展开「计算机配置→管理模板→打印机」,双击「配置RPC连接设置」;
  3. 选择「已启用」,在「RPC连接设置」中勾选「命名管道上的RPC」,保存后重启

d9e1c3815f10e22dbf5f887082786bb7.png

3.2 修复Print Spooler服务

  1. 按 Win+R 输入 services.msc,找到「Print Spooler」服务;
  2. 若状态为「已停止」,右键选择「启动」,并将启动类型设为「自动」;
  3. 重启服务后,删除 C:\Windows\System32\spool\PRINTERS 路径下的临时文件,清除打印队列冲突。

5e4321ac80b05b2392461daf16baab89.png

家庭版Win11用户:组策略编辑器默认不可用,可通过「设置→Windows更新」安装累积更新,或手动导入注册表修复RPC配置。

三、驱动修复工具

这个打印机驱动修复管家是个驱动修复工具,可以执行「诊断-修复-驱动匹配」的流程服务。能够进行驱动匹配和故障排查。工具内置驱动库,覆盖惠普、佳能、联想等主流品牌,支持自动识别打印机型号并匹配稳定驱动。界面设计简洁,可通过一键式操作完成从扫描到修复的全过程。

针对Win11共享打印0x0000bc4错误,可以重点检测三类问题:

  • 驱动状态:扫描驱动是否过期、损坏或与Win11不兼容;
  • 共享配置:检查文件和打印机共享功能是否启用;
  • 服务状态:监测Print Spooler等关键服务是否正常运行

34e3964c26f24f01b2900e26c6547ab3.png

修复完成后需重启电脑,重新添加共享打印机。若问题仍存在,可尝试「手动安装模式」,从驱动库中选择历史版本驱动,部分老旧打印机可能需要降级驱动以适配Win11。

四、总结与注意事项

解决Win11共享打印0x0000bc4的关键在于分层排查,需注意:

  • 驱动匹配:老旧打印机优先选择Win10兼容驱动,避免最新版驱动与Win11冲突;
  • 隐私安全:在线工具处理敏感文件时,优先使用本地软件,防止隐私泄露
  • 权限管理:共享主机需为管理员账户,客户端添加时输入正确的主机用户名和密码。

硬盘突然坏掉,我花了半个月才把数据救回来…(附数据恢复工具) - 程序设计实验室 - 博客园

mikel阅读(138)

来源: 硬盘突然坏掉,我花了半个月才把数据救回来…(附数据恢复工具) – 程序设计实验室 – 博客园

硬盘突然坏掉,我花了半个月才把数据救回来…(附数据恢复工具)

前言#

上次说到我的硬盘坏了,真的是当头一棒。😅

因为平时很多工作资料都在这块盘里,数据恢复的过程持续了小半个月,堪称一场心理和体力的双重折磨。

好在最后,大部分文件都救回来了。虽然过程非常花时间,但至少没有全军覆没。🤣

这次经历也算是给我自己上了一课,顺便整理成笔记,分享一下过程和心得。

👉 如果你正好也需要相关工具,我已经整理好了本次用到的软件清单,可以在公众号 「曦远Life」 后台回复 「数据恢复」 获取。

工具的两种思路#

在接触数据恢复工具之前,我总结了一下它们大致有两种工作模式:

  1. 扫描 MFT(Master File Table)
    • 优点:能保留目录结构、文件名,恢复出来的文件比较“原汁原味”。
    • 缺点:如果 MFT 本身损坏严重,可能丢失部分文件,或者文件内容不完整。
  2. 扫描数据块(Raw Scan)
    • 优点:能尽可能多地找回文件内容。
    • 缺点:失去目录结构和文件名,恢复出来一大堆 file0001.jpgfile0002.doc,后期整理会非常痛苦。

大部分恢复软件都是这两种思路的结合,实际使用时需要灵活选择。

👉 我这次用到的工具(DMDE、OSFMount、FinalData 等)都整理在一起了,获取方式:在公众号 「曦远Life」 后台回复 「数据恢复」

关于 NTFS#

NTFS(New Technology File System)是 Windows 系统常用的文件系统,它的优点是:

  • 支持大文件和大容量分区
  • 有权限控制、安全日志
  • 目录和文件的元信息都存储在 MFT(Master File Table) 里

核心要点:MFT 是 NTFS 的总目录表。

如果 MFT 受损,文件系统就像失忆了一样,文件还在,但找不到入口。

MFT介绍#

MFT 记录了每一个文件的:

  • 文件名
  • 路径
  • 大小
  • 时间戳(创建/修改/访问时间)
  • 文件数据所在的位置

所以,当我们做「基于 MFT 的扫描」时,本质上就是在想办法读取这张总目录表。

一旦这张表坏了,就只能退而求其次,去“数据块级别”扫描了。

我这次的思路#

这次我走的是 「先保护现场,再尝试修复」 的思路。

  1. 对分区做镜像
    • 用 DMDE 给损坏的分区做了完整镜像(img 格式)。
    • 原因:避免在原盘上直接操作,防止二次损坏。
  2. 挂载镜像
    • 使用 OSFMount 将镜像挂载为虚拟磁盘分区,方便后续操作。
  3. 文件系统检查
    • 执行 chkdsk /f /r X:
    • /f 修复错误,/r 尝试恢复坏扇区。
    • 过程中系统自动生成了一些 found.000 文件夹,里面是修复时捡回来的“孤立文件”。
  4. 扫描与恢复
    • 使用 FinalData 对挂载盘进行深度扫描。
    • 部分文件恢复成功,保留了文件名和目录结构;部分则散落在 found.000 里,需要人工整理。

成果#

恢复结果:大部分文件都找回来了!

遗憾点:有一部分目录结构和文件名乱了,需要大量时间手动分类、重命名。

总结感受:能把关键文件救回来就算赢了,剩下就是慢工出细活。

小结#

这次经历让我深刻认识到

  • 一定要重视 数据安全
  • 重要数据要 多地备份:本地 + NAS + 多种不同云存储。
  • 不要依赖单一云存储,服务商也可能出问题。

接下来,我也打算升级我的 NAS,把数据安全短板补齐,做到真正的有备无患。

数据无价,别等丢了才后悔!

Vue 配置中解决 CORS 跨域问题【亲测,跨坑!】 - 淡定=淡定 - 博客园

mikel阅读(134)

来源: Vue 配置中解决 CORS 跨域问题【亲测,跨坑!】 – 淡定=淡定 – 博客园

看了网上很多资料,很多不全,只是针对部分场景。请看到最后:

一、CORS 跨域问题解决
1.1、前言

如果你后端使用的是微服务项目,通过配置网关可以很好的解决跨域问题;

如果你使用 SpringBoot + Vue 来写项目,可以在 Controller 上加 @CrossOrigin 来解决跨域,但是一旦你在后端配置了拦截器(比如通过 HandlerInterceptor 配置登录拦截器),那么此时再解决跨域这个问题就很困难了.

Ps:在网上搜索 “Spring Boot 拦截器跨域问题解决” 会有大把大把的办法,但亲测没一个能用…

实际上,可以从 Vue 的角度来解决这个问题,只需要在 Vue 中进行如下配置即可.

1.2、解决办法
a)修改统一配置的 axios 实例
在 Vue 脚手架中,按照标准开发,一般会创建一个 utils 文件夹,里面创建一个 request.js 文件来统一封装 axios.

这里我们修改 axios 实例中的 baseURL 如下:

//构建统一 axios 实例
const instance = axios.create({
baseURL: “/api”,
timeout: 5000
});
Ps:不要管为什么,你先配置!修改的这些配置将来都不会影响你的原有的操作!

b)修改 config 文件夹下的 index.js 文件
在 Vue2 中,config 目录下有一个 index.js 文件.

添加如下配置

‘/api’: {
target: ‘http://localhost:8010’, //目标 url
changeOrigin: true, //是否跨域
pathRewrite: {
‘^/api’: ” //其中 /api 等价于前面的目标地址
}
}
c)完成
配置完了以后,一定要重启前端项目,重新 npm run dev !!

通过以上配置,后端也就无需担忧跨域问题了~
一般情况下,到这就OK了!But,不稳定,过一会又失效了@_@-,总结一下解决方案:

step 1:

修改 config 文件夹下的 index.js 文件
在 Vue2 中,config 目录下有一个 index.js 文件.

 

添加如下红色框里的配置 :

step 2:

修改 config 文件夹下的 dev.env.js 文件:
增加红框里的内容

Step 3:

在实际引入 axios使用的 js 文件里,增加一行:

如下调用:

axios.post(XXXX),then(……,这里的XXX不需要写要访问的服务端http地址了,也不需要写”/api”即可

 step 4:

重新启动 :

npm run dev

.NET 生态洞察:NuGet 下载量 Top 100 包深度解析

mikel阅读(223)

来源: .NET 生态洞察:NuGet 下载量 Top 100 包深度解析

在 .NET 开发中,NuGet 已经成为开发者管理依赖的标配工具。无论是后端 API、微服务,还是桌面应用,很多功能都不必自己重写——直接引用成熟的 NuGet 包即可。

本文整理了 下载量排名前 100 的 NuGet 社区包,并结合实际应用场景分析,让你快速了解哪些库最受欢迎,以及它们的典型用途。

数据来源:NuGet 包下载排行


🔹 JSON & 序列化

  • • Newtonsoft.Json:最流行的 JSON 序列化/反序列化库(虽然 .NET Core 内置 System.Text.Json,但很多项目仍使用它)。
  • • Newtonsoft.Json.Bson:支持 BSON(二进制 JSON)格式的序列化。

🔹 日志 Logging

  • • Serilog:结构化日志库,支持 JSON 输出和多种 sink。
  • • Serilog.Sinks.Console / Serilog.Sinks.File / Serilog.Sinks.Debug:输出到控制台、文件或 Visual Studio 调试窗口。
  • • Serilog.Extensions.Logging / Serilog.Extensions.Hosting:与 .NET Host 和 Microsoft.Extensions.Logging 集成。
  • • Serilog.Settings.Configuration:支持 appsettings.json 配置。
  • • Serilog.Formatting.Compact:压缩 JSON 日志格式。
  • • Serilog.AspNetCoreASP.NET Core 集成。
  • • Serilog.Sinks.PeriodicBatching:支持批量写入日志。

🔹 云服务 SDK

  • • AWSSDK.Core:AWS SDK 核心库。
  • • AWSSDK.S3:操作 Amazon S3。
  • • AWSSDK.SecurityToken:STS 认证(临时凭证)。
  • • AWSSDK.SQS:Amazon 队列服务。
  • • AWSSDK.Lambda:调用 AWS Lambda。

🔹 弹性与容错

  • • Polly:弹性策略库(重试、断路器、超时)。
  • • Polly.Core:核心功能。
  • • Polly.Extensions.Http:专为 HttpClient 提供策略扩展。

🔹 gRPC 生态

  • • Google.Protobuf:Protocol Buffers 序列化。
  • • Grpc.Core.Api / Grpc.Net.Client / Grpc.Net.ClientFactory:核心 API 与客户端。
  • • Grpc.Net.Common:共享组件。
  • • Grpc.Tools:编译 .proto 文件。
  • • Grpc.AspNetCore.Server:在 ASP.NET Core 上搭建 gRPC 服务。

🔹 API 文档 & Swagger

  • • Swashbuckle.AspNetCore.SwaggerGen:生成 Swagger 文档。
  • • Swashbuckle.AspNetCore.Swagger / Swashbuckle.AspNetCore:核心包与集合包。
  • • Swashbuckle.AspNetCore.SwaggerUI:可视化 UI。
  • • Swashbuckle.AspNetCore.Annotations:Swagger 注解支持。

🔹 测试相关

  • • xUnit 系列xunitxunit.corexunit.runner.visualstudioxunit.extensibility.corexunit.extensibility.executionxunit.assertxunit.analyzersxunit.abstractions
  • • Moq:Mock 框架。
  • • FluentAssertions:断言库,语法自然。
  • • NUnit / NUnit3TestAdapter:另一种测试框架及 VS 集成。
  • • Coverlet.Collector:代码覆盖率统计。

🔹 数据库 & ORM

  • • StackExchange.Redis:Redis 客户端。
  • • NpgSQL / NpgSQL.EntityFrameworkCore.PostgreSQL:PostgreSQL 驱动及 EF Core Provider。
  • • Dapper:轻量 ORM。
  • • RabbitMQ.Client:消息队列客户端。
  • • MongoDB.Driver / MongoDB.Bson:MongoDB 驱动及 BSON 类型支持。
  • • SQLitePCLRaw.Core:SQLite 驱动。
  • • DocumentFormat.OpenXml:操作 Word/Excel 等 Office 文档。

🔹 OpenTelemetry(可观测性)

  • • OpenTelemetry.Api / OpenTelemetry.Api.ProviderBuilderExtensions:核心 API 与扩展。
  • • OpenTelemetry / OpenTelemetry.Extensions.Hosting:完整 SDK 与 IHost 集成。
  • • OpenTelemetry.Instrumentation.AspNetCore / OpenTelemetry.Instrumentation.Http:ASP.NET Core 与 HTTP 监控。
  • • OpenTelemetry.Exporter.OpenTelemetryProtocol:OTLP 协议导出器。

🔹 实用工具库

  • • Humanizer.Core:字符串/日期/数字人性化显示(如 “2 days ago”)。
  • • FluentValidation / FluentValidation.DependencyInjectionExtensions:验证框架及 DI 集成。
  • • AutoMapper:对象映射工具。
  • • MediatR / MediatR.Contracts:CQRS 与中介者模式。
  • • Autofac:IoC 容器。
  • • YamlDotNet / CsvHelper:YAML 与 CSV 解析。
  • • DnsClient:DNS 查询。
  • • System.Linq.Async:异步 LINQ 扩展。
  • • RestSharp:HTTP 客户端。
  • • System.Reactive:响应式扩展。
  • • JetBrains.Annotations:代码注解。
  • • Hangfire.Core:后台任务调度。
  • • NJsonSchema:JSON Schema 支持。
  • • SixLabors.ImageSharp / SixLabors.Fonts:图像处理与字体渲染。
  • • SharpCompress / SharpZipLib / ZstdSharp.Port:压缩与解压缩库。
  • • BouncyCastle.Cryptography / Portable.BouncyCastle:加密库。
  • • SSH.NET:SSH 客户端。
  • • log4net:老牌日志库。
  • • HtmlAgilityPack:HTML 解析与操作。

🔹 其他精选库

  • • Pipelines.Sockets.Unofficial:高性能 Socket 库。
  • • Mono.TextTemplating:T4 模板。
  • • Google.Apis 系列:OAuth2 与 API 客户端。
  • • EO.WebBrowser:基于 Chromium 的浏览器控件(商用)。
  • • Fare:正则表达式生成字符串。
  • • Namotion.Reflection:增强反射功能。
  • • SFA.Core.ServiceModel:WCF 相关库。

🔹 总结

这些 NuGet 包覆盖了 序列化、日志、云 SDK、容错、gRPC、API 文档、测试、数据库、可观测性及实用工具 等各类常用场景,是 .NET 开发者最常依赖的生态组成部分。

合理利用这些成熟的库,可以显著提升开发效率和项目稳定性,让你专注于业务逻辑,而不是重复造轮子。

 

··············  END  ··············

GDI+中发生一般性错误_51CTO博客_gdi+发生一般性错误

mikel阅读(160)

来源: GDI+中发生一般性错误_51CTO博客_gdi+发生一般性错误

 

 在开发.NET应用中,使用 System.Drawing.Image.Save 方法而导致“GDI+ 中发生一般性错误”的发生,通常有以下三种原因:

1. 相应的帐户没有写权限。

解决方法:赋予 NETWORK SERVICE 帐户以写权限。

2. 指定的物理路径不存在。

解决方法:

在调用 Save 方法之前,先判断目录是否存在,若不存在,则创建。

if (!Directory.Exists(dirpath))

Directory.CreateDirectory(dirpath);

3. 保存的文件已存在并因某种原因被锁定。

解决方法:

重启IIS,解除锁定。并在代码中使用 using 语句,确保释放 Image 对象所使用的所有资源。

我遇到的情况:

在先用openFileDialog打开图片文件,然后用saveFileDialog保存文件时就出现了 “GDI+中发生一般性错误”,我当时就想到是打开的文件还没有释放出来,于是用openFileDialog1.Dispose()来释放,可是没有成功。同样从一个MemorySream 实例打开一个Image后,立即关闭了这个流,结果在Image.Save时也会发生这种错误。我“摆渡”了很久都是遇到和我一样问题的人,CSDN上面的同志也没有给出一个实用的答案。最后终于还是在微软的网站上找到了答案:(以下是官方解决办法)

症状

Bitmap 对象或一个 图像 对象从一个文件, 构造时该文件仍保留锁定对于对象的生存期。 因此, 无法更改图像并将其保存回它产生相同的文件。

 

替代方法

•    创建非索引映像。

•    创建索引映像。

这两种情况下, 原始 位图 上调用 Bitmap.Dispose() 方法删除该文件上锁或删除要求, 流或内存保持活动。

 

创建非索引图像

即使原始映像被索引格式中该方法要求新图像位于每像素 (超过 8 位 -) -, 非索引像素格式。 此变通方法使用 Graphics.DrawImage() 方法来将映像复制到新 位图 对象:

1.    构造从流、 从内存, 或从文件原始 位图 。

2.    创建新 位图 的相同大小, 带有是超过 8 位 – – 像素 (BPP) 每像素格式。

3.    使用 Graphics.FromImage() 方法以获取有关二 位图 Graphics 对象。

4.    用于 Graphics.DrawImage() 绘制首 位图 到二 位图 。

5.    用于 Graphics.Dispose() 处置是 图形 。

6.    用于 Bitmap.Dispose() 是首 位图 处置。

 

创建索引映像

此解决办法在索引格式创建一个 Bitmap 对象:

1.    构造从流、 从内存, 或从文件原始 位图 。

2.    创建新 位图 具有相同的大小和像素格式作为首 位图 。

3.    使用 Bitmap.LockBits() 方法来锁定整个图像对于两 Bitmap 对象以其本机像素格式。

4.    使用 Marshal.Copy 函数或其他内存复制函数来从首 位图 复制到二 位图 图像位。

5.    使用 Bitmap.UnlockBits() 方法可以解锁两 Bitmap 对象。

6.    用于 Bitmap.Dispose() 是首 位图 处置。

由于外国人的思维和我们不一样,我重新用实例解释一下,我这里使用的是创建非索引图像。

private void ToolStripMenuItem_Click(object sender, EventArgs e)

{

if (openFileDialog1.ShowDialog() == DialogResult.OK)

{

//创建一个bitmap类型的bmp变量来读取文件。

Bitmap bmp = new Bitmap(openFileDialog1 .FileName );

//新建第二个bitmap类型的bmp2变量,我这里是根据我的程序需要设置的。

Bitmap bmp2 = new Bitmap(1024, 768, PixelFormat.Format16bppRgb555);

//将第一个bmp拷贝到bmp2中

Graphics draw = Graphics.FromImage(bmp2);

draw.DrawImage(bmp,0,0);

pictureBox1.Image = (Image)bmp2 ;//读取bmp2到picturebox

FILE = openFileDialog1.FileName;

openFileDialog1.Dispose();

draw.Dispose();

bmp.Dispose();//释放bmp文件资源

}

}

通过以上的读取文件,在保存的时候就不会出现错误了。​

*********************************************************************************************

我写的一个生成缩略图程序, 生成gif,bmp,png 文件都可以, 就是不能生成jpg 文件, 何解??

 

//按比例缩小上传的图片

System.Drawing.Image img;

img = System.Drawing.Image.FromFile(all);

float width = img.Width;

float height = img.Height;

float newwidth = 0;

float newheight = 0;

if (width > height)

{

newwidth = 135;

newheight = height / width * newwidth;

}

else

{

newheight = 135;

newwidth = width / height * newheight;

}

System.Drawing.Image outimg = img.GetThumbnailImage((int)newwidth,(int)newheight,null,IntPtr.Zero);

string newfiles = path + newfilename + “.jpg”;

outimg.Save(newfiles);

 

outimg.Dispose();

img.Dispose();

——————————————————————————————-

绘图坐标超过了画布大小。建议先把画布设大写,看看效果再确定实际大小

跟画布大小应该是无关的,

如果上传jpg文件, 用以下方法保存是会报GDI 中发生一般性错误,

outimg.Save(newfiles,System.Drawing.Imaging.ImageFormat.Jpeg);

如果改成outimg.Save(newfiles,System.Drawing.Imaging.ImageFormat.Gif) 就能顺利生成,

但改成outimg.Save(newfiles,System.Drawing.Imaging.ImageFormat.Gif) 后, 上传gif文件生成缩略图就报GDI 中发生一般性错误, 现在连问题的根源都不清楚, 唉…

监测一下你的newwidth和newheight是不是未预期的数据

检查是否是权限问题

1. 确认没有同名jpg文件存在

2. 确认aspnet或者network service有覆盖文件等相应权限

vivianfdlpw() 一言惊醒梦中人啊!! 果然是重名了!!!

**************************************************************************************

private void DrawImg(int width)

{

//图片的地址

string path=String.Format(@”D:\共享文件夹\EnterpriseLicences\1\123.jpg”);

//保存水印图片的文件夹

string catchPath=Server.MapPath(@”..\temp\cache\”);

Image newImage = Image.FromFile(path);    //取出图片

 

if(width==0)

{

width=newImage.Width;

}

int hight=newImage.Height*width/newImage.Width;

System.Drawing.Bitmap bitmap=new Bitmap(width,hight);

System.Drawing.Graphics g = System.Drawing.Graphics.FromImage(bitmap);

g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.High;

g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;

g.Clear(System.Drawing.Color.Transparent);

g.DrawImage(newImage,0,0,width,hight);

 

//水印图片

Bitmap copyImage = (Bitmap)Bitmap.FromFile(Server.MapPath(@”..\Images\EnterpriseLisence\Logos.gif”));

copyImage.MakeTransparent(Color.White);

 

float copyW=width*4/10; float copyH=copyImage.Height*copyW/copyImage.Width;

g.DrawImage(copyImage,width-copyW-10,hight-copyH-5,copyW,copyH);

try

{

bitmap.Save(catchPath+”123.jpg”);  //这个文件夹有权限

 

}

catch (Exception e)

{

throw e;

}

bitmap.Dispose();

newImage.Dispose();

g.Dispose();

}

 

Message “GDI+ 中发生一般性错误。”

Source “System.Drawing”

StackTrace

at System.Drawing.Image.Save(String filename, ImageCodecInfo encoder, EncoderParameters encoderParams)

at System.Drawing.Image.Save(String filename, ImageFormat format)

at System.Drawing.Image.Save(String filename)

at KSI.KSI_Web.EnterpriseLisence.Drawing.DrawImg(Int32 width) in D:\\worksharp\\ksi\\ksi_web\\enterpriselisence\\drawimg.aspx.cs:line 98″

—————————————————————————————————-

1.尽量使用 引用图片,避免直接加载物理图片

eg://图片的地址

string path=String.Format(@”D:\共享文件夹\EnterpriseLicences\1\123.jpg”);

Image newImage = Image.FromFile(path);    //取出图片

g.DrawImage(newImage,0,0,width,hight);

这种方式不是很可取,而且容易造成 GDI+错误

2.VS03、05对GIF支持不是很完好!当你的程序执行较大操作的时候,且你会更新你的图片的时候,GDI+错误 偶尔、或者经常出现。

我本人不知道解决方法。只能使用别的方式,加载GIF图片 或者不加载GIF图片

注(您的代码比较严谨,不存在实质性的漏洞,加载释放都有,虽然位置不佳,但是依然可以达到 释放的目的)请你 更换GIF 图片 再 重新生成项目

 

C# 自定义项写入配置文件appsettings.json中(如url和token)_c# appsettings.json-CSDN博客

mikel阅读(100)

来源: C# 自定义项写入配置文件appsettings.json中(如url和token)_c# appsettings.json-CSDN博客

一、打开项目的 `appsettings.json` 文件,通常位于项目的根目录。
二、在 `appsettings.json` 文件中添加相应的配置项。可以使用类似下面的格式添加配置项:
{
“ApiConfiguration”: {
“BaseApiUrl”: “your_url_here”,
“Token”: “your_token_here”
},
// 其他配置项…
}
AI写代码
JavaScript
运行
三、在 `Startup.cs` 文件中的 `ConfigureServices` 方法中,注册配置项,并使其可供应用程序的其他部分访问。确保引用 `Microsoft.Extensions.Configuration` 和 `Microsoft.Extensions.Options` 命名空间。
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;

namespace YourNamespace
{
public class Startup
{
//…

public void ConfigureServices(IServiceCollection services)
{
//…

services.Configure<ApiConfiguration>
Configuration.GetSection(“ApiConfiguration”));
//…
}
}
}
AI写代码
cs
运行

四、创建一个包含配置项属性的类 `ApiConfiguration`,用于将配置项映射到实际的类属性。
public class ApiConfiguration
{
public string BaseApiUrl { get; set; }
public string Token { get; set; }
}
AI写代码
cs
运行
五、在所需使用配置文件的类中,如 `ApiDataProcessor` 类使用 `IOptions<ApiConfiguration>` 注入配置项,并将其作为构造函数参数。
public class ApiDataProcessor : BackgroundService
{
private readonly ApiConfiguration _apiConfiguration;

public ApiDataProcessor(IOptions<ApiConfiguration> apiConfigurationOptions)
{
_apiConfiguration = apiConfigurationOptions.Value;
}

//…
}
AI写代码
cs
运行

现在,就可以在 ApiDataProcessor 类(可替换为实际类)中使用 _apiConfiguration.BaseApiUrl 和 _apiConfiguration.Token 来访问配置项的值,而不是硬编码在代码中。这样的好处是,可以在不更改代码的情况下更改配置项的值。
————————————————

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

原文链接:https://blog.csdn.net/weixin_42060801/article/details/132576647

如何使用 appsettings.json 配置文件?

mikel阅读(114)

来源: 如何使用 appsettings.json 配置文件?

appsettings.json 是一个相较于 App.config 更加灵活的配置文件,是 .NET Core 以来新增的一种配置方式,提供了更多的灵活性

在 .NET Core 项目中,我们可以使用 appsettings.json 配置文件来存储应用程序的配置信息。在这篇文章中,我们将学习如何使用 appsettings.json 配置文件。

appsettings.json 是一个相较于 App.config 更加灵活的配置文件,是 .NET Core 以来新增的一种配置方式,提供了更多的灵活性。

快速入门 

我们可以在项目中创建一个 appsettings.json 文件,然并将其生成操作设置为「较新时复制」或「总是复制」,这样在项目构建时,appsettings.json 文件会被复制到输出目录中。

然后我们可以在其中添加如下内容:

1
2
3
4
5
6
7
8
{
    "AppSettings": {		
        "LogLevel":"Warning",
        "ConnectionStrings": {
            "Default": "this is the connection string"
        }	
    }
}

这样我们就可以尝试读取了。我们使用 NuGet 包管理器安装 Microsoft.Extensions.Configuration.Json 包。它会隐式安装 Microsoft.Extensions.Configuration 等依赖项,这些我们不需要显式安装。

然后我们可以在代码中读取配置文件:

1
2
3
4
5
using Microsoft.Extensions.Configuration;

var configuration = new ConfigurationBuilder()
    .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
    .Build();

这样我们就可以获取上面的配置信息了:

1
2
var logLevel = configuration["AppSettings:LogLevel"];
var connectionString = configuration["AppSettings:ConnectionStrings:Default"];

这里的形如 AppSettings.LogLevel 是一种特殊的写法,简单来说就是借助 : 来表示 JSON 中的层级关系。

如果要获取的配置项是一个数字,我们除了可以先通过上述方式获取到字符串,进而使用 int.Parse 或 Convert.ToInt32 等方法进行转换,还可以使用 GetValue 方法:

1
2
3
4
// 传统方法
var logLevel = int.Parse(configuration["AppSettings:LogLevel"]);
// 使用 GetValue 方法
var logLevel = configuration.GetValue<int>("AppSettings:LogLevel");

对于连接字符串,我们还可以使用 GetConnectionString 方法:

1
var connectionString = configuration.GetConnectionString("Default");

可选与自动重载 

在上面的代码中,我们可以看到 AddJsonFile 方法有两个参数,optional 和 reloadOnChange

  • optional 参数表示是否允许配置文件不存在,如果设置为 false,则会抛出异常,否则会忽略。
  • reloadOnChange 参数表示是否在配置文件发生变化时重新加载配置文件。如果设置为 true,则会在配置文件发生变化时重新加载配置文件。

比如我们可以用下面的例子测试自动重载的效果:

1
2
3
4
5
6
7
8
9
var configuration = new ConfigurationBuilder()
    .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
    .Build();

while (true)
{
    Console.WriteLine(configuration["AppSettings:LogLevel"]);
    Thread.Sleep(1000);
}

在运行程序后,我们可以修改 appsettings.json 文件中的 LogLevel 配置,然后我们会发现程序会自动重新加载配置文件。注意这里我们修改的是输出目录(也就是 .exe 文件所在位置)下的 appsettings.json 文件,而不是项目中的 appsettings.json 文件。

添加多个 JSON 文件 

如果只能添加一个 JSON 文件,那么配置文件的灵活性就大大降低了。事实上,我们可以通过多次调用 AddJsonFile 方法来添加多个 JSON 文件。一个典型的情形是添加一个 appsettings.Development.json 文件,用于存储开发环境的配置信息。

1
2
3
4
var configuration = new ConfigurationBuilder()
    .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
    .AddJsonFile("appsettings.Development.json", optional: true, reloadOnChange: true)
    .Build();

这样我们就可以在 appsettings.Development.json 文件中存储开发环境的配置信息,而在 appsettings.json 文件中存储通用的配置信息。

不仅如此,这二者之间存在优先级,或者说覆盖关系。具体来说:

  • 如果 appsettings.json 和 appsettings.Development.json 中都有相同的配置项,那么 appsettings.Development.json 中的配置项会覆盖 appsettings.json 中的配置项
  • 如果 appsettings.Development.json 中没有某个配置项,而 appsettings.json 中有,那么会使用 appsettings.json 中的配置项
  • 如果 appsettings.Development.json 中有某个配置项,而 appsettings.json 中没有,那么会使用 appsettings.Development.json 中的配置项

使用强类型配置 

在上面的例子中,我们使用 configuration["AppSettings:LogLevel"] 来获取配置信息,这种方式是一种弱类型的方式。我们也可以使用强类型的方式来获取配置信息。

我们修改一下 appsettings.json 文件中的配置项:

1
2
3
4
5
6
7
{
    "UserSettings": {
        "Name": "Alice",
        "Age": 18,
        "IsActive": true
    }
}

然后我们定义一个强类型的配置类:

1
2
3
4
5
6
public class UserSettings
{
    public string Name { get; set; }
    public int Age { get; set; }
    public bool IsActive { get; set; }
}

在获取配置前,我们还需要安装一个 NuGet 包:Microsoft.Extensions.Options.ConfigurationExtensions。然后我们就可以这样获取配置信息:

1
var userSettings = configuration.GetSection("UserSettings").Get<UserSettings>();

这样我们就可以获取到 UserSettings 对象了,然后就可以使用 userSettings.NameuserSettings.AgeuserSettings.IsActive 来获取配置信息了。

但是需要注意,因为这里的 userSettings 实例已经初始化,所以前面提到的自动重载功能不再生效。如果需要自动重载,我们需要重新获取 userSettings 对象。

添加环境变量和命令行参数 

在 .NET Core 中,我们还可以通过环境变量和命令行参数来覆盖配置文件中的配置信息。我们需要再安装两个 NuGet 包:

  • Microsoft.Extensions.Configuration.EnvironmentVariables
  • Microsoft.Extensions.Configuration.CommandLine

然后我们可以这样添加环境变量和命令行参数:

1
2
3
4
5
var configuration = new ConfigurationBuilder()
    .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
    .AddEnvironmentVariables()
    .AddCommandLine(args)
    .Build();

这样我们就可以通过环境变量和命令行参数来覆盖配置文件中的配置信息了。

比如我们可以创建一个 .bat 批处理文件:

1
2
3
4
5
@echo off
set UserSettings__Name=Bob
set UserSettings__Age=20

.\Demo.exe

或者还可以使用 PowerShell:

1
2
3
4
$env:UserSettings__Name = "Bob"
$env:UserSettings__Age = 20

.\Demo.exe

总结 

相信通过这篇文章,大家已经认识到了 appsettings.json 配置文件的强大之处。它不仅提供了一种灵活的配置方式,还提供了多种配置方式的组合,使得我们可以更加灵活地配置应用程序。

但是它也有一些局限性。最重要的一条就是它的配置项是“只读”的,也就是不能像 App.config 那样在运行时方便地修改配置项。毕竟,一个项目中可能存在多个配置项,而不是只有一个 appsettings.json 文件。此时如果修改了,该保存到哪个文件呢?

当然,如果只有一个配置文件,那么 appsettings.json 是一个不错的选择。比如我们可以使用 Newtonsoft.Json 来轻松地写入 JSON 文件,这样就可以实现配置项的修改了。

最后,其实通常情况下,我们并不会使用上面的方式读取配置项,而是会更进一步,使用 Host 作为整个程序的入口,并读取配置、注入服务等。在之后的文章中,我们会学习如何使用 Host 来构建一个 .NET 应用程序。

windows server使用 LetsEncrypt-Win-Simple来安装和使用用Let's Encrypt免费SSL证书 - 米高佐敦 - 博客园

mikel阅读(163)

来源: windows server使用 LetsEncrypt-Win-Simple来安装和使用用Let’s Encrypt免费SSL证书 – 米高佐敦 – 博客园

一、网站部署

LetsEncrypt-Win-Simple可以自动发现已经部署的网站供我们选择要生成证书的网站,而且还需要进行验证。所以在生成证书之前,确保网站已经部署好并可以正常访问。

二、生成证书

软件下载地址如下:

https://github.com/Lone-Coder/letsencrypt-win-simple/releases

直接下载zip压缩包就好,下载完之后解压运行里面的letsencrypt.exe打开控制台窗口,第一次运行会提示你输入一个邮箱以供后续使用。

Let’s Encrypt (Simple Windows ACME Client)

Renewal Period: 60

Certificate Store: WebHosting

ACME Server: https://acme-v01.api.letsencrypt.org/

Config Folder: C:\Users\ling\AppData\Roaming\letsencrypt-win-simple\httpsacme-v01.api.letsencrypt.org

Certificate Folder: C:\Users\ling\AppData\Roaming\letsencrypt-win-simple\httpsacme-v01.api.letsencrypt.org

Getting AcmeServerDirectory

Enter an email address (not public, used for renewal fail notices):

输入一个可用邮箱回车即开始注册,并问你是否同意协议

Calling Register

Do you agree to https://letsencrypt.org/documents/LE-SA-v1.1.1-August-1-2016.pdf? (Y/N)

输入Y回车,邮箱注册完之后,程序会自动获取当前服务器部署的所有网站,如下:

Scanning IIS Site Bindings for Hosts

1: IIS xxling.com (D:\www\xxx)

2: IIS www.xxling.com (D:\www\xxx)

W: Generate a certificate via WebDav and install it manually.

F: Generate a certificate via FTP/ FTPS and install it manually.

M: Generate a certificate manually.

A: Get certificates for all hosts

Q: Quit

Which host do you want to get a certificate for:

输入1或者2就会为相应的域名生成证书,M为手动生成一个证书,A则为所有域名生成证书。这里我们选择A然后回车继续,生成完证书程序还会自动为相应网站配置IIS的SSL。选择了A之后生成的证书在C:\Users\Administrator\AppData\Roaming\letsencrypt-win-simple\httpsacme-v01.api.letsencrypt.org下,具体看后面输出的提示会有位置信息。

由于Let’s Encrypt免费SSL证书只有90天的有效期,过期需要更新,该程序会生成一个计划任务,每天上午9点钟运行检查过期的证书并更新。所以生成完成证书会提示你是不是需要指定用户运行刷新证书的计划任务(会显示下次过期的时间),选择Y,输入相应的用户和密码即可。

注意:生成的计划任务的执行程序默认是生成证书时的letsencrypt.exe的路径,请到管理工具-计划任务查看相应任务属性,确认action的letsencrypt.exe路径对不对,如果移动到其它地方了也需要进行相应修改,否则会执行失败!

三、IIS配置

打开IIS,查看域名绑定,就会看到多了443的端口绑定,证书也以配置好。重启一下iis,通过https访问就可以了。

如果是手动配置,在IIS7配置https绑定是host name那栏灰掉,不可输入,此时如果需要指定相应的域名,可以打开以下位置文件:
C:\Windows\System32\inetsrv\config\applicationHost.config

搜索相应域名找到该网站的配置节点,你会发现不输入域名是的https配置如下

<binding protocol=”https” bindingInformation=”*:443:” />

将其改为

<binding protocol=”https” bindingInformation=”:443:www.xxling.com” />

即可,域名改为自己实际的域名。

其次,要注意的是,IIS只能绑定一个SSL证书,这生成证书的新版软件好像没有多域名证书生成的选项了,所以只能把其他域名重定向到有证书的域名上。

 

四、强制HTTPS访问

首先IIS配置选中要求SSL选项

IIS6中,站点属性-》目录安全性-》编辑中把“要求安全通道(SSL)”勾选上即可。

IIS7、8中,SSL设置-》把“要求SSL”勾选即可

此时通过http访问的话会报403错误,我们找到403的html页面,加入以下JavaScript脚本进行跳转:

<script type=”text/JavaScript”>

var url = window.location.href;

if (url.indexOf(“https”) < 0) {

url = url.replace(“http:”, “https:”);

window.location.replace(url);

}

</script>

403文件所在路径如下:

IIS6.0 :C:\WINDOWS\Help\iisHelp\common\403-4.htm

IIS7.0以上 :C:\inetpub\custerr\zh-CN\403.htm

如果使用的英文版系统zh-CN可能为en-US或者其它。

此时我们通过http访问我们的网站时就会自动跳转到https了。