Welcome to mirror list, hosted at ThFree Co, Russian Federation.

Route.cs « Routing « System.Web « referencesource « class « mcs - github.com/mono/mono.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 4e78e8ee3fb956a0dfb12129dc958402445f49b5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
namespace System.Web.Routing {
    using System;
    using System.Globalization;
    using System.Text.RegularExpressions;
    using System.Web;
    using System.Runtime.CompilerServices;

    [TypeForwardedFrom("System.Web.Routing, Version=3.5.0.0, Culture=Neutral, PublicKeyToken=31bf3856ad364e35")]
    public class Route : RouteBase {
        private const string HttpMethodParameterName = "httpMethod";

        private string _url;
        private ParsedRoute _parsedRoute;

        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings",
            Justification = "This is a URL template with special characters, not just a regular valid URL.")]
        public Route(string url, IRouteHandler routeHandler) {
            Url = url;
            RouteHandler = routeHandler;
        }

        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings",
            Justification = "This is a URL template with special characters, not just a regular valid URL.")]
        public Route(string url, RouteValueDictionary defaults, IRouteHandler routeHandler) {
            Url = url;
            Defaults = defaults;
            RouteHandler = routeHandler;
        }

        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings",
            Justification = "This is a URL template with special characters, not just a regular valid URL.")]
        public Route(string url, RouteValueDictionary defaults, RouteValueDictionary constraints, IRouteHandler routeHandler) {
            Url = url;
            Defaults = defaults;
            Constraints = constraints;
            RouteHandler = routeHandler;
        }

        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings",
            Justification = "This is a URL template with special characters, not just a regular valid URL.")]
        public Route(string url, RouteValueDictionary defaults, RouteValueDictionary constraints, RouteValueDictionary dataTokens, IRouteHandler routeHandler) {
            Url = url;
            Defaults = defaults;
            Constraints = constraints;
            DataTokens = dataTokens;
            RouteHandler = routeHandler;
        }

        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly",
            Justification = "This property is settable so people can use object initializers.")]
        public RouteValueDictionary Constraints {
            get;
            set;
        }

        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly",
            Justification = "This property is settable so people can use object initializers.")]
        public RouteValueDictionary DataTokens {
            get;
            set;
        }

        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly",
            Justification = "This property is settable so people can use object initializers.")]
        public RouteValueDictionary Defaults {
            get;
            set;
        }

        public IRouteHandler RouteHandler {
            get;
            set;
        }

        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1056:UriPropertiesShouldNotBeStrings",
            Justification = "This is a URL template with special characters, not just a regular valid URL.")]
        public string Url {
            get {
                return _url ?? String.Empty;
            }
            set {
                // The parser will throw for invalid routes. We don't have to worry
                // about _parsedRoute getting out of [....] with _url since the latter
                // won't get set unless we can parse the route.
                _parsedRoute = RouteParser.Parse(value);

                // If we passed the parsing stage, save the original URL value
                _url = value;
            }
        }

        public override RouteData GetRouteData(HttpContextBase httpContext) {
            // Parse incoming URL (we trim off the first two chars since they're always "~/")
            string requestPath = httpContext.Request.AppRelativeCurrentExecutionFilePath.Substring(2) + httpContext.Request.PathInfo;

            RouteValueDictionary values = _parsedRoute.Match(requestPath, Defaults);

            if (values == null) {
                // If we got back a null value set, that means the URL did not match
                return null;
            }

            RouteData routeData = new RouteData(this, RouteHandler);

            // Validate the values
            if (!ProcessConstraints(httpContext, values, RouteDirection.IncomingRequest)) {
                return null;
            }

            // Copy the matched values
            foreach (var value in values) {
                routeData.Values.Add(value.Key, value.Value);
            }

            // Copy the DataTokens from the Route to the RouteData
            if (DataTokens != null) {
                foreach (var prop in DataTokens) {
                    routeData.DataTokens[prop.Key] = prop.Value;
                }
            }

            return routeData;
        }

        public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values) {
            // Try to generate a URL that represents the values passed in based on current
            // values from the RouteData and new values using the specified Route.

            BoundUrl result = _parsedRoute.Bind(requestContext.RouteData.Values, values, Defaults, Constraints);

            if (result == null) {
                return null;
            }

            // Verify that the route matches the validation rules
            if (!ProcessConstraints(requestContext.HttpContext, result.Values, RouteDirection.UrlGeneration)) {
                return null;
            }

            VirtualPathData vpd = new VirtualPathData(this, result.Url);

            // Add the DataTokens from the Route to the VirtualPathData
            if (DataTokens != null) {
                foreach (var prop in DataTokens) {
                    vpd.DataTokens[prop.Key] = prop.Value;
                }
            }
            return vpd;
        }

        protected virtual bool ProcessConstraint(HttpContextBase httpContext, object constraint, string parameterName, RouteValueDictionary values, RouteDirection routeDirection) {
            IRouteConstraint customConstraint = constraint as IRouteConstraint;
            if (customConstraint != null) {
                return customConstraint.Match(httpContext, this, parameterName, values, routeDirection);
            }

            // If there was no custom constraint, then treat the constraint as a string which represents a Regex.
            string constraintsRule = constraint as string;
            if (constraintsRule == null) {
                throw new InvalidOperationException(String.Format(
                    CultureInfo.CurrentUICulture,
                    SR.GetString(SR.Route_ValidationMustBeStringOrCustomConstraint),
                    parameterName,
                    Url));
            }

            object parameterValue;
            values.TryGetValue(parameterName, out parameterValue);
            string parameterValueString = Convert.ToString(parameterValue, CultureInfo.InvariantCulture);
            string constraintsRegEx = "^(" + constraintsRule + ")$";
            return Regex.IsMatch(parameterValueString, constraintsRegEx,
                RegexOptions.CultureInvariant | RegexOptions.IgnoreCase);
        }

        private bool ProcessConstraints(HttpContextBase httpContext, RouteValueDictionary values, RouteDirection routeDirection) {
            if (Constraints != null) {
                foreach (var constraintsItem in Constraints) {
                    if (!ProcessConstraint(httpContext, constraintsItem.Value, constraintsItem.Key, values, routeDirection)) {
                        return false;
                    }
                }
            }
            return true;
        }
    }
}