ASP.NET: обработка URI - PullRequest
       37

ASP.NET: обработка URI

4 голосов
/ 17 ноября 2009

Я пишу метод, который, скажем, с учетом 1 и hello должен вернуть 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, который звучит очень актуально, но я не могу найти ничего, что действительно делает вышеперечисленное. Есть идеи?

(Для чего это стоит, порядок параметров для меня не имеет значения.)

Ответы [ 6 ]

13 голосов
/ 17 ноября 2009

Отредактировано, чтобы исправить массово неверный код

На основании этого ответа на похожий вопрос вы можете легко сделать что-то вроде:

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 
4 голосов
/ 17 ноября 2009

Насколько я здесь ничего не знаю. Так что у каждого своя реализация.

Пример из 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:

Вы также можете создать метод расширения:

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");

Обратите внимание, что здесь все не проверено.

3 голосов
/ 01 декабря 2009

Просто комбинированные ответы =>

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

Полупеченный код. Но должно работать достаточно хорошо.

0 голосов
/ 17 июля 2010

Вот моя версия (требуется .NET4 или вызов ToArray () для выбора)

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

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

Я думал, что использование словаря может означать, что элементы могут быть переупорядочены, но на самом деле этого не происходит в экспериментах - не знаю, о чем это.

0 голосов
/ 17 ноября 2009

Это может вас заинтересовать - недавно на работе я искал способ «типизировать» часто используемые переменные строки запроса 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
0 голосов
/ 17 ноября 2009

Также есть UriBuilder класс

...