初始化
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; }
}