Skip to content
This repository was archived by the owner on Nov 20, 2018. It is now read-only.

Commit 02aa1c5

Browse files
committed
#28 - Add Helper for building Uris.
1 parent 5696f3f commit 02aa1c5

File tree

3 files changed

+243
-0
lines changed

3 files changed

+243
-0
lines changed
Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
2+
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
3+
4+
using System;
5+
6+
namespace Microsoft.AspNet.Http
7+
{
8+
/// <summary>
9+
/// Provides correct handling for FragmentString value when needed to generate a URI string
10+
/// </summary>
11+
public struct FragmentString : IEquatable<FragmentString>
12+
{
13+
/// <summary>
14+
/// Represents the empty fragment string. This field is read-only.
15+
/// </summary>
16+
public static readonly FragmentString Empty = new FragmentString(string.Empty);
17+
18+
private readonly string _value;
19+
20+
/// <summary>
21+
/// Initialize the fragment string with a given value. This value must be in escaped and delimited format with
22+
/// a leading '#' character.
23+
/// </summary>
24+
/// <param name="value">The fragment string to be assigned to the Value property.</param>
25+
public FragmentString(string value)
26+
{
27+
if (!string.IsNullOrEmpty(value) && value[0] != '#')
28+
{
29+
throw new ArgumentException("The leading '#' must be included for a non-empty fragment.", "value");
30+
}
31+
_value = value;
32+
}
33+
34+
/// <summary>
35+
/// The escaped fragment string with the leading '#' character
36+
/// </summary>
37+
public string Value
38+
{
39+
get { return _value; }
40+
}
41+
42+
/// <summary>
43+
/// True if the fragment string is not empty
44+
/// </summary>
45+
public bool HasValue
46+
{
47+
get { return !string.IsNullOrEmpty(_value); }
48+
}
49+
50+
/// <summary>
51+
/// Provides the fragment string escaped in a way which is correct for combining into the URI representation.
52+
/// A leading '#' character will be included unless the Value is null or empty. Characters which are potentially
53+
/// dangerous are escaped.
54+
/// </summary>
55+
/// <returns>The fragment string value</returns>
56+
public override string ToString()
57+
{
58+
return ToUriComponent();
59+
}
60+
61+
/// <summary>
62+
/// Provides the fragment string escaped in a way which is correct for combining into the URI representation.
63+
/// A leading '#' character will be included unless the Value is null or empty. Characters which are potentially
64+
/// dangerous are escaped.
65+
/// </summary>
66+
/// <returns>The fragment string value</returns>
67+
public string ToUriComponent()
68+
{
69+
// Escape things properly so System.Uri doesn't mis-interpret the data.
70+
return HasValue ? _value : string.Empty;
71+
}
72+
73+
/// <summary>
74+
/// Returns an FragmentString given the fragment as it is escaped in the URI format. The string MUST NOT contain any
75+
/// value that is not a fragment.
76+
/// </summary>
77+
/// <param name="uriComponent">The escaped fragment as it appears in the URI format.</param>
78+
/// <returns>The resulting FragmentString</returns>
79+
public static FragmentString FromUriComponent(string uriComponent)
80+
{
81+
if (String.IsNullOrEmpty(uriComponent))
82+
{
83+
return Empty;
84+
}
85+
return new FragmentString(uriComponent);
86+
}
87+
88+
/// <summary>
89+
/// Returns an FragmentString given the fragment as from a Uri object. Relative Uri objects are not supported.
90+
/// </summary>
91+
/// <param name="uri">The Uri object</param>
92+
/// <returns>The resulting FragmentString</returns>
93+
public static FragmentString FromUriComponent(Uri uri)
94+
{
95+
if (uri == null)
96+
{
97+
throw new ArgumentNullException("uri");
98+
}
99+
string fragmentValue = uri.GetComponents(UriComponents.Fragment, UriFormat.UriEscaped);
100+
if (!string.IsNullOrEmpty(fragmentValue))
101+
{
102+
fragmentValue = "#" + fragmentValue;
103+
}
104+
return new FragmentString(fragmentValue);
105+
}
106+
107+
public bool Equals(FragmentString other)
108+
{
109+
return string.Equals(_value, other._value);
110+
}
111+
112+
public override bool Equals(object obj)
113+
{
114+
if (ReferenceEquals(null, obj))
115+
{
116+
return false;
117+
}
118+
return obj is FragmentString && Equals((FragmentString)obj);
119+
}
120+
121+
public override int GetHashCode()
122+
{
123+
return (_value != null ? _value.GetHashCode() : 0);
124+
}
125+
126+
public static bool operator ==(FragmentString left, FragmentString right)
127+
{
128+
return left.Equals(right);
129+
}
130+
131+
public static bool operator !=(FragmentString left, FragmentString right)
132+
{
133+
return !left.Equals(right);
134+
}
135+
}
136+
}

