[C#]使用 C# 代码实现拓扑排序

 

0.参考资料

尊重他人的劳动成果,贴上参考的资料地址,本文仅作学习记录之用。

  1. https://www.codeproject.com/Articles/869059/Topological-sorting-in-Csharp
  2. https://songlee24.github.io/2015/05/07/topological-sorting/
  3. https://www.cnblogs.com/skywang12345/p/3711483.html

1.介绍

自己之前并没有接触过拓扑排序,顶多听说过拓扑图。在写前一篇文章的时候,看到 Abp 框架在处理模块依赖项的时候使用了拓扑排序,来确保顶级节点始终是最先进行加载的。第一次看到觉得很神奇,看了一下维基百科头也是略微大,自己的水平也是停留在冒泡排序的层次。ヽ(≧□≦)ノ

看了第二篇参考资料才大致了解,在此记录一下。

2.原理

先来一个基本定义:

在图论中,拓扑排序(Topological Sorting)是一个有向无环图(DAG, Directed Acyclic Graph)的所有顶点的线性序列。且该序列必须满足下面两个条件:

  1. 每个顶点出现且只出现一次。
  2. 若存在一条从顶点 A 到顶点 B 的路径,那么在序列中顶点 A 出现在顶点 B 的前面。

有向无环图(DAG)才有拓扑排序,非DAG图没有拓扑排序一说。

例如,有一个集合它的依赖关系如下图:

可以看到他有一个依赖关系:

  1. Module D 依赖于 Module E 与 Module B 。
  2. Module E 依赖于 Module B 与 Module C 。
  3. Module B 依赖于 Module A 与 Module C 。
  4. Module C 依赖于 Module A 。
  5. Module A 无依赖 。

这个就是一个 DAG 图,我们要得到它的拓扑排序,一个简单的步骤如下:

  1. 从 DAG 图中选择一个没有前驱的顶点并输出。
  2. 从 DAG 图中删除该顶点,以及以它为起点的有向边。
  3. 重复步骤 1、2 直到当前的 DAG 图为空,或者当前图不存在无前驱的顶点为止

按照以上步骤,我们来进行一个排序试试。

最后的排序结果就是:

Module D -> Module E -> Module B -> Module C -> Module A

emmmm,其实一个有向无环图可以有一个或者多个拓扑序列的,因为有的时候会存在一种情况,即以下这种情况:

这个时候你就可能会有这两种结果

D->E->B->C->F->A

D->E->B->F->C->A

因为 F 与 C 是平级的,他们初始化顺序即便不同也没有什么影响,因为他们的依赖层级是一致的,不过细心的朋友可能会发现这个顺序好像是反的,我们还需要将其再反转一次。

3.实现

上面这种方法仅适用于已知入度的时候,也就是说这些内容本身就是存在于一个有向无环图之中的,如果按照以上方法进行拓扑排序,你需要维护一个入度为 0 的队列,然后每次迭代移除入度为 0 顶点所指向的顶点入度。

例如有以下图:

按照我们之前的算法,

  1. 首先初始化队列,将 5 与 4 这两个入度为 0 的顶点加入队列当中。
  2. 执行 While 循环,条件是队列不为空。
  3. 之后首先拿出 4 。
  4. 然后针对其指向的顶点 0 与 顶点 1 的入度减去 1。
  5. 减去指向顶点入度的时候同时判断,被减去入度的顶点其值是否为 0 。
  6. 这里 1 入度被减去 1 ,为 0 ,添加到队列。
  7. 0 顶点入度减去 1 ,为 1。
  8. 队列现在有 5 与 1 这两个顶点,循环判断队列不为空。
  9. 5 指向的顶点 0 入度 减去 1,顶点 0 入度为 0 ,插入队列。

这样反复循环,最终队列全部清空,退出循环,得到拓扑排序的结果4, 5, 2, 0, 3, 1 。

4.深度优先搜索实现

在参考资料 1 的代码当中使用的是深度优先算法,它适用于有向无环图。

有以下有向环图 G2:

对上图 G2 进行深度优先遍历,首先从入度为 0 的顶点 A 开始遍历:

它的步骤如下:

  1. 访问 A 。

  2. 访问 B 。

  3. 访问 C 。

在访问了 B 后应该是访问 B 的另外一个顶点,这里可以是随机的也可以是有序的,具体取决于你存储的序列顺序,这里先访问 C 。

  1. 访问 E 。

  2. 访问 D 。

这里访问 D 是因为 B 已经被访问过了,所以访问顶点 D 。

  1. 访问 F 。

因为顶点 C 已经被访问过,所以应该回溯访问顶点 B 的另一个有向边指向的顶点 F 。

  1. 访问 G 。

因此最后的访问顺序就是 A -> B -> C -> E -> D -> F -> G ,注意顺序还是不太对哦。

看起来跟之前的方法差不多,实现当中,其 Sort() 方法内部包含一个 visited 字典,用于标记已经访问过的顶点,sorted 则是已经排序完成的集合列表。

在字典里 Key 是顶点的值,其 value 值用来标识是否已经访问完所有路径,为 true 则表示正在处理该顶点,为 false 则表示已经处理完成。

现在我们来写实现吧:

public static IList<T> Sort<T>(IEnumerable<T> source, Func<T, IEnumerable<T>> getDependencies)
{
    var sorted = new List<T>();
    var visited = new Dictionary<T, bool>();

    foreach (var item in source)
    {
        Visit(item, getDependencies, sorted, visited);
    }

    return sorted;
}

public static void Visit<T>(T item, Func<T, IEnumerable<T>> getDependencies, List<T> sorted, Dictionary<T, bool> visited)
{
    bool inProcess;
    var alreadyVisited = visited.TryGetValue(item, out inProcess);

    // 如果已经访问该顶点,则直接返回
    if (alreadyVisited)
    {
        // 如果处理的为当前节点,则说明存在循环引用
        if (inProcess)
        {
            throw new ArgumentException("Cyclic dependency found.");
        }
    }
    else
    {
        // 正在处理当前顶点
        visited[item] = true;

        // 获得所有依赖项
        var dependencies = getDependencies(item);
        // 如果依赖项集合不为空,遍历访问其依赖节点
        if (dependencies != null)
        {
            foreach (var dependency in dependencies)
            {
                // 递归遍历访问
                Visit(dependency, getDependencies, sorted, visited);
            }
        }

        // 处理完成置为 false
        visited[item] = false;
        sorted.Add(item);
    }
}

顶点定义:

// Item 定义
public class Item
{
    // 条目名称
    public string Name { get; private set; }
    // 依赖项
    public Item[] Dependencies { get; set; }

    public Item(string name, params Item[] dependencies)
    {
        Name = name;
        Dependencies = dependencies;
    }

    public override string ToString()
    {
        return Name;
    }
}

调用:

static void Main(string[] args)
{
    var moduleA = new Item("Module A");
    var moduleC = new Item("Module C", moduleA);
    var moduleB = new Item("Module B", moduleC);
    var moduleE = new Item("Module E", moduleB);
    var moduleD = new Item("Module D", moduleE);

    var unsorted = new[] { moduleE, moduleA, moduleD, moduleB, moduleC };

    var sorted = Sort(unsorted, x => x.Dependencies);

    foreach (var item in sorted)
    {
        Console.WriteLine(item.Name);
    }

    Console.ReadLine();
}

结果:

dotNet Core WEB程序使用 Nginx反向代理

 

之前记录过一篇 使用 jexus 作为dotNetCore的反向代理,发现jexus的内存占用较大,最终选择使用Nginx的原因就是占用内存较小(https://www.cnblogs.com/jhy55/p/9229933.html)

Jexux与 Nginx性能对比参考(https://www.aliyun.com/jiaocheng/202277.html


直入正题。。。。。。。。。。

Nginx 安装

安装所需环境

Nginx 是 C语言 开发,建议在 Linux 上运行,当然,也可以安装 Windows 版本,本篇则使用 CentOS 7 作为安装环境。

一. gcc 安装

安装 nginx 需要先将官网下载的源码进行编译,编译依赖 gcc 环境,如果没有 gcc 环境,则需要安装:

yum install gcc-c++

二. PCRE pcre-devel 安装

PCRE(Perl Compatible Regular Expressions) 是一个Perl库,包括 perl 兼容的正则表达式库。nginx 的 http 模块使用 pcre 来解析正则表达式,所以需要在 linux 上安装 pcre 库,pcre-devel 是使用 pcre 开发的一个二次开发库。nginx也需要此库。命令:

yum install -y pcre pcre-devel

三. zlib 安装

zlib 库提供了很多种压缩和解压缩的方式, nginx 使用 zlib 对 http 包的内容进行 gzip ,所以需要在 Centos 上安装 zlib 库。

yum install -y zlib zlib-devel

四. OpenSSL 安装

OpenSSL 是一个强大的安全套接字层密码库,囊括主要的密码算法、常用的密钥和证书封装管理功能及 SSL 协议,并提供丰富的应用程序供测试或其它目的使用。

nginx 不仅支持 http 协议,还支持 https(即在ssl协议上传输http),所以需要在 Centos 安装 OpenSSL 库。

yum install -y openssl openssl-devel

官网下载

1.直接下载.tar.gz安装包,地址:https://nginx.org/en/download.html

2.使用wget命令下载(推荐)。

wget -c https://nginx.org/download/nginx-1.14.0.tar.gz

我下载的是1.14.0版本,这个是目前的稳定版。

解压

依然是直接命令:

tar -zxvf nginx-1.14.0.tar.gz cd nginx-1.14.0

其实在 nginx-1.10.1 版本中你就不需要去配置相关东西,默认就可以了。当然,如果你要自己配置目录也是可以的。

1.使用默认配置

./configure

编译安装

make make install

查找安装路径:

whereis nginx

启动、停止nginx

cd /usr/local/nginx/sbin/ ./nginx ./nginx -s stop ./nginx -s quit ./nginx -s reload

./nginx -s quit:此方式停止步骤是待nginx进程处理任务完毕进行停止。

./nginx -s stop:此方式相当于先查出nginx进程id再使用kill命令强制杀掉进程。

查询nginx进程:

ps aux|grep nginx

重启 nginx

1.先停止再启动(推荐):

对 nginx 进行重启相当于先停止再启动,即先执行停止命令再执行启动命令。如下:

./nginx -s quit ./nginx

2.重新加载配置文件:

当 ngin x的配置文件 nginx.conf 修改后,要想让配置生效需要重启 nginx,使用-s reload不用先停止 ngin x再启动 nginx 即可将配置信息在 nginx 中生效,如下:

./nginx -s reload

启动成功后,在浏览器可以看到这样的页面:

添加到系统服务,开机自启动

vim /etc/init.d/nginx

添加内容如下

#!/bin/bash

#chkconfig:- 99 20

#description:Nginx Service Control Script

cmd='/usr/local/nginx/sbin/nginx'

pid='/usr/local/nginx/logs/nginx.pid'

case "$1" in

start)

$cmd

;;

stop)

kill -s QUIT $(cat $pid)

;;

restart)

