ASP.NET:URI 处理

Posted

技术标签:

【中文标题】ASP.NET:URI 处理【英文标题】:ASP.NET: URI handling 【发布时间】:2010-12-17 10:38:34 【问题描述】:

我正在编写一个方法,假设1hello 应该返回http://something.com/?something=1&hello=en

可以很容易地把它组合起来,但是 ASP.NET 3.5 为构建 URI 提供了哪些抽象功能?我想要类似的东西:

URI uri = new URI("~/Hello.aspx"); // E.g. ResolveUrl is used here
uri.QueryString.Set("something", "1");
uri.QueryString.Set("hello", "en");
return uri.ToString(); // /Hello.aspx?something=1&hello=en

我发现Uri 类听起来非常相关,但我找不到任何能真正做到上述内容的东西。有什么想法吗?

(对于它的价值,参数的顺序对我来说并不重要。)

【问题讨论】:

【参考方案1】:

已编辑以更正大量不正确的代码

基于this answer 类似的问题,您可以轻松地执行以下操作:

UriBuilder ub = new UriBuilder();

// You might want to take more care here, and set the host, scheme and port too
ub.Path = ResolveUrl("~/hello.aspx"); // Assumes we're on a page or control.

// Using var gets around internal nature of HttpValueCollection
var coll = HttpUtility.ParseQueryString(string.Empty);

coll["something"] = "1";
coll["hello"] = "en";

ub.Query = coll.ToString();
return ub.ToString();
// This returned the following on the VS development server:
// http://localhost/Hello.aspx?something=1&hello=en

这也会对集合进行urlencode,所以:

coll["Something"] = "1";
coll["hello"] = "en&that";

将输出:

Something=1&hello=en%26that 

【讨论】:

HttpValueCollection 在内部时如何创建? @Sly - 嗯,你是对的,我的 Uri 对象和查询属性的大小写都错误,所以它显然不是来自正确的代码 - 抱歉- 我现在就更新。 在上面的例子中,变量'uri'应该重命名为'uriBuilder'。这是一个陷阱。 而如果需要在查询字符串前拼接部分,可以使用***.com/a/23399048/3481183【参考方案2】:

到目前为止,我对此一无所知。所以每个人都有自己的实现。

来自LinqToTwitter 的示例。

    internal static string BuildQueryString(IEnumerable<KeyValuePair<string, string>> parameters)
    
        if (parameters == null)
        
            throw new ArgumentNullException("parameters");
        

        StringBuilder builder = new StringBuilder();
        foreach (var pair in parameters.Where(p => !string.IsNullOrEmpty(p.Value)))
        
            if (builder.Length > 0)
            
                builder.Append("&");
            

            builder.Append(Uri.EscapeDataString(pair.Key));
            builder.Append("=");
            builder.Append(Uri.EscapeDataString(pair.Value));
        

        return builder.ToString();
    

更新:

你也可以创建扩展方法:

public static UriBuilder AddArgument(this UriBuilder builder, string key, string value)

 #region Contract

 Contract.Requires(builder != null);
 Contract.Requires(key != null);
 Contract.Requires(value != null);

 #endregion

 var query = builder.Query;

 if (query.Length > 0)
 
      query = query.Substring(1) + "&";
  

 query += Uri.EscapeDataString(key) + "="
      + Uri.EscapeDataString(value);

 builder.Query = query;

 return builder;

及用法:

var b = new UriBuilder();
b.AddArgument("test", "test");

请注意,这里的所有内容都未经测试。

【讨论】:

我必须同意;我认为 ASP.NET 中没有任何公开暴露的东西来构建这样的 URI,这似乎是一种疏忽。 +1 表示扩展方法 - 但是可能会调用它“AddQuery”,然后如果需要,您可以使用相反的“RemoveQuery”。【参考方案3】:

只是合并答案=>

