URI Comparer忽略查询字符串顺序

时间:2017-06-25 22:50:31

标签: c# .net powershell uri query-string

可以使用System.Uri.Compare比较两个URI 但是,将http://example.com/pages?pageStart=100&pageSize=50http://example.com/pages?pageSize=50&pageStart=100进行比较表示两个URI不同。有没有办法让比较忽略值在查询字符串中出现的顺序;从功能上讲,这两个URI是相同的。

我正在考虑编写一个包装器方法,在调用标准比较函数之前按顺序放置查询字符串参数,但是想先检查是否有开箱即用的解决方案,因为它似乎很奇怪比较将不具备此选项。

更新

这是我用来比较两个URI的解决方案,无论是或者它们的查询字符串参数顺序。如上所述,这是通过首先对每个URI的查询字符串进行排序来实现的。但是,如果在.net中存在现有解决方案,我宁可放弃我的代码和放大器。用那个。

function CompareUri ($GivenUri, $ShouldBeUri) {
    $uriComponentsOptions = ([UriComponents]::AbsoluteUri)
    $uriFormatOptions = ([UriFormat]::SafeUnescaped)
    $stringComparisonOptions = ([StringComparison]::OrdinalIgnoreCase)
    $a = OrderUriQueryString($GivenUri)
    $b = OrderUriQueryString($ShouldBeUri)
    [Uri]::Compare($a, $b, $uriComponentsOptions, $uriFormatOptions, $stringComparisonOptions)
}

function OrderUriQueryString($Uri) {
    [System.UriBuilder]$UriBuilder = New-Object -TypeName 'System.UriBuilder' -ArgumentList $Uri
    [System.Collections.Specialized.NameValueCollection]$Query = [System.Web.HttpUtility]::ParseQueryString($UriBuilder.Query)
    [System.Collections.Specialized.NameValueCollection]$Query2 = [System.Web.HttpUtility]::ParseQueryString('') #we have to initialise this way as HttpValueCollection has no public constructor (https://referencesource.microsoft.com/#system.web/HttpValueCollection.cs,fde6b9ec5f1ed58a,references)  
    $Query.AllKeys | sort | %{ $Query2.Add($_, $Query[$_]) }
    $UriBuilder.Query = $Query2.ToString()
    $UriBuilder.ToString()
}

2 个答案:

答案 0 :(得分:1)

我知道这与您所做的基本相同,但如果您真的只是希望比较在代码中看起来更简洁,则可以使用System.Uri修改Update-TypeData类型并使用它代替两个单独的功能。它不是原生的.NET,基本上使用的是相同的代码,但至少比较的调用看起来更清晰。

Update-TypeData -MemberType "ScriptMethod" -MemberName "SortedQueryStringCompare" -TypeName "System.Uri" -ErrorAction "SilentlyContinue" -Value {
    Param (
        [System.URI]$ComparingURI
    )

    $Sorter = {
        $UriBuilder = [System.UriBuilder]$args[0]

        $UnsortedQuery = [System.Web.HttpUtility]::ParseQueryString($UriBuilder.Query)
        $SortedQuery = [System.Web.HttpUtility]::ParseQueryString([String]::Empty)
        $UnsortedQuery.AllKeys | Sort-Object | ForEach-Object { 
            $SortedQuery.Add($_, $UnsortedQuery[$_])
        }

        $UriBuilder.Query = $SortedQuery.ToString()
        return $UriBuilder.ToString()
    }

    $UriComponentsOptions = ([UriComponents]::AbsoluteUri)
    $UriFormatOptions = ([UriFormat]::SafeUnescaped)
    $StringComparisonOptions = ([StringComparison]::OrdinalIgnoreCase)
    $OriginUriString = . $Sorter $This
    $ComparingUriString = . $Sorter $ComparingURI

    return [System.Uri]::Compare($OriginUriString,
                                 $ComparingUriString,
                                 $UriComponentsOptions,
                                 $UriFormatOptions,
                                 $StringComparisonOptions)
}

$e1 = [System.Uri]"http://example.com/pages?pageStart=100&pageSize=50"
$e2 = [System.Uri]"http://example.com/pages?pageSize=50&pageStart=100"

$e1.SortedQueryStringCompare($e2)

或者只是使用SortQueryString方法执行此操作,并将其用于调用Compare

Update-TypeData -MemberType "ScriptMethod" -MemberName "SortQueryString" -TypeName "System.Uri" -ErrorAction "SilentlyContinue" -Value {
    $UriBuilder = [System.UriBuilder]$this

    $UnsortedQuery = [System.Web.HttpUtility]::ParseQueryString($UriBuilder.Query)
    $SortedQuery = [System.Web.HttpUtility]::ParseQueryString([String]::Empty)
    $UnsortedQuery.AllKeys | Sort-Object | ForEach-Object { 
        $SortedQuery.Add($_, $UnsortedQuery[$_])
    }

    $UriBuilder.Query = $SortedQuery.ToString()
    return [System.Uri]$UriBuilder.ToString()
}

$UriComponentsOptions = ([UriComponents]::AbsoluteUri)
$UriFormatOptions = ([UriFormat]::SafeUnescaped)
$StringComparisonOptions = ([StringComparison]::OrdinalIgnoreCase)

$e1 = [System.Uri]"http://example.com/pages?pageStart=100&pageSize=50"
$e2 = [System.Uri]"http://example.com/pages?pageSize=50&pageStart=100"

[System.Uri]::Compare($e1.SortQueryString(), 
                      $e2.SortQueryString(), 
                      $UriComponentsOptions, 
                      $UriFormatOptions, 
                      $StringComparisonOptions)

答案 1 :(得分:0)

可能是查询参数的有序哈希表

$queryURI = http://example.com/pages?

$Parameters = [ordered] @{
            startsize = $startsize
            pagesize = $pagesize

        }

然后使用给定参数构建查询

foreach ($item in $Parameters.GetEnumerator())
        {

            if ($item.value -ne $null)
            {

                $query = [System.Web.HttpUtility]::ParseQueryString($uriBuilder.Query)
                $query[$item.key] = $item.Value

                $uriBuilder = [System.UriBuilder]::new($queryURI)
                $uriBuilder.Query = $query.ToString()
                $queryURI = $uriBuilder.ToString()
            }



        }

这是一个完整的例子

$QueryURI = 'http://example.com/pages?'


Function Get-MyQueryURL
{
    #takes 2 params 
    [CmdletBinding()]
    Param (
        [Parameter(Mandatory = $false,
                   ValueFromPipeline = $true,
                   ValueFromPipelineByPropertyName = $true)]
        [String[]]$startsize,
        [String[]]$pagesize



    ) #end param 

    Begin { }
    process
    {

        $Parameters = [ordered] @{
            startsize = $startsize
            pagesize = $pagesize
        }




        foreach ($item in $Parameters.GetEnumerator())
        {

            if ($item.value -ne $null)
            {

                $query = [System.Web.HttpUtility]::ParseQueryString($uriBuilder.Query)
                $query[$item.key] = $item.Value

                $uriBuilder = [System.UriBuilder]::new($QueryURI)
                $uriBuilder.Query = $query.ToString()
                $QueryURI = $uriBuilder.ToString()
            }



        }
            Write-Host $QueryURI
    }
}

具有以下结果:查询字符串是有序的

PS C:\Scripts> Get-MyQueryURL -startsize 100 -pagesize 50
http://example.com:80/pages?startsize=100&pagesize=50

PS C:\Scripts> Get-MyQueryURL -pagesize 50 -startsize 100
http://example.com:80/pages?startsize=100&pagesize=50