$0 stop

$0 start

;;

reload)

kill -s HUP  $(cat $pid)

;;

*)

echo 'Usage:$0 {start|stop|restart|reload}'

exit 1

esac

exit 0

重启服务

service nginx restart

到这里nginx安装完成了

站点配置

HTTP配置代理

如果在 nginx.conf 文件中添加站点配置,多站点的情况下,不利于管理

多站点配置,需要启用这个配置,然后在conf.d文件夹下,创建多个配置文件即可。比如lotteryAdmin.conf、lotteryAPI.conf

新建文件夹

mkdir /usr/local/nginx/conf.d/

vim /usr/local/nginx/conf/nginx.conf

在尾部 http { }内添加

include /usr/local/nginx/conf.d/*.conf;

然后 :wq!保存

vim  /usr/local/nginx/conf.d/lotteryAdmin.conf

添加内容

server {

listen 80;

index /Main/index;

server_name admin1.lottery.com; #域名

location / {

# 传递真实IP到后端

proxy_set_header Host $http_host;

proxy_set_header X-Real-IP $remote_addr;

proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

proxy_pass  http://localhost:5001;#dotNetCore程序的端口号

}

}

然后 :wq!保存

重启 Nginx 服务

service nginx restart

查看Nginx配置是否正常

/usr/local/nginx/sbin/nginx -t

现在可以访问你的站点了

HTTPS配置代理

申请到证书之后,我这里有 xxx.key和xxx.pem两个文件

server {

listen 443;

server_name api.lottery.com;

ssl on;

index index.html index.htm;

ssl_certificate  /dotnet/httpsKey/cretc.pem;

ssl_certificate_key  /dotnet/httpsKey/cretc.key;

ssl_session_timeout 5m;

ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;

ssl_protocols TLSv1 TLSv1.1 TLSv1.2;

ssl_prefer_server_ciphers on;

location / {

proxy_set_header Host $http_host;

proxy_set_header X-Real-IP $remote_addr;

proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

proxy_pass  https://localhost:5003;#dotNetCore程序的端口号

}

}

按 :wq!保存

service nginx restart

如果报错

unknown directive "ssl"............

切换到你解压的nginx目录下

####### 下载你当前版本的nginx包,并且解压 进到目录

./configure --with-http_ssl_module

####### 切记千万不要make install 那样就覆盖安装了

make

####### 将原来的nginx备份 备份之前先kill当前正在启动的nginx

cp /usr/local/nginx/sbin/nginx /usr/local/nginx/sbin/nginx.bak

####### make之后会在当前目录生成 objs 目录

cp objs/nginx /usr/local/nginx/sbin/nginx

####### 然后重新启动nginx

/usr/local/nginx/sbin/nginx

在重启nginx服务

service nginx restart

这个时候可以访问你的站点了

C#里面获得应用程序的当前路径

 

在C#里面获得应用程序的当前路径

Environment.CurrentDirectory
System.IO.Directory.GetCurrentDirectory()

——上面两种获得的是当前路径,这个路径不一定是程序所在的路径。任何会改变当前路径的方法都会改变它,例如:OpenFileDialog每换一次目录就会改变它。因此,用这2个方法获取程序路径并不可靠。

AppDomain.CurrentDomain.BaseDirectory

AppDomain.CurrentDomain.SetupInformation.ApplicationBase
——这两个只能在WindowForm中使用;这两个方法是可靠的获取程序路径的方法。返回的路径最末以"\"结尾。可以方便的在后面加入任何Path。当然就算没有也可以用Path.Combine来合并路径以获得想要的路径。

Application.StartupPath

——这个方法也是可靠的获取程序路径的方法。不过返回的路径最末并没有"\"结尾。另外因为是Forms命名空间的。因此如果使用WPF还是不用的好。
Application.ExecutablePath
——这个方法获取的是执行程序的完整文件名。是最可靠的方式,只需要去掉程序文件名就可以获得路径。

关于Nginx设置端口号,在Asp.net 获取不到的,解决办法

 

不知道你有没有遇到过这样的问题,网站访客多起来后,心里很是高兴,加上了Nginx反向代理,出问题了

原来是这么写的:

Request.Url.ToString()

输出是这样的:

http://www.zhyj2013.com:6038/Default/Index

平白无故多出个端口号

Nginx是这样配置的

server {
        listen       80;
        server_name  www.zhyj2013.com;

        location / {
            root   html;
            index  index.html index.htm;
        proxy_pass  http://localhost:6038;
        proxy_set_header Host $http_host:$server_port;
        proxy_set_header X-Real-IP $remote_addr;
        }

        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }

    }

大家都是这样配置的,没有什么问题,网上也找不到Asp.Net解决问题的方法,最后我翻看了System.Web.dll  发现他读取appSetting节点 aspnet:UseHostHeaderForRequestUrl 子节点,于是,在项目的WebConfig加上配置,好了

<appSettings>
    <add key="aspnet:UseHostHeaderForRequestUrl" value="true"/>
</appSettings>

再刷新

输出是这样的:

http://www.zhyj2013.com/Default/Index

.Net程序员 初学Ubuntu ,配置Nignix

 

1、安装VM虚拟机

2、升级VI编辑器

3、安装Nginx

4、测试localhost

5、编辑配置文件


仅仅用了记录一个过程,不会太详细

1、安装虚拟机,网上一大片,不是特别难

2、为什么要升级VI编辑器?

vi相当于windows的记事本,但是习惯了windows的我,不会用,上下左右箭头都与平时不一样,查了很久的各种命令,找到一篇博文,地址如下:

解决Ubuntu中vi命令的编辑模式下不能正常使用方向键和退格键的问题

2.1、vi 的使用,在黑窗口里面输入  sudo vi filename   ,回车,根据提示输入密码,回车,这样就能看到文件的内容了,也是在当前黑窗看到的,跟windows很不一样

此时,是在命令行模式,不能编辑输入文字,一直回车知道自己想编辑的那一行,把光标移动到想要编辑的字符,

输入 i ,此时,进入插入模式,可以写文字了,不想写了,按下esc键,重回到了命令模式,此时也没有保存文件

如果想保存文件,在命令模式下输入 :w!  ,回车,就保存了,输入的时候,看黑窗的最下方。

如果想退出的话,可以输入 :q  ,就回到了打开之前的

参考的网址是:

[Linux/Ubuntu] vi/vim 使用方法讲解

Ubuntu vi 常用命令集合

3、安装niginx 是因为用到了一点点

打开黑窗口 输入,

sudo apt-get install nginx 按照提输入密码,最后没有报错就是安装完成了。

参考网站在虚拟机内打开浏览器,输入localhost应该能看到一个nginx的默认页面 

3.1、安装后,我找到了这么几个文件夹

/etc/nginx/  这个是主文件夹

/etc/nginx/nginx.conf  这是主配置文件,但是内容跟windows的时候,稍微有点不一样,server配置在

/etc/nginx/sites-available/default   这是主要的配置文件,我主要是在这里面修改了反向代理的配置

/var/www/http/index.nginx-debian.html  这是nginx的默认首页

4、测试,在上一步已经测试过了

5、编辑配置文件,这个是核心的,由于之前我在windows上简单的配置过,就使用第一步的vi编辑器做了配置,这里把我的文件内容贴下面,增加以下篇幅

server {
    listen 80 default_server;
    listen [::]:80 default_server;
    root /var/www/html;

    index index.html index.htm index.nginx-debian.html;

    server_name _;

    location / {
        # First attempt to serve request as file, then
        # as directory, then fall back to displaying a 404.
        try_files $uri $uri/ =404;
    }
    location /tydyxsk/ {
        proxy_pass http://www.tydyxsk.com/;
    }
    location /Site/ {
        proxy_pass http://www.tydyxsk.com/Site/;
    }
    location /attached/ {
        proxy_pass http://www.tydyxsk.com/attached/;
    }

}

只有后面的三个 location是我配置的,最终实现了如下效果:

输入http://localhost ,显示默认页面

输入http://localhost/tydyxsk/,显示太原德育新时空的主站

截图几张


作为一个老鸟,真的发现不学习就落后

夜深了,写了个JQuery的省市区三级级联效果

 

刚刚练手的JQuery,希望大神们指正

主要实现以下功能:

1、三级菜单级联加载数据

2、可以在不操作脚本的情况下,给元素加属性实现级联功能

3、自定义动态显示数据

咨询问题:

对于一般比较固定不变的数据,是不是应该生成静态的文件,直接加载整个数据文件,访问文件比较好?还是这样动态的访问比较好?

一般的数据文件,小的会在50k,大的会在3M

这个可以讨论下

  1 /**
  2 省市区县级联
  3 */
  4 (function($){
  5
  6     /*
  7     *
  8     *获取ele的相对元素
  9     *
 10     **/
 11     function CssFirstElement(ele, css) {
 12         ele = $(ele);
 13         if (!ele) {
 14             var event = event ? arguments[0] : window.event;
 15             ele = event.srcElement ? event.srcElement : event.target;
 16             ele = $(ele);
 17         }
 18         var targetInpage;
 19
 20         if ((typeof css == 'string') && css.constructor == String && css.substr(0, "css:#".length) == "css:#") {
 21             //以css:# 开头,是一个ID选择器
 22             targetInpage = $( $(css.substring(4))[0] );
 23         } else if ((typeof css == 'string') && css.constructor == String && css.substr(0, "css:".length) == "css:") {
 24             //以css: 开头,是一个基于元素的父级元素
 25             var css0 = css.substring(4);
 26             if (css0.split(' ').length==1) {
 27                 var parentCss = css0.substring(0, css0.indexOf(' '));
 28                 var eleCss = css0.substring(css0.indexOf(' ')).replace(/(^\s*)|(\s*$)/g, "");
 29                 targetInpage = ele.parents(eleCss + ":first");
 30             } else {
 31                 var parentCss = css0.substring(0, css0.indexOf(' '));
 32                 var eleCss = css0.substring(css0.indexOf(' ')).replace(/(^\s*)|(\s*$)/g, "");
 33                 targetInpage = ele.parents(parentCss+":first").find(eleCss);
 34             }
 35
 36         } else if ((typeof css == 'string') && css.constructor == String) {
 37             targetInpage = $(css);
 38         } else {
 39             //对象直接返回
 40             return [];
 41         }
 42
 43         return targetInpage.length > 0 ? $(targetInpage.get(0)) : [];
 44     }
 45     function SelectData(element) {
 46         this.element = element;//元素
 47         this.optionUrl = element.attr("data-optionUrl");//加载选项的url
 48         this.defaultValue = element.attr("data-defaultValue");//加载选项试的默认值
 49         this.display = element.attr("data-display");//返回对象的 option 显示的键
 50         this.value = element.attr("data-value");//返回对象的 option 绑定的键
 51         this.changeTarget = CssFirstElement(element, element.attr("data-changeTarget"));//元素选择改变后,触发目标元素重新加载选项
 52         this.showAll = element.attr("data-showAll");//是否显示全部选项
 53         this.immediately = element.attr("data-immediately");//是否立即加载选项
 54         this.param = element.attr("data-param");//请求时携带的参数
 55         //有需要触发改变选项的目标,就添加change事件,触发目标请求时,携带的参数
 56         if (this.changeTarget.length > 0) {
 57             this.element.on("change.selectDataFill",$.proxy(this.changeEvent,this));
 58         }
 59         this.element.data("SelectDataFillObj",this);
 60     }
 61     SelectData.prototype = {
 62         changeEvent: function () {
 63             this.changeTarget.attr("data-param",
 64                 this.element.get(0).name + "=" + this.element.get(0).value);
 65             this.changeTarget.data("SelectDataFillObj").empty();
 66
 67             var targetW=this.changeTarget;
 68             while (true) {
 69                 targetW = targetW.data("SelectDataFillObj").changeTarget;
 70                 if (targetW && targetW.length>0) {
 71                     targetW.data("SelectDataFillObj").empty();
 72                 } else {
 73                     break;
 74                 }
 75             }
 76             this.changeTarget.data("SelectDataFillObj").LoadData();
 77         },
 78         empty: function () {
 79             this.element.empty();
 80             if (this.showAll) {
 81                 $("<option value=\"\">全部</option>").appendTo(this.element);
 82             }
 83         },
 84         FillDataSuccess: function (data) {
 85             debugger;
 86             var element = this.element;
 87             this.empty();
 88
 89             for (var i = 0; i < data.list.length; i++) {
 90                 var item = data.list[i];
 91                 $("<option value=\"" + item[this.value] + "\" " +
 92                     (item[this.value] == this.defaultValue ? "selected" : "") + ">" +
 93                     item[this.display] + "</option>").appendTo(element);
 94             }
 95             if (this.element.val()!='') {
 96                 this.element.trigger("change.selectDataFill");
 97             }
 98         },
 99         LoadData: function () {
100             $.getJSON(this.optionUrl,this.element.attr("data-param")).success($.proxy(this.FillDataSuccess, this));
101         }
102     };
103     $.fn.SelectDataFill = function () {
104
105         this.each(function (index, element) {
106
107             var element = $(element);
108             var obj = new SelectData(element);
109             if (obj.immediately) {
110                 obj.LoadData();
111             }
112
113         });
114
115     }
116
117
118 })(jQuery);

