博客 (138)

安装 Nuget 包:

BuildBundlerMinifier


项目根目录创建绑定配置文件:bundleconfig.json

示例:

[
  {
    "outputFileName": "wwwroot/css/site.min.css",
    "inputFiles": [
      "wwwroot/css/site.css",
      "wwwroot/css/custom.css"
    ]
  },
  {
    "outputFileName": "wwwroot/js/site.min.js",
    "inputFiles": [
      "wwwroot/js/site.js"
    ],
    "minify": {
      "enabled": true,
      "renameLocals": true
    },
    "sourceMap": false
  }
]

配置文件中所有路径都相对于项目根目录(而非静态文件根目录 wwwroot),因此配置的路径都要以“wwwroot”开头。

outputFileName 是压缩合并后的文件,inputFiles 是被压缩合并的原始文件集合。

对于 js 配置部分,minify.enabled 配置是否缩小,renameLocals 配置是否修改变量名,sourceMap 配置是否生成 map 映射文件。


引用示例:

<link rel="stylesheet" href="~/css/site.min.css" asp-append-version="true" />

asp-append-version 表示是否在引用路径添加版本参数,可实现在文件有修改时及时在客户端浏览器中生效。


* 注意:有时候“生成”不一定生效,“重新生成”肯定会生效。


更多高级用法请参考官方文档

xoyozo 6 年前
9,595

An unhandled exception occurred while processing the request.

InvalidOperationException: RenderBody has not been called for the page at '/Areas/Admin/Views/Shared/_Layout.cshtml'. To ignore call IgnoreBody().

Microsoft.AspNetCore.Mvc.Razor.RazorPage.EnsureRenderedBodyOrSections()


解决方法一:

return; 前执行 IgnoreBody();


解决方法二:

不要在 @RenderBody() 之前执行 return;

xoyozo 6 年前
12,246

* 本文凡使用变量 httpContextAccessor_httpContextAccessor 的地方都需要需要注入 Microsoft.AspNetCore.Http.IHttpContextAccessor

* 在视图(view)中应以 ViewContext 类引出


获取当前页面网址:

using Microsoft.AspNetCore.Http.Extensions;
string url = Request.GetDisplayUrl();


获取当前访问的域名和端口:

image.png


获取来源:

Request.GetTypedHeaders().Referer


判断 Scheme 是否为 https:

Request.IsHttps


获取客户端IP和端口、服务器IP和端口:

image.png


获取浏览器用户代理(UserAgent):

httpContextAccessor.HttpContext.Request.Headers[HeaderNames.UserAgent];


获取当前请求的唯一标识:

httpContextAccessor.HttpContext.TraceIdentifier

返回结果:80000564-0002-f700-b63f-84710c7967bb

用途:可作为生成随机数的种子。


获取客户端IP地址:

httpContextAccessor.HttpContext.Connection.RemoteIpAddress


获取当前项目根目录磁盘路径:

AppContext.BaseDirectory // 以“\”结尾

注意:此路径到项目根目录,而非网站根目录,网站根目录请自行追加,默认为 wwwroot\


