File: DynamicDataRoute.cs

package info (click to toggle)
mono 6.12.0.199%2Bdfsg-6
  • links: PTS, VCS
  • area: main
  • in suites: sid, trixie
  • size: 1,296,836 kB
  • sloc: cs: 11,181,803; xml: 2,850,076; ansic: 699,709; cpp: 123,344; perl: 59,361; javascript: 30,841; asm: 21,853; makefile: 20,405; sh: 15,009; python: 4,839; pascal: 925; sql: 859; sed: 16; php: 1
file content (200 lines) | stat: -rw-r--r-- 7,863 bytes parent folder | download | duplicates (9)
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
187
188
189
190
191
192
193
194
195
196
197
198
199
200
using System.Web.Routing;
using System.Diagnostics;

namespace System.Web.DynamicData {
    /// <summary>
    /// Route used by Dynamic Data
    /// </summary>
    public class DynamicDataRoute : Route {
        internal const string ActionToken = "Action";
        internal const string TableToken = "Table";
        internal const string ModelToken = "__Model";

        private MetaModel _model;
        private volatile bool _initialized;
        private object _initializationLock = new object();

        /// <summary>
        /// Construct a DynamicDataRoute
        /// </summary>
        /// <param name="url">url passed to the base ctor</param>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings",
            Justification = "This is a URL template with special characters, not just a regular valid URL.")]
        public DynamicDataRoute(string url)
            : base(url, new DynamicDataRouteHandler()) {
        }

        /// <summary>
        /// Name of the table that this route applies to. Can be omitted.
        /// </summary>
        public string Table { get; set; }

        /// <summary>
        /// Action that this route applies to. Can be omitted.
        /// </summary>
        public string Action { get; set; }

        /// <summary>
        /// The ViewName is the name of the page used to handle the request. If omitted, it defaults to the Action name.
        /// </summary>
        public string ViewName { get; set; }

        /// <summary>
        /// The MetaModel that this route applies to
        /// </summary>
        public MetaModel Model {
            get { return _model ?? MetaModel.Default; }
            set { _model = value; }
        }

        // Make sure that if the Table or Action properties were used, they get added to
        // the Defaults dictionary
        private void EnsureRouteInitialize() {
            if (!_initialized) {
                lock (_initializationLock) {
                    if (!_initialized) {
                        // Give the model to the handler
                        Debug.Assert(Model != null);
                        RouteHandler.Model = Model;

                        // If neither was specified, we don't need to do anything
                        if (Table == null && Action == null)
                            return;

                        // If we don't already have a Defaults dictionary, create one
                        if (Defaults == null)
                            Defaults = new RouteValueDictionary();

                        if (Table != null) {
                            // Try to get the table just to cause a failure if it doesn't exist
                            var metaTable = Model.GetTable(Table);

                            Defaults[TableToken] = Table;
                        }

                        if (Action != null)
                            Defaults[ActionToken] = Action;

                        _initialized = true;
                    }
                }
            }
        }

        /// <summary>
        /// See base class documentation
        /// </summary>
        public override RouteData GetRouteData(HttpContextBase httpContext) {
            EnsureRouteInitialize();

            // Try to get the route data for this route
            RouteData routeData = base.GetRouteData(httpContext);

            // If not, we're done
            if (routeData == null) {
                return null;
            }

            // Add all the query string values to the RouteData
            // 
            AddQueryStringParamsToRouteData(httpContext, routeData);

            // Check if the route values match an existing table and if they can be served by a scaffolded or custom page
            if (!VerifyRouteValues(routeData.Values))
                return null;

            return routeData;
        }

        internal static void AddQueryStringParamsToRouteData(HttpContextBase httpContext, RouteData routeData) {
            foreach (string key in httpContext.Request.QueryString) {
                // Don't overwrite existing items
                if (!routeData.Values.ContainsKey(key)) {
                    routeData.Values[key] = httpContext.Request.QueryString[key];
                }
            }
        }

        /// <summary>
        /// See base class documentation
        /// </summary>
        public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values) {
            EnsureRouteInitialize();

            // Check if the route values include a MetaModel
            object modelObject;
            if (values.TryGetValue(ModelToken, out modelObject)) {
                var model = modelObject as MetaModel;
                if (model != null) {
                    // If it's different from the one for this route, fail the route matching
                    if (modelObject != Model)
                        return null;

                    // It has the right model, so we want to continue.  But we first need to
                    // remove this token so it doesn't affect the path
                    values.Remove(ModelToken);
                }
            }

            // Call the base to try to generate a path from this route
            VirtualPathData virtualPathData = base.GetVirtualPath(requestContext, values);

            // If not, we're done
            if (virtualPathData == null)
                return null;

            // Check if the route values match an existing table and if they can be served by a scaffolded or custom page
            if (VerifyRouteValues(values)) {
                return virtualPathData;
            }
            else {
                return null;
            }
        }

        private bool VerifyRouteValues(RouteValueDictionary values) {
            // Get the MetaTable and action.  If either is missing, return false to skip this route
            object tableNameObject, actionObject;
            if (!values.TryGetValue(TableToken, out tableNameObject) || !values.TryGetValue(ActionToken, out actionObject)) {
                return false;
            }

            MetaTable table;
            // If no table by such name is available, return false to move on to next route.
            if (!Model.TryGetTable((string)tableNameObject, out table)) {
                return false;
            }

            // Check if n Page can be accessed for the table/action (either scaffold or custom).
            // If not, return false so that this route is not used and the search goes on.
            return RouteHandler.CreateHandler(this, table, (string)actionObject) != null;
        }

        /// <summary>
        /// Extract the MetaTable from the RouteData. Fails if it can't find it
        /// </summary>
        /// <param name="routeData">The route data</param>
        /// <returns>The found MetaTable</returns>
        public MetaTable GetTableFromRouteData(RouteData routeData) {
            string tableName = routeData.GetRequiredString(TableToken);
            return Model.GetTable(tableName);
        }

        /// <summary>
        /// Extract the Action from the RouteData. Fails if it can't find it
        /// </summary>
        /// <param name="routeData">The route data</param>
        /// <returns>The found Action</returns>
        public string GetActionFromRouteData(RouteData routeData) {
            return routeData.GetRequiredString(ActionToken);
        }

        /// <summary>
        /// Strongly typed version of Route.RouteHandler for convenience
        /// </summary>
        public new DynamicDataRouteHandler RouteHandler {
            get { return (DynamicDataRouteHandler)base.RouteHandler; }
            set { base.RouteHandler = value; }
        }
    }
}