应用:

 1 <td colspan="3">
 2     <select name="ProvinceId"
 3             data-optionUrl="/BasicPlugin/Area/ProvinceJson"
 4             data-defaultValue="3"
 5             data-display="Name"
 6             data-value="Id"
 7             data-changeTarget="css:td select[name=CityId]"
 8             data-showAll="true"
 9             data-immediately="true">
10         <option value="">请选择</option>
11     </select>
12     <select name="CityId"
13             data-optionUrl="/BasicPlugin/Area/CityJson"
14             data-defaultValue="1"
15             data-display="Name"
16             data-value="Id"
17             data-changeTarget="css:td select[name=DistrictId]"
18             data-showAll="true">
19         <option value="">请选择</option>
20     </select>
21     <select name="DistrictId"
22             data-optionUrl="/BasicPlugin/Area/DistrictJson"
23             data-defaultValue="1"
24             data-display="Name"
25             data-value="Id"
26             data-changeTarget="css:td select[name=StreetId]"
27             data-showAll="true">
28         <option value="">请选择</option>
29     </select>
30         <select name="StreetId"
31                 data-optionUrl="/BasicPlugin/Area/StreetJson"
32                 data-defaultValue="1"
33                 data-display="Name"
34                 data-value="Id"
35                 data-showAll="true">
36         <option value="">请选择</option>
37     </select>
38 </td> 

