ASP.NET: URI handling

倾然丶 夕夏残阳落幕 提交于 2019-12-09 00:41:13

问题


I'm writing a method which, let's say, given 1 and hello should return http://something.com/?something=1&hello=en.

I could hack this together pretty easily, but what abstraction functionality does ASP.NET 3.5 provide for building URIs? I'd like something like:

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

I found the Uri class which sounds highly relevant, but I can't find anything which does the above really. Any ideas?

(For what it's worth, the order of the parameters doesn't matter to me.)


回答1:


Edited to correct massively incorrect code

Based on this answer to a similar question you could easily do something like:

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

This will also urlencode the collection, so:

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

Will output:

Something=1&hello=en%26that 



回答2:


As far I know nothing here. So everybody has its own implementation.

Example from 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();
    }

UPDATE:

You can also create extension method:

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;
}

And usage:

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

Please note that everything here is untested.




回答3:


Just combined answers=>

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();
    }
}

Half baked code. But should work well enough.




回答4:


There's also the UriBuilder class




回答5:


This is something that might appeal to you- recently at work I was looking at a way to "type" commonly used URL query string variables and so developed this interface:

   '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

You can then implement this interface to describe a query string parameter, such an implementation for your "Hello" param might look like this:

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

I developed a small (and very, very basic) class to help build URLs using these strongly typed parameters:

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:


Here's my version (needs .NET4 or a ToArray() call on the Select)

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

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

I thought the use of Dictionary might mean the items can get reordered, but that doesn't actually seem to be happening in experiments here - not sure what that's about.



来源:https://stackoverflow.com/questions/1748609/asp-net-uri-handling

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!