编码/解码:(参数和返回值均为 string?

using System.Net;
WebUtility.HtmlEncode(myString)
WebUtility.HtmlDecode(myString)
WebUtility.UrlEncode(myString)
WebUtility.UrlDecode(myString)


更多:https://xoyozo.net/Blog/Index/Core


xoyozo 6 年前
5,155

本文使用 Pomelo 提供的 Pomelo.EntityFrameworkCore.MySql,如使用 MySql.Data.EntityFrameworkCore 请移步

对比 MySql.Data.EntityFrameworkCore 与 Pomelo.EntityFrameworkCore.MySql


本文以 Visual Studio 2019、ASP.NET Core 3.0 开发环境为例。

  1. 新建 ASP.NET Core Web 应用程序。

  2. 安装 NuGet 包:

    Microsoft.EntityFrameworkCore.Tools

    Pomelo.EntityFrameworkCore.MySql(3.0.0 预发行版以上)

    image.png

  3. 根据已有数据库创建数据模型。在 NuGet 的程序包管理(Package Manager)控制台中(PowerShell)执行命令:

    Scaffold-DbContext "server=数据库服务器;uid=数据库用户名;pwd=数据库密码;database=数据库名;" Pomelo.EntityFrameworkCore.MySql -OutputDir Data -Force

    .Net Core CLi:

    dotnet ef dbcontext scaffold "server=数据库服务器;uid=数据库用户名;pwd=数据库密码;database=数据库名;" Pomelo.EntityFrameworkCore.MySql -o Data -f
  4. 搞定。


补充:其它数据库提供程序请参考:https://docs.microsoft.com/zh-cn/ef/core/providers/


代码参数说明:

-OutputDir (-o) *** 实体文件所存放的文件目录

-ContextDir *** DbContext文件存放的目录

-Context *** DbContext文件名

-Schemas *** 需要生成实体数据的数据表所在的模式

-Tables(-t) *** 需要生成实体数据的数据表的集合

-DataAnnotations

-UseDatabaseNames 直接使用数据库中的表名和列名(某些版本不支持)

-Force (-f) 强制执行,重写已经存在的实体文件


更多高级用法请参考官方文档


xoyozo 7 年前
9,905

mesh-topology.png

路由器模式:使用 mesh 主体拨号,缺点是由于 mesh 主体不适合放入弱电箱,那么就有两条网线连接到弱电箱(不需要有线回程或不需要接交换机的忽略此缺点)。

AP 模式:适合已有拨号路由器的环境,mesh 路由器主体与分身之间用 AP 模式连接(小米路由器 Mesh 不支持 AP 模式,估计跟“不分子母”有关);


布线方案:

如果 mesh 作拨号路由器功能够用,那么直接使用路由器模式。家庭新装修的朋友建议在合适的位置(如客厅电视机柜)预留两条网线到弱电箱,一条用于连接光猫到 Mesh 主体,再用另一条有线回程到弱电箱的交换机,无线回程者随意。

如果选择其它路由器作拨号路由器(如软路由,或看中小米路由器强大的 App 功能又不想用小米 mesh),那么 mesh 路由器使用 AP 模式,本体接任意墙壁网口即可。建议关闭拨号路由器的 WiFi,并考虑带机量。


顺便提一下 AC+AP 方案的布线:

同样的,如果无其它拨号路由器,那么可以选择路由/AC/PoE 一体机,配合 AP 使用;如果有指定的拨号路由器,那么选择单独的 AC 控制器 + 交换机 + AP 即可。

AC 和 AP 可二层组网、三层组网,可直连式组网、旁挂式组网。

旁挂组网时,如果 AC 控制器选择百兆网口,不会影响千兆交换机和 AP 的传输效率,因为 AC 控制器仅用来管理 AP,不进行数据传输。

AP 有面板式、吸顶式、户外等可选,PoE 或 DC 供电,有胖瘦之分。胖 AP 有独立管理后台,瘦 AP 无管理后台,必须与 AC 配合使用。

据说:TL-AC100 支持快速漫游,TL-AC300 支持无缝漫游。

xoyozo 7 年前
85,061
  1. 微信的 H5 页面前端引导到:

    https://api.magcloud.cc/magshare/{siteId}?jump_url={jump_url}&content_url={content_url}

    各参数含义见官方文档:http://doc.magcloud.net/325339

    content_url 地址(一般仍为活动页面)接收参数 magshareredirect,值为 1 则跳转到自定义的引导页。

  2. 自定义引导页按 iOS 和安卓显示图文和箭头,引导用户点击右上角菜单,在浏览器中打开。

  3. 在浏览器 H5 中引导打开:

    {siteId}://pagejump?jump_url={jump_url}

    各参数含义见第 1 步中的文档。

    这里涉及一个“若未安装则引导安装”的过程,可以选择下方合适的一种方式实现:

    • A 标签的 href 填入下载地址,onclick 事件 location 到 App

    • onclick 事件 location 到 App,再用 setTimeOut location 到下载地址

    • 若仍无法实现预期效果,可以在弹出层中放置“未安装,前往下载”和“已安装,立即打开”两个按钮,让用户自己选择

  4. 若下载地址为应用宝,那么在 iOS 中可能会出现“打开 App 后继而自动打开 App Store”的情况,可以自建中转的 App 介绍页引导到 App Store 或应用宝。

  5. 分别实现微信和 MAGAPP 客户端的分享

xoyozo 7 年前
8,173

Orbi 型号命名规则:

套装:RBK

主体:RBR

分身:RBS、RBW 等


套装对比:


小米 Mesh

RBK13

RBK20

RBK30

RBK40

RBK50

CPU

高通 IPQ4019 四核 717MHz

四核 710MHz

ROM

128MB

-

-

-

-

-

内存 RAM

256MB DDR3

512MB

闪存 Flash

-

256MB

4GB

包装内容

2 个(不分子母)

1 个 RBR10

1 个 RBS10

1 个 RBR20

1 个 RBS20

1 个 RBR40

1 个 RBW30 插墙式

1 个 RBR40

1 个 RBS40

1 个 RBR50

1 个 RBS50

速度

AC1300 双频

1300Mbps 电力线

1000M 有线

AC1200 双频段 

2.4GHz 300Mbps+5GHz 866Mbps

三频

AC2200 本体

AC2200 分身

 (866回程+866+400Mbps)

三频

AC3000 本体

AC3000 分身

(1733回程+866+400Mbps)

本体端口

每个主机 3 个 WAN/LAN 自适应以太网端口

1 WAN & 1 LAN

1 WAN & 1 LAN

1 WAN & 3 LAN

1 WAN & 3 LAN & 1 USB 2.0

分身端口

-

2 LAN

-

4 LAN

4 LAN & 1 USB 2.0

天线

4根

6根

以太网回程

支持
(互联网 → 主 mesh → 交换机 → 子 mesh)


支持
(RBW30 无 LAN 口,不能组成有线回程)

Daisy Chain Topology 菊花链

支持

Beamforming 波束成形

支持

MU-MIMO

支持

802.11k/v 快速漫游

支持

802.11r 快速漫游

不支持

802.11ax(Wi-Fi 6)

不支持

AP 模式

不支持


支持

关闭 WiFi 双频合一

原厂不支持,小米和 RBK50 可通过修改实现,分离后有线回程可能会失效

IPv6

支持

带机量

248






覆盖范围

-

418 平方米

250 平方米

200 平方

250 平方米

350 平方米

官网价

999

229.99 美元

-

-

-

-

京东自营

999


RBK20:949~1999
RBK23:1399~2999

RBK30:1499~1999

RBK40:2699

RBK50:2499~2999
RBK53:3499~3999

京东旗舰

-


RBK20:999
RBK23:1499

RBK30:2099

RBK40:2799

RBK50:2599
RBK53:3599

天猫旗舰店

999


RBK20:999
RBK23:1299

RBK30:1399

-

RBK50:2799
RBK53:3799

其它天猫店

969 苏宁易购


-

RBK30:1288

RBK40:1699

-

优势

管理功能丰富。

配合米家APP 设置小米智能家居设备入网时,无需手动输入密码,入网更便捷。

网口盲插,不分子母。后续再扩展两个分身时可直接购买套装充当两个分身,相对于 Orbi 购买两个分身要节省成本。


三频。

性能稳定。

大内存


分体价格:

  • 本体 RBR20:599

  • 本体 RBR40:999

  • 本体 RBR50:999 活动

  • 分身 RBS20:699

  • 分身 RBW30 插墙:999

  • 分身 RBS40:1099

  • 分身 RBS50:1449

  • 分身 RBS50Y 室外:未知


价格采自2019年8月


主体/分身 匹配:

  • 分身 RBS20 可作为 RBR20, RBR40 or RBR50 的卫星

  • 分身 RBW30 可作为 RBR40 or RBR50 的卫星

  • 分身 RBS40 可作为 RBR40 or RBR50 的卫星

  • 分身 RBS50 可作为 RBR50 的卫星

  • 分身 RBS50Y 可作为 RBR50 or RBR40 or SRR60 的卫星


image.png


  • RBK13 = 1个 RBR10 + 2个 RBS10

  • RBK20 = 1个 RBR20 + 1个 RBS20

  • RBK23 = 1个 RBR20 + 2个 RBS20

  • RBK30 = 1个 RBR40 + 1个 RBW30

  • RBK33 = 1个 RBR40 + 2个 RBW30

  • RBK40 = 1个 RBR40 + 1个 RBS40

  • RBK43 = 1个 RBR40 + 2个 RBS20

  • RBK44 = 1个 RBR40 + 3个 RBS20

  • RBK50 = 1个 RBR50 + 1个 RBS50

  • RBK53 = 1个 RBR50 + 2个 RBS50


扩展阅读:Mesh 路由器有线回程布线方案

xoyozo 7 年前
28,823

本文介绍 ASP.NET 的 Swagger 部署,若您使用 ASP.NET Core 应用程序,请移步 ASP.NET Core Web API Swagger 官方文档:

https://docs.microsoft.com/zh-cn/aspnet/core/tutorials/first-web-api?view=aspnetcore-5.0&tabs=visual-studio

https://github.com/domaindrivendev/Swashbuckle.AspNetCore


安装

NuGet 中搜索安装 Swashbuckle,作者 Richard Morris


访问

http://您的域名/swagger


配置


显示描述

以将描述文件(xml)存放到项目的 bin 目录为例:

  1. 打开项目属性,切换到“生成”选项卡

  2. 在“配置”下拉框选择“所有配置”

  3. 更改“输出路径”为:bin\

  4. 勾选“XML 文档文件”:bin\******.xml,(默认以程序集名称命名)

  5. 打开文件:App_Start/SwaggerConfig.cs

  6. 取消注释:c.IncludeXmlComments(GetXmlCommentsPath());

  7. 添加方法:

    public static string GetXmlCommentsPath()
    {
        return System.IO.Path.Combine(
            System.AppDomain.CurrentDomain.BaseDirectory,
            "bin",
            string.Format("{0}.xml", typeof(SwaggerConfig).Assembly.GetName().Name));
    }

    其中 Combine 方法的第 2 个参数是项目中存放 xml 描述文件的位置,第 3 个参数即以程序集名称作为文件名,与项目属性中配置一致。

如遇到以下错误,请检查第 2、3、4 步骤中的配置(Debug / Release)

500 : {"Message":"An error has occurred."} /swagger/docs/v1


使枚举类型按实际文本作为参数值(而非转成索引数字)

  1. 打开文件:App_Start/SwaggerConfig.cs

  2. 取消注释:c.DescribeAllEnumsAsStrings();

xoyozo 7 年前
4,836

思路:使用 SHOW PROCESSLIST 命令列出数据库当前的所有连接,筛选相关进程,使用 KILL 命令结束进程。

首先创建 SHOW PROCESSLIST 结果集的模型:

class ProcessItem
{
    public int Id { get; set; }
    public string User { get; set; }
    public string db { get; set; }
    public string Command { get; set; }
    public int Time { get; set; }
}

查询、筛选、执行:

using (var db = new dbEntities())
{
    foreach (var p in db.Database.SqlQuery<ProcessItem>("SHOW PROCESSLIST").ToList())
    {
        if (p.Id > 0 && p.User == "用户名" && p.db == "库名" && p.Command == "Sleep" /*&& p.Time >= minSecondsToExpire*/)
        {
            pids.Add(p.Id);
        }
    }
    foreach (var pid in pids)
    {
        db.Database.ExecuteSqlCommand("KILL " + pid);
    }
}
xoyozo 7 年前
3,731

百度地图天地图
初始化地图var map = new BMap.Map("allmap");var map = new T.Map("allmap");
将覆盖物添加到地图addOverlay(overlay: Overlay)addOverLay(overlay:OverLay)
从 Map 的 click 事件中获取坐标点

map.addEventListener("click", function (e) {

    Point = e.point;

}

map.addEventListener("click", function (e) {

    LngLat = e.lnglat;

}

坐标点new BMap.Point(lng: Number, lat: Number)new T.LngLat(lng: Numbe, lat: Number)
像素点new BMap.Pixel(x: Number, y: Number)new T.Point(x: Number, y: Number)
文本标注
new BMap.Label(content: String, {
    offset: Size,
    position: Point
})
new T.Label({
    text: string, 
    position: LngLat, 
    offset: Point
})
设置文本标注样式
setStyle(styles: Object)每个样式使用单独的 set 方法实现
图像标注
new BMap.Marker(Point, {
    offset: Size,
    icon: Icon,
    enableMassClear: Boolean,
    enableDragging: Boolean,
    enableClicking: Boolean,
    raiseOnDrag: Boolean,
    draggingCursor: String,
    rotation: Number,
    shadow: Icon,
    title: String
})
new T.Marker(LngLat, {
    icon: Icon,
    draggable: boolean,
    title: string,
    zIndexOffset: number,
    opacity: number
})
为图像标注添加文本标注Marker.setLabel(label: Label)

无。

可借用 title(鼠标掠过显示)属性来实现,并通过 Marker.options.title 来获取值

从图像标注获取坐标点Point = Marker.getPosition();
LngLat = Marker.getLngLat();
绘制折线
new BMap.Polyline(points: Array<Point>, {
    strokeColor: String,
    strokeWeight: Number,
    strokeOpacity: Number,
    strokeStyle: String,
    enableMassClear: Boolean,
    enableEditing: Boolean,
    enableClicking: Boolean,
    icons: Array<IconSequence>
})
new T.Polyline(points:Array<LngLat>, {
    color: string,
    weight: number,
    opacity: number,
    lineStyle: string
})
绘制多边形
new BMap.Polygon(points: Array<Point>, {
    strokeColor: String,
    fillColor: String,
    strokeWeight: Number,
    strokeOpacity: Number,
    fillOpacity: Number,
    strokeStyle: String,
    enableMassClear: Boolean,
    enableEditing: Boolean,
    enableClicking: Boolean
})
new T.Polygon(points:Array<LngLat>,{
    color: string,
    weight: number,
    opacity: number,
    fillColor: String,
    fillOpacity: number,
    lineStyle: string
})
设置多边形的点数组Polygon.setPath(points: Array<Point>)Polyline.setLngLats(lnglats: Array<LngLat>)
设置地图视野Map.setViewport(view: Array<Point> | Viewport, viewportOptions: ViewportOptions)Map.setViewport(view: Array<LngLat>)
xoyozo 7 年前
10,591