以上代码中的请求路径,如  /BasicPlugin/Area/StreetJson 返回的json格式为:

1 {
2     list:[
3         {ID:1,Name:"名称",Code:"001"},
4         {ID:1,Name:"名称",Code:"001"}
5     ]
6 }

效果如下:

一级选择改变,相关联的均重新加载数据,如果加载项中有默认值,则会选中默认值

暂时公开访问地址可以看到效果:

http://uiprogrammer.sxxxt.cn/Home/Index

[C#]使用 C# 代码实现拓扑排序 dotNet Core WEB程序使用 Nginx反向代理 C#里面获得应用程序的当前路径 关于Nginx设置端口号,在Asp.net 获取不到的,解决办法 .Net程序员 初学Ubuntu ,配置Nignix 夜深了,写了个JQuery的省市区三级级联效果的更多相关文章

  1. 2017-03-05 CentOS中配置守护服务(Supervisor)监听dotnet core web程序的运行

    我们继续解决上篇博客的问题,我这个人有个毛病,不喜欢遗留什么问题,也不喜欢问题说不明白,具体要怎么解决一定要详尽,因为经常自己遇到问题的时候,去翻别人的博客,就会遇到这样的问题,很苦恼,又说废话了. ...

  2. WebAPI中无法获取Session对象的解决办法

    在MVC的WebApi中默认是没有开启Session会话支持的.需要在Global中重写Init方法来指定会话需要支持的类型 public override void Init() { PostAut ...

  3. nginx反向代理docker registry报”blob upload unknown"解决办法

    问题症状:keepalived+nginx反向代理后端docker registry群集时,使用docker客户机向registry push镜像时出现 "blob upload unkno ...

  4. 2017-03-05 CentOS中结合Nginx部署dotnet core Web应用程序

    Visual Studio Live 倒计时2天,当然这是美国倒计时两天,中国应该是在3月8日的凌晨,正值"3.8妇女节".提前祝广大的女性同志节日快乐,当然还有奋斗在一线的程序媛 ...

  5. 14 微服务电商【黑马乐优商城】:day06-使用nginx反向代理并掌握cors解决跨域

    本项目的笔记和资料的Download,请点击这一句话自行获取. day01-springboot(理论篇) :day01-springboot(实践篇) day02-springcloud(理论篇一) ...

  6. Nginx反向代理、CORS、JSONP等跨域请求解决方法总结

    由于 Javascript 同源策略的存在使得一个源中加载来自其它源中资源的行为受到了限制.即会出现跨域请求禁止. 通俗一点说就是如果存在协议.域名.端口或者子域名不同服务端,或一者为IP地址,一者为 ...

  7. 前端通过Nginx反向代理解决跨域问题

    在前面写的一篇文章SpringMVC 跨域,我们探讨了什么是跨域问题以及SpringMVC怎么解决跨域问题,解决方式主要有如下三种方式: JSONP CORS WebSocket 可是这几种方式都是基 ...

  8. Nginx反向代理解决iframe跨域问题

    前言 这几天有个需求:做个表单页面,要求后台人员能自定义发布表单,用户来填写表单.我一想,这不麦克表单有现成的吗,拿来就用!发布表单后,可以选择使用iframe方式嵌入网站,一切顺利. 当时的网站是h ...

  9. nginx反向代理-解决前端跨域问题

    1.定义 跨域是指a页面想获取b页面资源,如果a.b页面的协议.域名.端口.子域名不同,所进行的访问行动都是跨域的,而浏览器为了安全问题一般都限制了跨域访问,也就是不允许跨域请求资源.注意:跨域限制访 ...

随机推荐

  1. SpringBoot jackson传入List引起的坑

    一.jackson无法解析value为[]的json 当入参为{xxxx1:[1,2,3],xxxx2:[obj1,obj2,obj3]}时,springmvn controller接收入参写为Lon ...

  2. Django模板遍历字典的方法

    使用Python + Django做Web开发时,有时需要在view中传递一个字典给模板(template),如何在模板中遍历字典呢? 下面介绍两种方法: views.py代码如下: dicts = ...

  3. maven打包加入依赖包以及加入本地依赖包的方法

    Maven引入本地Jar包并打包进War包中 1.概述 在平时的开发中,有一些Jar包因为种种原因,在Maven的中央仓库中没有收录,所以就要使用本地引入的方式加入进来. 2. 拷贝至项目根目录 项目 ...

  4. app_data中的数据库使用

    原文发布时间为:2008-07-24 -- 来源于本人的百度文章 [由搬家工具导入] ASP.NET中利用VWD操作数据库 建立本地数据库   你可以轻易地在Visual Studio的Web应用程序 ...

  5. 如果dom节点是动态添加进页面的,在页面节点绑定事件如何解决的问题。

    如果dom节点是动态添加进页面,想在节点绑定事件,传统的做法就是遍历节点,但会出现问题,也肯能有其他的办法,突然想到 可以依据事件冒泡,这样就不惧页面后添加节点而不响应事件的问题.比较结实.示例代码如 ...

  6. vue.js源码学习分享(七)

    var _Set; /* istanbul ignore if */ if (typeof Set !== 'undefined' && isNative(Set)) { // use ...

  7. js函数的四种调用方式以及对应的this指向

    一.函数调用,此时this是全局的也就是window 1 var c=function(){ 2 alert(this==window) 3 } 4 c()//true 二.方法调用 var myOb ...

  8. sync fsync fdatasync

    传统的UNIX实现在内核中设有缓冲区高速缓存或页面高速 缓存,大多数磁盘I/O都通过缓冲进行.当将数据写入文件时,内核通常先将该数据复制到其中一个缓冲区中,如果该缓冲区尚未写满,则并不将其排入输出队 ...

  9. kafka优化–JVM参数配置优化

    https://blog.csdn.net/u013063153/article/details/73826403

  10. Windows下php环境变量的配置

    1.找到php的路径比如"E:\php_env\PHP".    2.需要保证该目录下php.ini的配置是正确的,如果是刚下载的php包,则可能需要修改相应的一些配置:将php目 ...