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

github.com/mono/mono.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mcs/class/System.Web.Routing/System.Web.Routing/HttpMethodConstraint.cs23
-rw-r--r--mcs/class/System.Web.Routing/System.Web.Routing/PatternParser.cs49
-rw-r--r--mcs/class/System.Web.Routing/System.Web.Routing/Route.cs45
-rw-r--r--mcs/class/System.Web.Routing/Test/System.Web.Routing/HttpMethodConstraintTest.cs15
-rw-r--r--mcs/class/System.Web.Routing/Test/System.Web.Routing/RouteCollectionTest.cs60
5 files changed, 151 insertions, 41 deletions
diff --git a/mcs/class/System.Web.Routing/System.Web.Routing/HttpMethodConstraint.cs b/mcs/class/System.Web.Routing/System.Web.Routing/HttpMethodConstraint.cs
index f12ec329484..be189559fac 100644
--- a/mcs/class/System.Web.Routing/System.Web.Routing/HttpMethodConstraint.cs
+++ b/mcs/class/System.Web.Routing/System.Web.Routing/HttpMethodConstraint.cs
@@ -68,12 +68,25 @@ namespace System.Web.Routing
if (values == null)
throw new ArgumentNullException ("values");
- foreach (string allowed in AllowedMethods)
- // LAMESPEC: .NET allows case-insensitive comparison, which violates RFC 2616
- if (httpContext.Request.HttpMethod == allowed)
- return true;
+ switch (routeDirection)
+ {
+ case RouteDirection.IncomingRequest:
+ // LAMESPEC: .NET allows case-insensitive comparison, which violates RFC 2616
+ return AllowedMethods.Contains(httpContext.Request.HttpMethod);
- return false;
+ case RouteDirection.UrlGeneration:
+ // See: aspnetwebstack's WebAPI equivalent for details.
+ object method;
+
+ if (!values.TryGetValue(parameterName, out method))
+ return true;
+
+ // LAMESPEC: .NET allows case-insensitive comparison, which violates RFC 2616
+ return AllowedMethods.Contains(Convert.ToString(method));
+
+ default:
+ throw new ArgumentException("Invalid routeDirection: " + routeDirection);
+ }
}
}
}
diff --git a/mcs/class/System.Web.Routing/System.Web.Routing/PatternParser.cs b/mcs/class/System.Web.Routing/System.Web.Routing/PatternParser.cs
index 4571bc754a8..cdc76db15a8 100644
--- a/mcs/class/System.Web.Routing/System.Web.Routing/PatternParser.cs
+++ b/mcs/class/System.Web.Routing/System.Web.Routing/PatternParser.cs
@@ -361,11 +361,12 @@ namespace System.Web.Routing
return AddDefaults (ret, defaults);
}
- public bool BuildUrl (Route route, RequestContext requestContext, RouteValueDictionary userValues, out string value)
+ public string BuildUrl (Route route, RequestContext requestContext, RouteValueDictionary userValues, RouteValueDictionary constraints, out RouteValueDictionary usedValues)
{
- value = null;
+ usedValues = null;
+
if (requestContext == null)
- return false;
+ return null;
RouteData routeData = requestContext.RouteData;
RouteValueDictionary defaultValues = route != null ? route.Defaults : null;
@@ -407,10 +408,10 @@ namespace System.Web.Routing
// Has the user provided value for it?
if (userValues == null || !userValues.ContainsKey (parameterName)) {
if (allMustBeInUserValues)
- return false; // partial override => no match
+ return null; // partial override => no match
if (!canTakeFromAmbient || ambientValues == null || !ambientValues.ContainsKey (parameterName))
- return false; // no value provided => no match
+ return null; // no value provided => no match
} else if (canTakeFromAmbient)
allMustBeInUserValues = true;
}
@@ -431,28 +432,16 @@ namespace System.Web.Routing
object defaultValue = de.Value;
if (defaultValue is string && parameterValue is string) {
if (String.Compare ((string)defaultValue, (string)parameterValue, StringComparison.Ordinal) != 0)
- return false; // different value => no match
+ return null; // different value => no match
} else if (defaultValue != parameterValue)
- return false; // different value => no match
+ return null; // different value => no match
}
}
}
- // Check the constraints
- RouteValueDictionary constraints = route != null ? route.Constraints : null;
- if (constraints != null && constraints.Count > 0) {
- HttpContextBase context = requestContext.HttpContext;
- bool invalidConstraint;
-
- foreach (var de in constraints) {
- if (!Route.ProcessConstraintInternal (context, route, de.Value, de.Key, userValues, RouteDirection.UrlGeneration, requestContext, out invalidConstraint) ||
- invalidConstraint)
- return false; // constraint not met => no match
- }
- }
-
// We're a match, generate the URL
var ret = new StringBuilder ();
+ usedValues = new RouteValueDictionary();
bool canTrim = true;
// Going in reverse order, so that we can trim without much ado
@@ -475,6 +464,9 @@ namespace System.Web.Routing
#if SYSTEMCORE_DEP
if (userValues.GetValue (parameterName, out tokenValue)) {
+ if (tokenValue != null)
+ usedValues.Add(parameterName, tokenValue.ToString());
+
if (!defaultValues.Has (parameterName, tokenValue)) {
canTrim = false;
if (tokenValue != null)
@@ -483,7 +475,8 @@ namespace System.Web.Routing
}
if (!canTrim && tokenValue != null)
- ret.Insert (0, tokenValue.ToString ());
+ ret.Insert(0, tokenValue.ToString());
+
continue;
}
@@ -491,16 +484,21 @@ namespace System.Web.Routing
object ambientTokenValue;
if (ambientValues.GetValue (parameterName, out ambientTokenValue))
tokenValue = ambientTokenValue;
-
+
if (!canTrim && tokenValue != null)
ret.Insert (0, tokenValue.ToString ());
+
+ usedValues.Add (parameterName, tokenValue.ToString());
continue;
}
canTrim = false;
if (ambientValues.GetValue (parameterName, out tokenValue)) {
if (tokenValue != null)
- ret.Insert (0, tokenValue.ToString ());
+ {
+ ret.Insert (0, tokenValue.ToString());
+ usedValues.Add (parameterName, tokenValue.ToString());
+ }
continue;
}
#endif
@@ -538,11 +536,12 @@ namespace System.Web.Routing
ret.Append ('=');
if (parameterValue != null)
ret.Append (Uri.EscapeDataString (de.Value.ToString ()));
+
+ usedValues.Add (parameterName, de.Value.ToString());
}
}
- value = ret.ToString ();
- return true;
+ return ret.ToString ();
}
}
}
diff --git a/mcs/class/System.Web.Routing/System.Web.Routing/Route.cs b/mcs/class/System.Web.Routing/System.Web.Routing/Route.cs
index 1a7ce99e833..fc206880a80 100644
--- a/mcs/class/System.Web.Routing/System.Web.Routing/Route.cs
+++ b/mcs/class/System.Web.Routing/System.Web.Routing/Route.cs
@@ -102,11 +102,8 @@ namespace System.Web.Routing
if (values == null)
return null;
- RouteValueDictionary constraints = Constraints;
- if (constraints != null)
- foreach (var p in constraints)
- if (!ProcessConstraint (httpContext, p.Value, p.Key, values, RouteDirection.IncomingRequest))
- return null;
+ if (!ProcessConstraints(httpContext, values, RouteDirection.IncomingRequest))
+ return null;
var rd = new RouteData (this, RouteHandler);
RouteValueDictionary rdValues = rd.Values;
@@ -135,14 +132,27 @@ namespace System.Web.Routing
// if (values == null)
// values = requestContext.RouteData.Values;
- string s;
- if (!url.BuildUrl (this, requestContext, values, out s))
+ RouteValueDictionary usedValues;
+ string resultUrl = url.BuildUrl (this, requestContext, values, Constraints, out usedValues);
+
+ if (resultUrl == null)
+ return null;
+
+ if (!ProcessConstraints(requestContext.HttpContext, usedValues, RouteDirection.UrlGeneration))
return null;
- return new VirtualPathData (this, s);
+ var result = new VirtualPathData (this, resultUrl);
+
+ RouteValueDictionary dataTokens = DataTokens;
+ if (dataTokens != null) {
+ foreach (var item in dataTokens)
+ result.DataTokens[item.Key] = item.Value;
+ }
+
+ return result;
}
- internal static bool ProcessConstraintInternal (HttpContextBase httpContext, Route route, object constraint, string parameterName,
+ private bool ProcessConstraintInternal (HttpContextBase httpContext, Route route, object constraint, string parameterName,
RouteValueDictionary values, RouteDirection routeDirection, RequestContext reqContext,
out bool invalidConstraint)
{
@@ -203,7 +213,7 @@ namespace System.Web.Routing
constraint += "$";
}
- return Regex.Match (value, constraint).Success;
+ return Regex.IsMatch (value, constraint, RegexOptions.CultureInvariant | RegexOptions.IgnoreCase | RegexOptions.Compiled);
}
protected virtual bool ProcessConstraint (HttpContextBase httpContext, object constraint, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
@@ -234,6 +244,21 @@ namespace System.Web.Routing
return ret;
}
+
+ private bool ProcessConstraints (HttpContextBase httpContext, RouteValueDictionary values, RouteDirection routeDirection)
+ {
+ var constraints = Constraints;
+
+ if (Constraints != null)
+ {
+ foreach (var p in constraints)
+ if (!ProcessConstraint (httpContext, p.Value, p.Key, values, RouteDirection.IncomingRequest))
+ return false;
+ }
+
+ return true;
+ }
+
#if NET_4_0
RequestContext SafeGetContext (HttpRequestBase req)
{
diff --git a/mcs/class/System.Web.Routing/Test/System.Web.Routing/HttpMethodConstraintTest.cs b/mcs/class/System.Web.Routing/Test/System.Web.Routing/HttpMethodConstraintTest.cs
index 44f12551055..62e121c8a0f 100644
--- a/mcs/class/System.Web.Routing/Test/System.Web.Routing/HttpMethodConstraintTest.cs
+++ b/mcs/class/System.Web.Routing/Test/System.Web.Routing/HttpMethodConstraintTest.cs
@@ -99,7 +99,7 @@ namespace MonoTests.System.Web.Routing
public void Match ()
{
var c = new MyHttpMethodConstraint (new string [0]);
- Assert.IsFalse (c.CallMatch (new HttpContextStub (), new Route (null, null), "foo", new RouteValueDictionary (), RouteDirection.IncomingRequest));
+ Assert.IsFalse (c.CallMatch (new HttpContextStub (""), new Route (null, null), "foo", new RouteValueDictionary (), RouteDirection.IncomingRequest));
}
[Test]
@@ -121,5 +121,18 @@ namespace MonoTests.System.Web.Routing
// LAMESPEC: .NET allows case-insensitive comparison, which violates RFC 2616
// Assert.IsFalse (c.CallMatch (new HttpContextStub ("", "", "get"), new Route (null, null), "", new RouteValueDictionary (), RouteDirection.IncomingRequest), "#4");
}
+
+ [Test]
+ public void UrlGeneration ()
+ {
+ var c = new HttpMethodConstraint(new string[] { "GET" }) as IRouteConstraint;
+ var req = new HttpContextStub("", "", "HEAD");
+
+ var values = new RouteValueDictionary() { { "httpMethod", "GET" } };
+ Assert.IsTrue(c.Match(req, new Route(null, null), "httpMethod", values, RouteDirection.UrlGeneration), "#1");
+
+ values = new RouteValueDictionary() { { "httpMethod", "POST" } };
+ Assert.IsFalse(c.Match(req, new Route(null, null), "httpMethod", values, RouteDirection.UrlGeneration), "#2");
+ }
}
}
diff --git a/mcs/class/System.Web.Routing/Test/System.Web.Routing/RouteCollectionTest.cs b/mcs/class/System.Web.Routing/Test/System.Web.Routing/RouteCollectionTest.cs
index 5310aafbbf1..6ef558b9e32 100644
--- a/mcs/class/System.Web.Routing/Test/System.Web.Routing/RouteCollectionTest.cs
+++ b/mcs/class/System.Web.Routing/Test/System.Web.Routing/RouteCollectionTest.cs
@@ -538,6 +538,66 @@ namespace MonoTests.System.Web.Routing
}
[Test]
+ public void GetVirtualPath8()
+ {
+ var routes = new RouteCollection();
+
+ routes.Add(new MyRoute("login", new MyRouteHandler())
+ {
+ Defaults = new RouteValueDictionary(new { controller = "Home", action = "LogOn" }),
+ //new { Url = new UrlMatchConstraint("~/login", true) }
+ });
+
+ routes.Add(new MyRoute("{site}/{controller}/{action}", new MyRouteHandler())
+ {
+ Defaults = new RouteValueDictionary(new { site = "_", controller = "Home", action = "Index" }),
+ Constraints = new RouteValueDictionary( new { site = "_?[0-9A-Za-z-]*" })
+ });
+
+ routes.Add(new MyRoute("{*path}", new MyRouteHandler())
+ {
+ Defaults = new RouteValueDictionary(new { controller = "Error", action = "NotFound" }),
+ });
+
+ var hc = new HttpContextStub2("~/login", String.Empty, String.Empty);
+ hc.SetResponse(new HttpResponseStub(3));
+ var rd = routes.GetRouteData(hc);
+ var rvs = new RouteValueDictionary()
+ {
+ { "controller", "Home" },
+ { "action" , "Index" }
+ };
+ var vpd = routes.GetVirtualPath(new RequestContext(hc, rd), rvs);
+ Assert.IsNotNull(vpd, "#A1");
+ Assert.AreEqual("/", vpd.VirtualPath, "#A2");
+ Assert.AreEqual(0, vpd.DataTokens.Count, "#A3");
+
+ hc = new HttpContextStub2("~/login", String.Empty, String.Empty);
+ hc.SetResponse(new HttpResponseStub(3));
+ rd = routes.GetRouteData(hc);
+ rvs = new RouteValueDictionary()
+ {
+ { "controller", "Home" }
+ };
+ vpd = routes.GetVirtualPath(new RequestContext(hc, rd), rvs);
+ Assert.IsNotNull(vpd, "#B1");
+ Assert.AreEqual("/login", vpd.VirtualPath, "#B2");
+ Assert.AreEqual(0, vpd.DataTokens.Count, "#B3");
+
+ hc = new HttpContextStub2("~/login", String.Empty, String.Empty);
+ hc.SetResponse(new HttpResponseStub(3));
+ rd = routes.GetRouteData(hc);
+ rvs = new RouteValueDictionary()
+ {
+ { "action" , "Index" }
+ };
+ vpd = routes.GetVirtualPath(new RequestContext(hc, rd), rvs);
+ Assert.IsNotNull(vpd, "#C1");
+ Assert.AreEqual("/", vpd.VirtualPath, "#C2");
+ Assert.AreEqual(0, vpd.DataTokens.Count, "#C3");
+ }
+
+ [Test]
[Ignore ("looks like RouteExistingFiles ( = false) does not affect... so this test needs more investigation")]
public void GetVirtualPathToExistingFile ()
{