public static class UriBuilderExtensions

    public static void AddQueryArgument(this UriBuilder b, string key, string value)
    
        key = Uri.EscapeDataString(key);
        value = Uri.EscapeDataString(value);

        var x = HttpUtility.ParseQueryString(b.Query);
        if (x.AllKeys.Contains(key)) throw new ArgumentNullException
                ("Key '0' already exists!".FormatWith(key));
        x.Add(key, value);
        b.Query = x.ToString();
    

    public static void EditQueryArgument(this UriBuilder b, string key, string value)
    
        key = Uri.EscapeDataString(key);
        value = Uri.EscapeDataString(value);

        var x = HttpUtility.ParseQueryString(b.Query);
        if (x.AllKeys.Contains(key))
            x[key] = value;
        else throw new ArgumentNullException
                ("Key '0' does not exists!".FormatWith(key));
        b.Query = x.ToString();
    

    public static void AddOrEditQueryArgument(this UriBuilder b, string key, string value)
    
        key = Uri.EscapeDataString(key);
        value = Uri.EscapeDataString(value);

        var x = HttpUtility.ParseQueryString(b.Query);
        if (x.AllKeys.Contains(key))
            x[key] = value;
        else
            x.Add(key, value);
        b.Query = x.ToString();
    

    public static void DeleteQueryArgument(this UriBuilder b, string key)
    
        key = Uri.EscapeDataString(key);
        var x = HttpUtility.ParseQueryString(b.Query);
        if (x.AllKeys.Contains(key))
            x.Remove(key);
        b.Query = x.ToString();
    

半生不熟的代码。但应该工作得很好。

【讨论】:

它坏了。例如,AddOrEditQueryArgument 将两次转义参数值。 @driAn 可能是这样。无论如何- 会离开。仍然可能有帮助。【参考方案4】:

还有UriBuilder 类

【讨论】:

检查了,但似乎没有多大帮助。 虽然 UriBuilder.Query 是一个字符串,所以无论如何你都必须使用 String.Format 或 StringBuilder【参考方案5】:

这可能会吸引你——最近在工作中,我正在寻找一种“键入”常用 URL 查询字符串变量的方法,因此开发了这个接口:

   'Represent a named parameter that is passed from page-to-page via a range of methods- query strings, HTTP contexts, cookies, session, etc.
Public Interface INamedParam

    'A key that uniquely identfies this parameter in any HTTP value collection (query string, context, session, etc.)
    ReadOnly Property Key() As String

    'The default value of the paramter.
    ReadOnly Property DefaultValue() As Object

End Interface

然后您可以实现此接口来描述查询字符串参数,您的“Hello”参数的这种实现可能如下所示:

Public Class HelloParam
    Implements INamedParam

    Public ReadOnly Property DefaultValue() As Object Implements INamedParam.DefaultValue
        Get
            Return "0"
        End Get
    End Property

    Public ReadOnly Property Key() As String Implements INamedParam.Key
        Get
            Return "hello"
        End Get
    End Property
End Class

我开发了一个小型(并且非常非常基本)类来帮助使用这些强类型参数构建 URL:

Public Class ParametrizedHttpUrlBuilder

    Private _RelativePath As String
    Private _QueryString As String

    Sub New(ByVal relativePath As String)
        _RelativePath = relativePath
        _QueryString = ""
    End Sub

    Public Sub AddQueryParameterValue(ByVal param As INamedParam, ByVal value As Object)
        Dim sb As New Text.StringBuilder(30)
        If _QueryString.Length > 0 Then
            sb.Append("&")
        End If
        sb.AppendFormat("0=1", param.Key, value.ToString())
        _QueryString &= sb.ToString()
    End Sub

    Public Property RelativePath() As String
        Get
            Return _RelativePath
        End Get
        Set(ByVal value As String)
            If value Is Nothing Then
                _RelativePath = ""
            End If
            _RelativePath = value
        End Set
    End Property

    Public ReadOnly Property Query() As String
        Get
            Return _QueryString
        End Get
    End Property

    Public ReadOnly Property PathAndQuery() As String
        Get
            Return _RelativePath & "?" & _QueryString
        End Get
    End Property

End Class

【讨论】:

【参考方案6】:

这是我的版本(需要 .NET4 或在 Select 上调用 ToArray())

var items = new Dictionary<string,string>   "Name", "Will" ,  "Age", "99" ;

String query = String.Join("&", items.Select(i => String.Concat(i.Key, "=", i.Value)));

我认为使用 Dictionary 可能意味着项目可以重新排序,但这实际上似乎并没有在这里的实验中发生 - 不确定这是关于什么的。

【讨论】:

以上是关于ASP.NET:URI 处理的主要内容,如果未能解决你的问题,请参考以下文章

ASP.NET MVC OutputCache 不适用于根 URI

具有固定 URI 的 ASP.NET 路由不映射查询字符串参数

如何在 ASP.NET 中获取根域 URI?

错误:redirect_uri_mismatch (ASP.NET MVC)

ASP.Net - Google Calendar API V3 redirect_uri_mismatch 错误

ASP.NET MVC C# Google Drive API 重定向不匹配 URI