asp.net core

server/2025/2/26 12:26:53/

初始化

WebApplication.CreateBuilder

var builder = WebApplication.CreateBuilder(args);

用于创建一个 Web 应用程序的构建器 (WebApplicationBuilder) 实例。通过这个构建器,你可以配置应用程序的服务和中间件,进而构建和运行你的 ASP.NET Core Web 应用。

builder.WebHost.UseUrls

builder.WebHost.UseUrls("http://*:8080");

用于设置Web服务器所监听的URL和端口。通过这个方法,开发者可以指定应用程序在哪些地址和端口上运行,从而控制外部请求如何到达你的应用程序。

builder.Configuration

builder.Configuration.AddCommandLine(args);

允许你访问应用程序的配置设置,这些设置通常包含在 appsettings.json、环境变量、用户机密、命令行参数等中。builder.Configuration 是 WebApplicationBuilder 的一部分,提供了一种灵活的方式来管理和访问配置。

services.Configure

appsetting.json包含一个secret类型

{  "Secret": {  "ApiKey": "your-api-key-here",  "ConnectionString": "your-connection-string-here"  }  
}
public class Secret  
{  public string ApiKey { get; set; }  public string ConnectionString { get; set; }  
}
builder.Services.Configure<Secret>(builder.Configuration.GetSection("Secret"));  

是一个用于将应用程序配置绑定到强类型配置对象的服务注册方法。通过这种方式,你可以轻松地管理和访问应用程序的配置数据,并能够在整个应用程序中以一致的方式使用这些配置。通常用于将从配置源(如 JSON 文件、环境变量等)获取的设置绑定到特定的类型上。
实际应用:

services.Configure<MyConnectionConFig>(configuration.GetSection("SysConnection"));
_connection = provider.GetRequiredService<IOptions<MyConnectionConFig>>().Value;

services.BuildServiceProvider

例子

using Microsoft.Extensions.DependencyInjection;  
public interface IMyService  
{  string GetMessage();  
}  
public class MyService : IMyService  
{  public string GetMessage() => "Hello, World!";  
}  
// 创建一个 Service Collection 并注册服务  
var services = new ServiceCollection();  
services.AddSingleton<IMyService, MyService>(); // 注册服务  
// 构建服务提供者  
var serviceProvider = services.BuildServiceProvider();  
// 解析服务  
var myService = serviceProvider.GetService<IMyService>();  
// 使用服务  
Console.WriteLine(myService.GetMessage());

方法用于构建服务提供者(Service Provider),这是完成依赖注入(DI)配置后的一个重要步骤。通过此方法,我们可以生成一个服务提供者实例,该实例可以用于解析已注册的服务。

builder.Host.UseServiceProviderFactory

builder.Host.UseServiceProviderFactory(new AutofacServiceProviderFactory());

builder.Services.AddDistributedMemoryCache

用于注册一个基于内存的分布式缓存服务。此缓存服务适用于在应用程序的不同实例之间共享缓存的数据,但它仅存储在内存中,因此在应用程序重启或部署后,缓存中的数据会丢失。

builder.Services.AddControllersWithViews().AddRazorRuntimeCompilation()

是在 ASP.NET Core 应用程序中注册支持 MVC 控制器和视图的服务,并启用 Razor 视图运行时编译的代码。这对于开发过程中的视图修改非常有用,可以在不重启应用程序的情况下立即查看更改。

builder.Services.AddSession

builder.Services.AddSession(options =>
{options.IdleTimeout = TimeSpan.FromMinutes(AppSetting.SessionTimeout);
});

用于注册会话服务,允许你在应用程序中存储用户的会话状态。会话是用于保存用户数据的功能,它在用户与应用程序的多个请求之间保留数据,便于在用户访问不同页面时维持状态。
▷可以方便地在开发阶段快速进行视图修改而无需重启应用程序。

是在 ASP.NET Core 应用程序中注册 API 控制器并添加对 Newtonsoft.Json 序列化支持的代码。这样做通常是为了方便进行复杂的对象序列化和反序列化,尤其是在处理 JSON 数据时。

builder.Services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>()

