自制一个可编辑QueryString的类URLModifier
Posted 启天
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了自制一个可编辑QueryString的类URLModifier相关的知识,希望对你有一定的参考价值。
有些情况下,需要 新增/删除/替换 url中的部分Querystring中的参数,而.net自带的Uri类只能解析,不能编辑,,并且如果是Relative类型的链接,转成Uri类型之后,很多参数又不能很好的读取,因此,,,自己动手,丰衣足食,,大家不用复制文内的代码,,,文章最后,给出完整的类的代码链接,,有需要的,直接复制就行了
使用的场景如:
当前request的url= https://www.xxx.com/doc/base/infrastructure.html?categoryid=5&order=2&state=2u#topoop
在前端razor输出的时候,需要保留order和state的情况下.修改categoryid值:
@{ var requestUrlModifier = ViewContext.HttpContext.Request.GetDisplayUrl().ToUrlModifier(); } @foreach (var category in Model.Categories) { <a href="@requestUrlModifier.Clone().ReplaceQuery("categoryID", category.CategoryID.ToStringEx()).ToString()"></a> }
首先明确这个工具类的几个作用
1,可 新增/删除/替换 链接中的QueryString 中的各个keyvalue
2.可 替换/设置/保留 锚点anchor
3.对原有的Host/端口/协议/路径 保留原有值
4.最后可输出编辑后的结果
5.对不太标准的Url或部分有问题的QueryString支持
测试主要以下两种Url:
1.https://www.layui.com/doc/base/infrastructure.html?=&o==ppp&&pppp=iii&o1=ooo&test2=&u#topoop
这个链接QueryString中,除了正常的KeyValue对之外,,还有出现:
1) =& 开头的无效字符
2) o==ppp 中间包含两个==号的错误连续
3) &&pppp=iii 出现 && 两个连续字符
4) test2=& 这样的只有key,没有value
5) &u 这样的只有key,连等号都没有的
6) #topoop 链接后的锚点
2.https://www.layui.com/doc/base/infrastructure.html?=&o==ppp&&pppp=iii&o1=ooo&test2=&
1) 链接最后以 & 结尾
3. /doc/base/infrastructure.html?=&o==ppp&&pppp=iii&o1=ooo&test2=&u#topoop
1) 链接以 / 开头的相对链接,不包含域名信息和端口等信息
如果还有其他情况,可以留言,增加测试用例
由于该类在实际使用过程中,可能会频繁被调用,因此,需要尽量少的消耗资源,尽量少的变量定义
处理的流程主要分以下几个步骤:
1.从后往前,计算出是否包含锚点,并计算锚点所在的index1
2.从前往后,计算出?号所在index2
3.截取出从0到index2的所有字符
4.从index2到锚点index1之间的字符串就是QueryString了
5.循环判断QueryString的起始和结束index,为了去掉前后的无效字符
6.循环获取=和&号的位置,切分字符串
到此,完成对Url字符串的解析,,这里为什么不用正则表达式呢,,,因为第一慢,第二闲,,没事自己写,省事省空间
接下来就上代码了,,每个处理步骤,请看代码的注释文字
1.在构造函数中,对传入的Url进行解析操作
private string _anchor = string.Empty; private string _hostAndPath =string.Empty; private List<(string key, string value)> _queryKeys = new List<(string key, string value)>(5); public UrlModifier(string url) //直接传入string,不用uri,省的相对路径下,Uri类在读取Query属性的之后报错 { if (string.IsNullOrWhiteSpace(url)) { return; } var endIndex = url.Length - 1; //从后往前扫描锚点# for (int i = url.Length-1; i >= 0; i--) { if (url[i]==‘#‘) { _anchor = url.Substring(i+1); endIndex = i - 1; break; } //防止出现无#字符的情况 if (url[i] == ‘=‘ || url[i] == ‘&‘ || url[i] == ‘ ‘ || url[i] == ‘?‘ || url[i]==‘/‘) { endIndex = url.Length-1; break; } } //截取域名段,包含协议,端口号等 var hostEndIndex = endIndex; for (int i = 0; i < endIndex; i++) { if (url[i]==‘?‘) //查找?号所在index { hostEndIndex = i - 1; } } if (hostEndIndex>0) //如果是绝对路径的,获取Host和Path的字符串 {
if(url[hostEndIndex]==‘?‘)
{
_hostAndPath=url.Substring(0,hostEndIndex);
}
else
{
_hostAndPath=url.Substring(0,hostEndIndex+1);
} hostEndIndex++; } if (hostEndIndex >0 && hostEndIndex < endIndex) { //排除掉使用=号或者&或者空格结尾的字符,减少后续判断的麻烦,计算出实际的结束index for (int i = endIndex; i >= hostEndIndex; i--) { var c = url[i]; if (c != ‘=‘ && c != ‘&‘ && c != ‘ ‘) { endIndex = i; break; } } var keyword = ""; var value = ""; var startIndex = 1; char lastKeyword =‘