博客 (167)

Nuget 安装:X.PagedList.Mvc.Core


控制器:

using X.PagedList;

public IActionResult Index(int page = 1)
{
    ……
    return View(q.ToPagedList(page, size));
}


视图:

@using X.PagedList
@using X.PagedList.Mvc.Core
@model IPagedList<xxx>

@Html.PagedListPager(Model, page => Url.Action("Index", new { page }))


自定义(options 默认值):

@Html.PagedListPager(
    Model, 
    page => Url.Action("Index", new { page }), 
    new X.PagedList.Mvc.Common.PagedListRenderOptionsBase
    {
        HtmlEncoder = HtmlEncoder.get_Default(),
        DisplayLinkToFirstPage = PagedListDisplayMode.IfNeeded,
        DisplayLinkToLastPage = PagedListDisplayMode.IfNeeded,
        DisplayLinkToPreviousPage = PagedListDisplayMode.IfNeeded,
        DisplayLinkToNextPage = PagedListDisplayMode.IfNeeded,
        DisplayLinkToIndividualPages = true,
        DisplayPageCountAndCurrentLocation = false, // 显示总页数和当前页码
        MaximumPageNumbersToDisplay = 10, // 最多显示页码数
        DisplayEllipsesWhenNotShowingAllPageNumbers = true,
        EllipsesFormat = "&#8230;",
        LinkToFirstPageFormat = "<<",
        LinkToPreviousPageFormat = "<",
        LinkToIndividualPageFormat = "{0}",
        LinkToNextPageFormat = ">",
        LinkToLastPageFormat = ">>",
        PageCountAndCurrentLocationFormat = "Page {0} of {1}.",
        ItemSliceAndTotalFormat = "Showing items {0} through {1} of {2}.",
        FunctionToDisplayEachPageNumber = null,
        ClassToApplyToFirstListItemInPager = null,
        ClassToApplyToLastListItemInPager = null,
        ContainerDivClasses = new string[1]
        {
            "pagination-container"
        },
        UlElementClasses = new string[1]
        {
            "pagination"
        },
        LiElementClasses = Enumerable.Empty<string>(),
        PageClasses = Enumerable.Empty<string>(),
        UlElementattributes = null,
        ActiveLiElementClass = "active",
        EllipsesElementClass = "PagedList-ellipses",
        PreviousElementClass = "PagedList-skipToPrevious",
        NextElementClass = "PagedList-skipToNext",
    })


保留地址栏参数:

@{ 
    string query = Context.Request.QueryString.Value;
}
@Html.PagedListPager(Model, page => Regex.IsMatch(query, @"[?&]page=\d+")
    ? Regex.Replace(query, @"([?&])page=\d+", $"$1page={page}")
    : (query.StartsWith("?") ? $"{query}&page={page}" : $"{query}?page={page}"),
    new X.PagedList.Web.Common.PagedListRenderOptionsBase
    {
        DisplayPageCountAndCurrentLocation = true,
        MaximumPageNumbersToDisplay = 5,
    })

这里从查询字符串中判断并替换 page 值,如果有更简单的方法敬请告知。比如 Webdiyer 的分页组件会自动携带所有参数。


更多使用方式参官方文档:https://github.com/dncuug/X.PagedList


附应用于 Unify Template(一款基于 Bootstrap 的 HTML 模板)中的配置:

<style>
    .u-pagination-v1-1--active .u-pagination-v1-1 { color: #fff; border-color: #72c02c; }
    .PagedList-pageCountAndLocation { float: right !important; }
</style>
@{
    string query = Context.Request.QueryString.Value;
}
@Html.PagedListPager(Model, page => Regex.IsMatch(query, @"[?&]page=\d+")
    ? Regex.Replace(query, @"([?&])page=\d+", $"$1page={page}")
    : (query.StartsWith("?") ? $"{query}&page={page}" : $"{query}?page={page}"),
    new X.PagedList.Web.Common.PagedListRenderOptionsBase
    {
        DisplayPageCountAndCurrentLocation = true,
        MaximumPageNumbersToDisplay = 5,
        UlElementClasses = new string[] { "list-inline" },
        LiElementClasses = new string[] { "list-inline-item" },
        PageClasses = new string[] { "u-pagination-v1__item", "u-pagination-v1-1", "g-pa-7-14" },
        ActiveLiElementClass = "u-pagination-v1-1--active",
        EllipsesElementClass = "g-pa-7-14",
    })


xoyozo 5 年前
9,830

* 本文凡使用变量 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 5 年前
3,930

确保磁盘未满,否则会提示各种无法连接。


  1. 在“小米WiFi”App 中开启对应路由器的“SAMBA 协议”(工具箱 - 更多工具 - SAMBA)。

  2. 在“小米WiFi”App 中开启相应电脑或设备的“全盘访问”。

  3. 通过 miwifi.com 下载安装 PC 客户端。

  4. 打开“此电脑”,“映射网络驱动器”或“添加一个网络位置”,填写路由器的地址和目录,如:“\\192.168.31.1\下载”。

  5. 如果上一步无法成功添加,那么首先需要检查 samba 服务器是否正常,可以在 iPhone 上安装“Remote File Manager”来验证。

  6. 如果 iPhone 连接正常,那么在电脑上打开“本地组策略编辑器”(命令行:gpedit.msc),在“计算机配置 - 管理模板 - 网络 - Lanman 工作站”右侧,双击“启用不安全的来宾登录”,改为“已启用”。Win7 用户参考此文


注意:电脑必须运行 PC 客户端才能访问小米路由器硬盘。

xoyozo 5 年前
14,878

You could try using --skip-broken to work around the problem

……

curl-7.54.0-1.el7.centos.x86_64 is a duplicate with curl-7.29.0-35.el7.centos.x86_64


解决方法:

yum remove curl-7.29.0-35.el7.centos.x86_64

yum install curl

实测上面的方法无法安装 curl

xoyozo 5 年前
7,265

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 5 年前
16,279

完整操作步骤如下:

  1. 安装 NuGet 包:Microsoft.AspNet.Web.Optimization

  2. 打开 Views 目录(如果是应用于区域,则为区域的 Views 目录)中的 web.config,在 <namespaces /> 节点中添加

    <add namespace="System.Web.Optimization" />
  3. App_Start 目录中创建类文件 BundleConfig.cs,更改其命名空间为应用程序的默认命名空间(即移除 .App_Start),创建方法:

    public static void RegisterBundles(BundleCollection bundles)
    {
        bundles.Add(new StyleBundle("~/虚拟路径(不能有点)").Include("~/CSS文件路径"));
        bundles.Add(new ScriptBundle("~/虚拟路径(不能有点)").Include("~/JS文件路径"));
    }

    虚拟路径应避免与页面访问路径相同。Include 可包含多个文件,效果是合并输出,注意引用的顺序。

  4. 打开 Global.asax,在 Application_Start() 事件中添加代码

    BundleTable.EnableOptimizations = true; // 该设置使在开发模式中实现压缩代码,不设置则仅在发布后压缩代码
    BundleConfig.RegisterBundles(BundleTable.Bundles);
  5. 视图页面中引用样式表或脚本

    @Styles.Render("~/CSS虚拟路径")
    @Scripts.Render("~/JS虚拟路径")

    使用 Render 的好处是,ASP.NET 会自动给引用地址加上参数,可在更改脚本或样式表内容后更改这些参数使浏览器缓存立即失效。

如果你的项目中已经安装并使用 Bundle,那么只需要参考第 4 步,将 BundleTableEnableOptimixations 设为 true

以下是一些常见异常的解决方法:


The name 'Styles' does not exist in the current context

The name 'Scripts' does not exist in the current context

解决:参步骤 2。


引用的样式表或脚本不存在(报 404 错误)

解决:步骤 3 中的虚拟路径不规范。

xoyozo 6 年前
5,423

设置 CarPlay 车载

请按照以下步骤开始操作:

  1. 确保您所在的地区支持 CarPlay 车载,且您的汽车支持 CarPlay 车载

  2. 启动您的汽车,然后确保 Siri 已打开

  3. 将 iPhone 与汽车相连:

    • 如果您的汽车支持通过 USB 连接线连接 CarPlay 车载,请将您的 iPhone 插接到车内的 USB 端口。这类 USB 端口可能标有 CarPlay 车载图标或智能手机图标。

    • 如果您的汽车支持无线 CarPlay 车载,请按住方向盘上的语音命令按钮。确保您的立体声系统处于无线或蓝牙模式。然后,在您的 iPhone 上前往“设置”>“通用”>“CarPlay 车载”,轻点“可用的汽车”,然后选择您的汽车。请查看您的汽车使用手册,以了解更多信息。


A
转自 Apple 6 年前
6,856

原标题:关于 PHP 获取 IP 地址的几种方法


PHP 获取客户端的 IP 地址有 4 种方式:

  1. REMOTE_ADDR:浏览当前页面的用户计算机的 IP 地址

  2. HTTP_X_FORWARDED_FOR:记录代理信息,会把每一层代理都记录

  3. HTTP_CLIENT_IP:客户端的 IP

  4. X-Real-IP:没有标准,由上一跳决定


REMOTE_ADDR 一般是不能伪造的,因为是通过服务器与客户端握手协议来获取的。而 HTTP_X_FORWARDED_FOR 和 HTTP_CLIENT_IP 是在 header 信息里面,所以客户端是可以进行很轻松的伪造。下面是对这三种方式详解:

https://www.v2ex.com/t/230367

https://www.test404.com/post-1448.html

https://www.cnblogs.com/mypath/articles/5239687.html


一、关于 REMOTE_ADDR
这个变量获取到的是“直接来源”的 IP 地址,所谓“直接来源”指的是直接请求该地址的客户端 IP 。这个 IP 在单服务器的情况下,很准确的是客户端 IP ,无法伪造。当然并不是所有的程序都一定是单服务器,比如在采用负载均衡的情况(比如采用 haproxy 或者 nginx 进行负载均衡),这个 IP 就是转发机器的 IP ,因为过程是客户端 -> 负载均衡 -> 服务端。是由负载均衡直接访问的服务端而不是客户端。


二、关于 HTTP_X_FORWARDED_FOR 和 HTTP_CLIENT_IP
基于“一”,在负载均衡的情况下直接使用 REMOTE_ADDR 是无法获取客户端 IP 的,这就是一个问题,必须解决。于是就衍生出了负载均衡端将客户端 IP 加入到 HEAD 中发送给服务端,让服务端可以获取到客户端的真实 IP 。当然也就产生了各位所说的伪造,毕竟 HEAD 除了协议里固定的那几个数据,其他数据都是可自定义的。


三、为何网上找到获取客户端 IP 的代码都要依次获取 HTTP_CLIENT_IP 、 HTTP_X_FORWARDED_FOR 和 REMOTE_ADDR
基于“一”和“二”以及对程序通用性的考虑,所以才这样做。 假设你在程序里直接写死了 REMOTE_ADDR ,有一天你们的程序需要做负载均衡了,那么你有得改了。当然如果你想这么做也行,看个人爱好和应用场景。也可以封装一个只有 REMOTE_ADDR 的方法,等到需要的时候改这一个方法就行了。


X_FORWARDED_FOR 与 X-Real-IP 的区别:

X_FORWARDED_FOR:记录了所有链路里的代理 IP 值,比如下面所说的,经过了 3 次代理,分别是 1.1.1.1, 2.2.2.2, 3.3.3.3,其中 1.1.1.1 是客户端 IP,2.2.2.2 是代理服务器,接下来同理。

X-Real-IP:是只会记录前一次代理的 IP 地址。

一般来说,X-Forwarded-For是用于记录代理信息的,每经过一级代理(匿名代理除外),代理服务器都会把这次请求的来源IP追加在X-Forwarded-For

来自4.4.4.4的一个请求,header 包含这样一行

X-Forwarded-For: 1.1.1.1, 2.2.2.2, 3.3.3.3

代表请求由1.1.1.1发出,经过三层代理,第一层是2.2.2.2,第二层是3.3.3.3,而本次请求的来源IP4.4.4.4是第三层代理

X-Real-IP,没有相关标准,上面的例子,如果配置了X-Read-IP,可能会有两种情况

// 最后一跳是正向代理,可能会保留真实客户端IP
X-Real-IP: 1.1.1.1
// 最后一跳是反向代理,比如Nginx,一般会是与之直接连接的客户端IP
X-Real-IP: 3.3.3.3

所以 ,如果只有一层代理,这两个头的值就是一样的。

那一般在后端取值(比如 node.js 通过 nginx 代理)是用哪个值呢?我看 sf 上看一般推荐是用 X-Forwarded-For,直接用 X-Real-IP 岂不是更方便点?

X-Forwarded-For 确实是一般的做法

  1. 他在正向(如 squid)反向(如 nginx)代理中都是标准用法,而正向代理中是没有 x-real-ip 相关的标准的,也就是说,如果用户访问你的 nginx 反向代理之前,还经过了一层正向代理,你即使在 nginx 中配置了 x-real-ip,取到的也只是正向代理的 IP 而不是客户端真实 IP

  2. 大部分 nginx 反向代理配置文章中都没有推荐加上 x-real-ip ,而只有 x-forwarded-for,因此更通用的做法自然是取 x-forwarded-for

  3. 多级代理很少见,只有一级代理的情况下二者是等效的

  4. 如果有多级代理,x-forwarded-for 效果是大于 x-real-ip 的,可以记录完整的代理链路


1、将以下代码保存为 Client.php

// php 脚本开始
$ch = curl_init();
$url = "http://localhost/ser.php";
$header = array('CLIENT-IP:208.165.188.175', 'X-FORWARDED-FOR:208.165.188.175');
// 声明伪造 head 请求头
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
curl_setopt($ch, CURLOPT_RETURNTRANSFER,true);
$page_content = curl_exec($ch); curl_close($ch);
echo $page_content;


2、将以下代码保存为 ser.php

// php 脚本开始
echo getenv('HTTP_CLIENT_IP');
echo getenv('HTTP_X_FORWARDED_FOR');
echo getenv('REMOTE_ADDR');


测试结果为

208.165.188.175
208.165.188.175
127.0.0.1


上面结果可看出,http_client_ip、http_x_forwarded_for 都被伪造了,而 remote_addr 还是127.0.0.1 就是客户端 IP

总结:

如果我们没用到负载均衡(CDN)的话直接用 REMOTE_ADDR 获取 IP。

如果使用了一级 CDN 的话,CDN 会把 REMOTE_ADDR 转发成 X-Real-IP,我们服务器可以获取 X-Real-IP 来获取 IP 值。如果是多级 CDN 的话需要我们来做 nginx 代理,详细:https://www.cnblogs.com/princessd8251/articles/6268943.html

就是第一台负载服务器获取 REMOTE_ADDR 转发成 X-Real-IP,之后的去继承前一台的 X-Real-IP 就可以了,这里记住必须是去继承,不然第二台会把第一台的 REMOTE_ADDR 转发成 X-Real-IP 导致错误。

在 discuz! 中的获取 IP 的方法:

private function _get_client_ip() {
    $ip = $_SERVER['REMOTE_ADDR'];
    if (isset($_SERVER['HTTP_CLIENT_IP']) && preg_match('/^([0-9]{1,3}\.){3}[0-9]{1,3}$/', $_SERVER['HTTP_CLIENT_IP'])) {
        $ip = $_SERVER['HTTP_CLIENT_IP'];
    } elseif(isset($_SERVER['HTTP_X_FORWARDED_FOR']) AND preg_match_all('#\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}#s', $_SERVER['HTTP_X_FORWARDED_FOR'], $matches)) {
        foreach ($matches[0] AS $xip) {
            if (!preg_match('#^(10|172\.16|192\.168)\.#', $xip)) {
                $ip = $xip;
                break;
            }
        }
    }
    return $ip;
}

这里 DZ 为了符合有些用户会用代理,所以才首先使用了两个容易伪造的方法,如果有需要可以自行修改。

h
转自 hykeda 6 年前
6,829

场景:每天带笔记本电脑上班,公司使用固定 IP 上网,家里网络的网段又跟公司不一样。


方法 1:两个网络环境分别使用有线连接和无线连接(鉴于笔记本无线网卡不支持 5G(802.11ac),或者有其它需求必须都使用有线连接的不适用此方法)。

方法 2:修改家里路由器的局域网 IP 地址,使其网段与公司相同(虽然仅需要一次修改,但部分路由器不允许修改局域网 IP 地址);

方法 3:使用第三方软件一键切换(有安全隐患,且可能导致电脑网络设置出现错误);

方法 4(推荐):设置电脑网络连接同时使用两个 IP,具体方法如下:


打开“以太网 属性”,双击“Internet 协议版本 4 (TCP/IPv4)”,配置其中一个网络环境的 IP 地址和网关(例如我在公司上网的 IP 是 192.168.1.5,网关是 192.168.1.1)

image.png

点击“高级”,在 IP 地址栏添加另一个网络的 IP(如 192.168.31.5),在“默认网关”处添加这个网络的网关(如 192.168.31.1)

image.png

这样设置后,不管到公司还是回到家,只要网线一插就能上网,不需要每天更换 IP 地址设置了。

image.png

(图中显示了两个网络名称)

xoyozo 6 年前
6,959

spacedesk 是一款非常强大的虚拟投影软件,可以将其它电脑、苹果设备(iPhone、iPad)、安卓手机甚至 HTML5 浏览器作为第二屏幕。本文以一台笔记本的屏幕作为另一台笔记本的扩展记录安装配置过程。


主笔记本安装 spacedesk DRIVER

扩展笔记本安装 spacedesk VIEWER

从官方网站下载软件


为了保证屏幕最佳的显示效果,我们希望两台笔记本最终的显示分辨率与物理分辨率一致。

我的主笔记本分辨率 1920x1080,扩展笔记本分辨率 1366x768


主笔记本

首先在扩展笔记本中打开 spacedesk VIEWER,连接主笔记本。

在主笔记本,桌面右键“显示设置”,分别针对 1 和 2 显示器设置分辨率: 

image.png

image.png


当然还可以在上上图中的“重新排列显示器”中拖动来实现屏幕内容的显示位置。


扩展笔记本

打开 spacedesk VIEWER,在菜单的 Settings 中选择 Resolutions 可设置显示分辨率:

TIM图片20190327195919.jpg


选择 Compression Quality 可设置显示质量: 

TIM图片20190327195959.png


压缩(Compression)如果选择 Off,那得看你的电脑能否吃得消,否则显示效果会更卡。我的配置是压缩选择 On,颜色深度选择低,快速,质量 100,帧率选择 60 FPS:

TIM图片20190327200238.png


这样比默认设置的显示效果要好很多。

如果有条件用有线连接的话,尽量不要用无线连接,能减少不少延时。

xoyozo 6 年前
25,602