是在 ASP.NET Core 应用程序中用于注册 IHttpContextAccessor 服务的代码。这一行的目的是让你可以在应用程序的各个部分访问当前的 HTTP 上下文。
这是 ASP.NET Core 的接口,允许你从非控制器类中访问当前的 HttpContext。对于需要访问 HTTP 请求信息(如请求头、用户信息等)的服务或类,这个接口非常有用。
IHttpContextAccessor 的实例作为单例服务注册到依赖注入容器中。这意味着在整个应用程序的生命周期中,只有一个实例会被创建和使用。这种注册方式非常适合像 IHttpContextAccessor 这样的服务,因为它不持有状态。

builder.Services.TryAddSingleton();

调试

数据表不更新

可能因为里面某些语法错误,导致整个页面异常

layui

固定字段的表格

表格写法如下

  • html <input type="checkbox" lay-skin="primary"> :在前面设置单选框
  • html <tbody id="content"></tbody>:这个是数据本体
  • html <div id="paged"></div>:使用layui的paging模块来更新
<table id="gridList" class="layui-form layui-table table-hover FNMES-table" lay-skin="line"><thead><tr><th><input type="checkbox" lay-skin="primary"></th><th>工单号</th><th>产品</th><th>产品备注</th><th>数量</th><th>计划开始时间</th><th>计划完成时间</th><th>状态</th></tr></thead><!--内容容器--><tbody id="content"></tbody>
</table>
<div id="paged"></div>

使用layui遍历返回的数据

  • layui.each:使用的是layui的迭代器
