ASP.NET: URI handling

后端 未结 6 2070
暗喜
暗喜 2021-01-06 05:53

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

I

相关标签:
6条回答
  • 2021-01-06 06:20

    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
    
    0 讨论(0)
  • 2021-01-06 06:25

    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 
    
    0 讨论(0)
  • 2021-01-06 06:26

    There's also the UriBuilder class

    0 讨论(0)
  • 2021-01-06 06:29

    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.

    0 讨论(0)
  • 2021-01-06 06:35

    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.

    0 讨论(0)
  • 2021-01-06 06:38

    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.

    0 讨论(0)
提交回复
热议问题