src/Microsoft.AspNet.Http/HostString.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,11 @@ public string Value
3333
get { return _value; }
3434
}
3535

36+
public bool HasValue
37+
{
38+
get { return !string.IsNullOrEmpty(_value); }
39+
}
40+
3641
/// <summary>
3742
/// Returns the value as normalized by ToUriComponent().
3843
/// </summary>
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
using System;
2+
using Microsoft.AspNet.Http;
3+
4+
namespace Microsoft.AspNet.WebUtilities
5+
{
6+
/// <summary>
7+
/// A helper class for constructing encoded Uris for use in headers and other Uris.
8+
/// </summary>
9+
public class UriHelper
10+
{
11+
public UriHelper()
12+
{
13+
}
14+
15+
public UriHelper(HttpRequest request)
16+
{
17+
Scheme = request.Scheme;
18+
Host = request.Host;
19+
PathBase = request.PathBase;
20+
Path = request.Path;
21+
Query = request.QueryString;
22+
// Fragment is not a valid request field.
23+
}
24+
25+
public UriHelper(Uri uri)
26+
{
27+
Scheme = uri.Scheme;
28+
Host = HostString.FromUriComponent(uri);
29+
// Assume nothing is being put in PathBase
30+
Path = PathString.FromUriComponent(uri);
31+
Query = QueryString.FromUriComponent(uri);
32+
Fragment = FragmentString.FromUriComponent(uri);
33+
}
34+
35+
public string Scheme { get; set; }
36+
37+
public HostString Host { get; set; }
38+
39+
public PathString PathBase { get; set; }
40+
41+
public PathString Path { get; set; }
42+
43+
public QueryString Query { get; set; }
44+
45+
public FragmentString Fragment { get; set; }
46+
47+
// Always returns at least '/'
48+
public string GetPartialUri()
49+
{
50+
string path = (PathBase.HasValue || Path.HasValue) ? (PathBase + Path).ToString() : "/";
51+
return path + Query + Fragment;
52+
}
53+
54+
// Always returns at least 'scheme://host/'
55+
public string GetFullUri()
56+
{
57+
if (string.IsNullOrEmpty(Scheme))
58+
{
59+
throw new InvalidOperationException("Missing Scheme");
60+
}
61+
if (!Host.HasValue)
62+
{
63+
throw new InvalidOperationException("Missing Host");
64+
}
65+
66+
string path = (PathBase.HasValue || Path.HasValue) ? (PathBase + Path).ToString() : "/";
67+
return Scheme + "://" + Host + path + Query + Fragment;
68+
}
69+
70+
public static string Create(PathString pathBase,
71+
PathString path = new PathString(),
72+
QueryString query = new QueryString(),
73+
FragmentString fragment = new FragmentString())
74+
{
75+
return new UriHelper()
76+
{
77+
PathBase = pathBase,
78+
Path = path,
79+
Query = query,
80+
Fragment = fragment
81+
}.GetPartialUri();
82+
}
83+
84+
public static string Create(string scheme,
85+
HostString host,
86+
PathString pathBase = new PathString(),
87+
PathString path = new PathString(),
88+
QueryString query = new QueryString(),
89+
FragmentString fragment = new FragmentString())
90+
{
91+
return new UriHelper()
92+
{
93+
Scheme = scheme,
94+
Host = host,
95+
PathBase = pathBase,
96+
Path = path,
97+
Query = query,
98+
Fragment = fragment
99+
}.GetFullUri();
100+
}
101+
}
102+
}

0 commit comments

Comments
 (0)