<script id="contentTpl" type="text/html">{{#  layui.each(d.list, function(index, item){ }}<tr><td><input type="checkbox" lay-skin="primary" value="{{item.Id}}"></td><td>{{item.TaskOrderNumber}}</td><td>{{item.ProductPartNo}}</td><td>{{item.ProductDescription}}</td><td>{{item.PlanQty}}</td><td>{{item.PlanStartTime}}</td><td>{{item.PlanEndTime}}</td><td>{{item.FlagString}}</td></tr>{{#  }); }}{{# if(d.list.length<=0) { }}<tr style="color: red"><td colspan="8">查无数据。</td></tr>{{# } }}
</script>

使用layui来更新

  • initGrid:将返回的数据更新到表格
  • tempElem的值是#contentTpl,指定了更新表格的地方
  • elem的值是#content
  • paging是layui的分页组件,用于分页浏览表格数据
<script type="text/javascript">var paging;layui.config({base: parent._baseUrl}).use(['paging', 'form', 'layer'], function () {var layer = parent.layer || layui.layer;var form = layui.form;paging = layui.paging();$("#lineId").bindSelect({type: "POST",url: "/system/line/getListTreeSelect",title: '请选择线体'});initGrid();});function initGrid() {if ($("#lineId").val() == "0") {return};paging.init({url: '/param/order/index',elem: '#content',tempElem: '#contentTpl',singleSelected: true, //单选params: {keyWord: $("#keyWord").val(),configId: $("#lineId").val(),index: $('#queryDate').find('button.active').val()},pageConfig: {elem: 'paged',pageSize: 10,},success: function () {}});}

弹窗显示表格

  • 按钮用onclick绑定事件btn_data()
  • btn_data用layerOpen中content中传递对应的参数
<button class="layui-btn layui-btn-primary layui-btn-small" onclick="btn_data()">查看产品</button>function btn_data() {var ids = $("#gridList").gridSelectedRowValue();if (ids.length != 1) {$.layerMsg("请勾选单条记录查看。", "warning");return;}$.layerOpen({id: "data",title: "查看产品",width: "1200px",height: "550px",content: "/param/order/data?primaryKey=" + ids[0] + "&configId=" + $("#lineId").val(),btn: null});
}
var paging;
layui.config({ base: parent._baseUrl }).use(['paging', 'form'], function () {var form = layui.form;paging = layui.paging();var primaryKey = $.getQueryString("primaryKey");var configId = $.getQueryString("configId");initGrid(primaryKey,configId);
});
function initGrid(primaryKey, configId) {paging.init({url: '/param/order/getData',elem: '#content',tempElem: '#contentTpl',checkbox: true, //是否显示复选框singleSelected: true, //单选params: {primaryKey: primaryKey,configId: configId,},pageConfig: {elem: 'paged',pageSize: 10,},success: function () {},fail: function (msg) {top.layer.msg(msg);}});
}

返回页面,用ViewData传递参数

[Route("param/order/data")]
[HttpGet]
public ActionResult Data(string primaryKey, string configId)
{ViewData["primaryKey"] = primaryKey;ViewData["configId"] = configId;return View();
}

在js文件中用$.getQueryString读取

layui.config({ base: parent._baseUrl }).use(['paging', 'form'], function () {var form = layui.form;paging = layui.paging();var primaryKey = $.getQueryString("primaryKey");var configId = $.getQueryString("configId");initGrid(primaryKey,configId);
});

表格弹窗查看

主js写法:

  • content: “/param/order/detail?primaryKey=” + ids[0] + “&configId=” + $(“#lineId”).val():传递参数primarykey和configId
  • layerOpen:默认使用Get请求方法,C#对应的方法也要使用HttpGet
function btn_detail() {var ids = $("#gridList").gridSelectedRowValue();if (ids.length != 1) {$.layerMsg("请勾选单条记录查看。", "warning");return;}$.layerOpen({id: "detail",title: "查看工单",width: "730px",height: "400px",content: "/param/order/detail?primaryKey=" + ids[0] + "&configId=" + $("#lineId").val(),btn: null});
}

子html(表单)写法:

  • form:表单元素,class=“layui-form”
  • class=“layui-form-item”:表单项
<form id="form" class="layui-form" style="margin-top: 25px"><form id="form" class="layui-form" style="margin-top: 25px"><div class="layui-form-item"><div class="layui-inline"><label class="layui-form-label label-required">工单号</label><div class="layui-input-inline"><input type="hidden" name="Id" id="Id" /><input type="hidden" name="ConfigId" id="ConfigId" /><input type="text" name="TaskOrderNumber" autocomplete="off" class="layui-input" disabled /></div></div></div><div class="layui-form-item"><div class="layui-inline"><label class="layui-form-label">产品</label><div class="layui-input-block"><input type="text" name="ProductPartNo" autocomplete="off" class="layui-input" disabled /></div></div><div class="layui-inline"><label class="layui-form-label">产品描述</label><div class="layui-input-block"><input type="text" name="ProductDescription" autocomplete="off" class="layui-input" disabled /></div></div></div><div class="layui-form-item"><div class="layui-inline"><label class="layui-form-label">计划数量</label><div class="layui-input-block"><input type="text" name="PlanQty" autocomplete="off" class="layui-input" disabled /></div></div><div class="layui-inline"><label class="layui-form-label">状态</label><div class="layui-input-block"><input type="text" name="FlagString" autocomplete="off" class="layui-input" disabled /></div></div></div><div class="layui-form-item"><div class="layui-inline"><label class="layui-form-label">计划开始时间</label><div class="layui-input-inline"><input type="text" name="PlanStartTime" autocomplete="off" class="layui-input" disabled /></div></div><div class="layui-inline"><label class="layui-form-label">计划完成时间</label><div class="layui-input-inline"><input type="text" name="PlanEndTime" autocomplete="off" class="layui-input" disabled /></div></div></div><div class="layui-form-item"><div class="layui-inline"><label class="layui-form-label">上线数量</label><div class="layui-input-inline"><input type="text" name="StartQty" autocomplete="off" class="layui-input" disabled /></div></div><div class="layui-inline"><label class="layui-form-label">下线数量</label><div class="layui-input-inline"><input type="text" name="PackQty" autocomplete="off" class="layui-input" disabled /></div></div></div>
</form>

C#代码

  • 无参数,由url传递参数
[Route("param/order/detail")]
[HttpGet, AuthorizeChecked]
public ActionResult Detail()
{return View();
}

表单查看(不提交)

主js写法:

  • $.layerOpen:弹窗,并传递参数primarykey和configId
    function btn_detail() {var ids = $("#gridList").gridSelectedRowValue();if (ids.length != 1) {$.layerMsg("请勾选单条记录查看。", "warning");return;}$.layerOpen({id: "detail",title: "查看工单",width: "730px",height: "400px",content: "/param/order/detail?primaryKey=" + ids[0] + "&configId=" + $("#lineId").val(),btn: null});}

C#代码:

  • 尽管Detail的参数为空,但是url中会存在primaryKey和configId
        [Route("param/order/detail")][HttpGet, AuthorizeChecked]public ActionResult Detail(){return View();}

子js(表单)写法:

  • $(“#form”).formSerialize(data):表单反序列
  • form.render():表单渲染
layui.use(['element', 'form', 'laydate'], function () {var form = layui.form;var element = layui.element;var laydate = layui.laydate;laydate.render({});//获取url参数var primaryKey = $.getQueryString("primaryKey");var configId = $.getQueryString("configId");if (primaryKey) {$.ajax({url: "/param/order/getForm",data: {primaryKey: primaryKey,configId: configId},type: "post",dataType: "json",async: false,success: function (data) {$("#form").formSerialize(data);}});}form.render();
});

表单渲染对应C#代码:

  • 返回的是Content,entity.Tojson()返回的是json字符串
  • 会自动对json字符串解释并根据对应的name对元素进行赋值
   [Route("param/order/getForm")][HttpPost, LoginChecked]public ActionResult GetForm(string primaryKey, string configId){ParamOrder entity = orderLogic.GetWithQty(long.Parse(primaryKey), configId);return Content(entity.ToJson());}

表单提交

主js写法:

  • iBody.find(‘#btnSubmit’).click():表单需要提交的话,需要包含这一行
  • $.layerOpen:打开默认调用post方法
function btn_edit() {var ids = $("#gridList").gridSelectedRowValue();if (ids.length != 1) {$.layerMsg("请勾选单条记录修改。", "warning");return;}$.layerOpen({id: "edit",title: "修改工序",width: "750px",height: "400px",content: "/param/route/form?primaryKey=" + ids[0] + "&configId=" + $("#lineId").val(),yes: function (iBody) {iBody.find('#btnSubmit').click();initGrid();}});
}

子html(表单)写法:

  • form包括的部分就是表单部分
  • layui-form-item:表单项
  • html<button id="btnSubmit" class="layui-btn" lay-submit lay-filter="add">提交</button>:隐藏的按钮,利用这个执行提交
<form id="form" class="layui-form" style="margin-top: 25px"><div class="layui-form-item"><div class="layui-inline"><label class="layui-form-label label-required">选择工序</label><div class="layui-input-inline"><input type="hidden" name="Id" id="Id" /><input type="hidden" name="ConfigId" id="ConfigId" /><input type="hidden" name="ProductPartNo" id="ProductPartNo" /><select class="select2 layui-input-inline" lay-ignore name="StationCode" lay-verify="required" id="StationCode" style="width: 130px"></select></div></div><div class="layui-inline"><label class="layui-form-label label-required">工序顺序号</label><div class="layui-input-inline"><input type="number" name="Step" id="Step" lay-verify="required" placeholder="请输入序号" autocomplete="off" class="layui-input"></div></div></div><div class="layui-form-item"><div class="layui-inline"><label class="layui-form-label label-required">校验工站</label><div class="layui-input-inline"><select lay-ignore name="CheckStations" class="select2" id="CheckStations" multiple="multiple" style="width: 514px;" ></select></div></div></div><div class="layui-form-item"><div class="layui-inline"><label class="layui-form-label">选项</label><div class="layui-input-block"><input type="checkbox" lay-skin="primary" name="IsAllowJump" value="true" title="允许跳站" checked><input type="checkbox" lay-skin="primary" name="IsAllowRepeat" value="true" title="允许重复作业"><input type="checkbox" lay-skin="primary" name="IsTranshipStation" value="true" title="中转工序"><input type="checkbox" lay-skin="primary" name="IsGenerateCodeStation" value="true" title="生成国标码工序"><input type="checkbox" lay-skin="primary" name="IsEntrance" value="true" title="入口工序"></div></div></div><div class="layui-form-item" style="display: none"><div class="layui-input-block"><button id="btnSubmit" class="layui-btn" lay-submit lay-filter="add">提交</button></div></div>
</form>

子js写法:

  • $(“#form”).formSerialize(data):通过formSerialize反序列化到每一个控件
  • form.on(‘submit(add)’, function (form):通过submit(add)事件进行表单提交
 <script type="text/javascript">layui.use(['element', 'form', 'laydate', 'layer'], function () {var form = layui.form;var element = layui.element;var laydate = layui.laydate;laydate.render({});var configId = $.getQueryString("configId");$("#ConfigId").val(configId);$("#StationCode").bindSelect({type: "POST",url: "/param/unitProcedure/getParentCode?configId=" + configId});$("#CheckStations").bindSelect({type: "POST",url: "/param/unitProcedure/getParentCode?configId=" + configId,title: '请选择校验工序'});var configId = $.getQueryString("configId");$("#ConfigId").val(configId);var primaryKey = $.getQueryString("primaryKey");var productPartNo = $.getQueryString("productPartNo");$("#ProductPartNo").val(productPartNo);if (primaryKey) {$.ajax({url: "/param/route/getForm",data: { primaryKey: primaryKey,configId: configId },type: "post",dataType: "json",async: false,success: function (data) {//在这里反序列化$("#form").formSerialize(data);$("#ConfigId").val(configId);}});}form.render();form.on('submit(add)', function (form) {var type = $('input[name="IsParent"]:checked').val();var parentIsNull = $("#Pid").val() == null;form.field.Criterion = $("#CheckStations").val().join();$.formSubmit({url: "/param/route/form",data: form.field});return false;});});</script>

webapi

传参

无论是内建类型,还是实体类型,统一传参类型为dynamic,由方法自身来解释
data本身必须是Json字符串,而不是实体

using Newtonsoft.Json;
[ApiController]
[Route("[controller]")]
public class apiController : ControllerBase
{//实体public class test{public string name = "";public int id = 1;public string[]? nickName;}public string dynamicPara(dynamic data){test objdyn = JsonConvert.DeserializeObject<test>(Convert.ToString(data));string d = objdyn.name;return d;}
}

用apipost测试,接口可以正常解释参数
在这里插入图片描述

Project

Entity

声明模型,包括DTO(数据传输对象),表格实体等等

Utility

相关的库,包括日志

杂记

菜单获取

1、先找出类型为菜单且图层为0的项
c => c.Type == ModuleType.Menu && c.Layer == 0
Menu = 2
2、再找出类型为子菜单且图层为1,父Id为上一层id的项
c => c.Type == ModuleType.SubMenu && c.Layer == 1 && c.ParentId == item.Id
3、只要第二行的url和图标和名称
Select(c => new LayChildNavbar() { href = c.Url, icon = c.Icon, title = c.Name })

url

  • Controller类要在前面加上,才能找到对应视图
   [HiddenApi][Area("Param")]
  • 所有需要路由的方法都要加上路由地址,js才能调用
[Route("/param/plc/index")]
   [HiddenApi][Area("Param")]public class PLCController : Controller{[Route("/param/plc/index")][HttpGet]public IActionResult Index(){return View();}}

分页表格

Js写法,需要注意params即便为空,也要写上

function initGrid() {paging.init({url: '/param/plc/getlist',elem: '#content',tempElem: '#contentTpl',singleSelected: true, //单选params: {},pageConfig: {elem: 'paged',pageSize: 10,},success: function () {}});
}

C#写法,要带pageIndex和pageSize,一个是页码,一个是一页显示的行数

[Route("/param/plc/getlist")]
[HttpPost]
public ActionResult GetList(int pageIndex, int pageSize)
{try{int totalCount = 0;var pageData = paramPLCLogic.GetList(pageIndex, pageSize, ref totalCount);var result = new LayPadding<ParamPLC>(){result = true,msg = "success",list = pageData,count = totalCount};return Content(result.ToJson());}catch(Exception E){return Content(new LayPadding<ParamPLC>(){result = false,msg = E.Message,list = new List<ParamPLC>(),count = 0}.ToJson());}
}

报错

分表标识

现象:“中文提示 : 需要在分表字段加上属性[SplitFieldAttribute]
English Message : [SplitFieldAttribute] need to be added to the table field”
原因:没指定[splitfield]
解决:在CreateTime上面标注[splitfield]属性

在webservice的形参不能设置datacontract

会出现labview无法找到返回的data

"…"doesnothaveanattribute route. ActionMethodsOnController

现象:如图,报错"…"doesnothaveanattribute route. ActionMethodsOnController
在这里插入图片描述
原因:指定了[ApiController]属性的类,存在没指定[Route]属性的方法
解决:所有方法都要指定[Route]属性

btn_task is not define

现象:在点击网页按钮后,控制台出现如题异常
原因:btn_task用了layeropen,url没写对,一定要有参数,不能直接调用
在这里插入图片描述

解决:url要写,并且要带参数

表单提交后提示无信息的异常抖动窗口

现象:如题
原因:提交时候post的地址,有多个
解决:保证只有一个就行

控制器中的形参拿不到视图中Form.Field的值

现象:如题
在这里插入图片描述
原因:AskTargetParam 的成员变量没实现get和set
解决:AskTargetParam 里面的成员变量实现get和set,如下

public class AskTargetParam
{//任务号public string taskId { get; set; }//产品条码public string productCode { get; set; }//指当前物料的类型public string productType { get; set; }//起点public string start { get; set; }//区域点public string region { get; set; }
}

http://www.ppmy.cn/server/170746.html

相关文章

Java进阶学习笔记64——IO流

IO流&#xff1a; 输入输出流&#xff0c;就是读写数据的。 IO流的应用场景&#xff1a; 怎么去学习IO流&#xff1f; 1、先搞清楚IO流的分类、体系&#xff1f; 2、再挨个学习每个IO流的作用、用法。 IO流的分类&#xff1a; 按流的方向分为&#xff1a; 按流中数据的最小…

【Docker基础】理解 Docker:本质、性质、架构与核心组件

文章目录 Docker 本质Docker 的引擎迭代Docker 和虚拟机的区别Docker 为什么比虚拟机资源利用率高&#xff0c;速度快&#xff1f;Docker 和 JVM 虚拟化的区别Docker 版本1. LXC (Linux Containers)2. libcontainer3. Moby4. docker-ce5. docker-ee总结&#xff1a; Docker 架构…

C#贪心算法

贪心算法&#xff1a;生活与代码中的 “最优选择大师” 在生活里&#xff0c;我们常常面临各种选择&#xff0c;都希望能做出最有利的决策。比如在超市大促销时&#xff0c;面对琳琅满目的商品&#xff0c;你总想用有限的预算买到价值最高的东西。贪心算法&#xff0c;就像是一…

JPA与存储过程的完美结合

在现代的Java开发中&#xff0c;JPA&#xff08;Java Persistence API&#xff09;已经成为ORM&#xff08;对象关系映射&#xff09;的主流选择之一。它不仅简化了数据库操作&#xff0c;还提供了强大的功能来与数据库交互。今天&#xff0c;我们将深入探讨如何通过NamedStore…

音视频容器格式

音视频容器格式是存储和封装音视频流、字幕、元数据等信息的文件格式。容器格式决定了音视频的组织方式和播放方式&#xff0c;不同的容器格式适用于不同的用途和平台。以下是一些常见的音视频容器格式的详细介绍&#xff1a; 1. MP4 (.mp4) 介绍&#xff1a; MP4 是最常见的…

网络应用层之HTTPS

前言 HTTPS 是什么 HTTP 协议内容都是按照文本的方式明文传输的. 这就导致在传输过程中出现⼀些被篡改的情况. HTTPS 也是⼀个应用层协议, 是在 HTTP 协议的基础上引入了⼀个加密层SSL/TLS, 负责对HTTP进行握手协商和数据的加密解密. 此时交给传输层的数据都是经过加密的, 数…

“零信任+AI”将持续激发网络安全领域技术创新活力

根据Forrester的报告&#xff0c;到2025年&#xff0c;AI软件市场规模将从2021年的330亿美元增长到640亿美元&#xff0c;网络安全将成为AI支出增长最快的细分市场。当前&#xff0c;零信任供应侧企业已经开始尝试使用AI赋能零信任&#xff0c;未来&#xff0c;零信任与AI的结合…

终端指令(补充)和shell

1.终端指令&#xff08;补充&#xff09;思维导图 2.shell思维导图