+2010-05-05 Marek Habersack <mhabersack@novell.com>
+
+ * RouteValueDictionary.cs: do not process type fields in
+ RouteValueDictionary (object)
+
+ * RouteCollection.cs: GetRouteData throws an exception if Request
+ is null in the passed context.
+ Added Ignore* and MapPageRoute* 4.0 APIs
+
+ * RequestContext.cs: 4.0 API update
+
+ * PatternParser.cs: match parser rewrite to encompass 4.0 bug
+ fixes. We don't emulate some of the pre-4.0 routing bugs anymore.
+
2009-11-23 Marek Habersack <mhabersack@novell.com>
* Route.cs: GetRouteData throws NotImplementedException only when
// Atsushi Enomoto <atsushi@ximian.com>
// Marek Habersack <mhabersack@novell.com>
//
-// Copyright (C) 2008-2009 Novell Inc. http://novell.com
+// Copyright (C) 2008-2010 Novell Inc. http://novell.com
//
//
return dict;
}
-
+
+ bool MatchSegment (int segIndex, int argsCount, string[] argSegs, List <PatternToken> tokens, RouteValueDictionary ret)
+ {
+ string pathSegment = argSegs [segIndex];
+ int pathSegmentLength = pathSegment != null ? pathSegment.Length : -1;
+ int startIndex = pathSegmentLength - 1;
+ PatternTokenType tokenType;
+ int tokensCount = tokens.Count;
+ PatternToken token;
+ string tokenName;
+
+ for (int tokenIndex = tokensCount - 1; tokenIndex > -1; tokenIndex--) {
+ token = tokens [tokenIndex];
+ if (startIndex < 0)
+ return false;
+
+ tokenType = token.Type;
+ tokenName = token.Name;
+
+ if (segIndex > segmentCount - 1 || tokenType == PatternTokenType.CatchAll) {
+ var sb = new StringBuilder ();
+
+ for (int j = segIndex; j < argsCount; j++) {
+ if (j > segIndex)
+ sb.Append ('/');
+ sb.Append (argSegs [j]);
+ }
+
+ ret.Add (tokenName, sb.ToString ());
+ break;
+ }
+
+ int scanIndex;
+ if (token.Type == PatternTokenType.Literal) {
+ int nameLen = tokenName.Length;
+ if (startIndex + 1 < nameLen)
+ return false;
+ scanIndex = startIndex - nameLen + 1;
+ if (String.Compare (pathSegment, scanIndex, tokenName, 0, nameLen, StringComparison.OrdinalIgnoreCase) != 0)
+ return false;
+ startIndex = scanIndex - 1;
+ continue;
+ }
+
+ // Standard token
+ int nextTokenIndex = tokenIndex - 1;
+ if (nextTokenIndex < 0) {
+ // First token
+ ret.Add (tokenName, pathSegment.Substring (0, startIndex + 1));
+ continue;
+ }
+
+ if (startIndex == 0)
+ return false;
+
+ var nextToken = tokens [nextTokenIndex];
+ string nextTokenName = nextToken.Name;
+
+ // Skip one char, since there can be no empty segments and if the
+ // current token's value happens to be the same as preceeding
+ // literal text, we'll save some time and complexity.
+ scanIndex = startIndex - 1;
+ int lastIndex = pathSegment.LastIndexOf (nextTokenName, scanIndex, StringComparison.OrdinalIgnoreCase);
+ if (lastIndex == -1)
+ return false;
+
+ lastIndex += nextTokenName.Length - 1;
+
+ string sectionValue = pathSegment.Substring (lastIndex + 1, startIndex - lastIndex);
+ if (String.IsNullOrEmpty (sectionValue))
+ return false;
+
+ ret.Add (tokenName, sectionValue);
+ startIndex = lastIndex;
+ }
+
+ return true;
+ }
+
public RouteValueDictionary Match (string path, RouteValueDictionary defaults)
{
var ret = new RouteValueDictionary ();
continue;
}
- string pathSegment = argSegs [i];
- int pathSegmentLength = pathSegment != null ? pathSegment.Length : -1;
- int pathIndex = 0;
- PatternTokenType tokenType;
- List <PatternToken> tokens = segment.Tokens;
- int tokensCount = tokens.Count;
-
- // Process the path segments ignoring the defaults
- for (int tokenIndex = 0; tokenIndex < tokensCount; tokenIndex++) {
- var token = tokens [tokenIndex];
- if (pathIndex > pathSegmentLength - 1)
- return null;
-
- tokenType = token.Type;
- var tokenName = token.Name;
-
- // Catch-all
- if (i > segmentCount - 1 || tokenType == PatternTokenType.CatchAll) {
- if (tokenType != PatternTokenType.CatchAll)
- return null;
-
- StringBuilder sb = new StringBuilder ();
- for (int j = i; j < argsCount; j++) {
- if (j > i)
- sb.Append ('/');
- sb.Append (argSegs [j]);
- }
-
- ret.Add (tokenName, sb.ToString ());
- break;
- }
-
- // Literal sections
- if (token.Type == PatternTokenType.Literal) {
- int nameLen = tokenName.Length;
- if (pathSegmentLength < nameLen || String.Compare (pathSegment, pathIndex, tokenName, 0, nameLen, StringComparison.OrdinalIgnoreCase) != 0)
- return null;
- pathIndex += nameLen;
- continue;
- }
-
- int nextTokenIndex = tokenIndex + 1;
- if (nextTokenIndex >= tokensCount) {
- // Last token
- ret.Add (tokenName, pathSegment.Substring (pathIndex));
- continue;
- }
-
- // Next token is a literal - greedy matching. It seems .NET
- // uses a simple and naive algorithm here which finds the
- // last ocurrence of the next section literal and assigns
- // everything before that to this token. See the
- // GetRouteData28 test in RouteTest.cs
- var nextToken = tokens [nextTokenIndex];
- string nextTokenName = nextToken.Name;
- int lastIndex = pathSegment.LastIndexOf (nextTokenName, pathSegmentLength - 1, pathSegmentLength - pathIndex, StringComparison.OrdinalIgnoreCase);
- if (lastIndex == -1)
- return null;
-
- int copyLength = lastIndex - pathIndex;
- string sectionValue = pathSegment.Substring (pathIndex, copyLength);
- if (String.IsNullOrEmpty (sectionValue))
- return null;
-
- ret.Add (tokenName, sectionValue);
- pathIndex += copyLength;
- }
+ if (!MatchSegment (i, argsCount, argSegs, segment.Tokens, ret))
+ return null;
i++;
}
[AspNetHostingPermission (SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
public class RequestContext
{
+#if NET_4_0
+ public RequestContext ()
+ {
+ HttpContext = null;
+ RouteData = null;
+ }
+#endif
public RequestContext (HttpContextBase httpContext, RouteData routeData)
{
if (httpContext == null)
RouteData = routeData;
}
+#if NET_4_0
+ public virtual HttpContextBase HttpContext { get; set; }
+ public virtual RouteData RouteData { get; set; }
+#else
public HttpContextBase HttpContext { get; private set; }
-
public RouteData RouteData { get; private set; }
+#endif
}
}
if (values == null)
return null;
- if (Constraints != null)
- foreach (var p in Constraints)
+ RouteValueDictionary constraints = Constraints;
+ if (constraints != null)
+ foreach (var p in constraints)
if (!ProcessConstraint (httpContext, p.Value, p.Key, values, RouteDirection.IncomingRequest))
return null;
-
+
var rd = new RouteData (this, RouteHandler);
RouteValueDictionary rdValues = rd.Values;
bool ret = ProcessConstraintInternal (httpContext, this, constraint, parameterName, values, routeDirection, out invalidConstraint);
if (invalidConstraint)
- throw new InvalidOperationException (String.Format ("Constraint parameter '{0}' must be either a string or an IRouteConstraint instance", parameterName));
+ throw new InvalidOperationException (
+ String.Format (
+ "Constraint parameter '{0}' on the route with URL '{1}' must have a string value type or be a type which implements IRouteConstraint",
+ parameterName, Url
+ )
+ );
return ret;
}
if (httpContext == null)
throw new ArgumentNullException ("httpContext");
+ if (httpContext.Request == null)
+ throw new ArgumentException ("The context does not contain any request data.", "httpContext");
+#if NET_4_0
+ if (Count == 0)
+ return null;
+#endif
if (!RouteExistingFiles) {
var path = httpContext.Request.AppRelativeCurrentExecutionFilePath;
VirtualPathProvider vpp = HostingEnvironment.VirtualPathProvider;
if (path != "~/" && vpp != null && (vpp.FileExists (path) || vpp.DirectoryExists (path)))
return null;
}
-
+#if !NET_4_0
if (Count == 0)
return null;
-
+#endif
foreach (RouteBase rb in this) {
var rd = rb.GetRouteData (httpContext);
if (rd != null)
{
return write_lock;
}
+#if NET_4_0
+ public void Ignore (string url)
+ {
+ Ignore (url, null);
+ }
+
+ public void Ignore (string url, object constraints)
+ {
+ if (url == null)
+ throw new ArgumentNullException ("url");
+
+ Add (new Route (url, null, new RouteValueDictionary (constraints), new StopRoutingHandler ()));
+ }
+
+ public Route MapPageRoute (string routeName, string routeUrl, string physicalFile)
+ {
+ return MapPageRoute (routeName, routeUrl, physicalFile, true, null, null, null);
+ }
+ public Route MapPageRoute (string routeName, string routeUrl, string physicalFile, bool checkPhysicalUrlAccess)
+ {
+ return MapPageRoute (routeName, routeUrl, physicalFile, checkPhysicalUrlAccess, null, null, null);
+ }
+
+ public Route MapPageRoute (string routeName, string routeUrl, string physicalFile, bool checkPhysicalUrlAccess,
+ RouteValueDictionary defaults)
+ {
+ return MapPageRoute (routeName, routeUrl, physicalFile, checkPhysicalUrlAccess, defaults, null, null);
+ }
+
+ public Route MapPageRoute (string routeName, string routeUrl, string physicalFile, bool checkPhysicalUrlAccess,
+ RouteValueDictionary defaults, RouteValueDictionary constraints)
+ {
+ return MapPageRoute (routeName, routeUrl, physicalFile, checkPhysicalUrlAccess, defaults, constraints, null);
+ }
+
+ public Route MapPageRoute (string routeName, string routeUrl, string physicalFile, bool checkPhysicalUrlAccess,
+ RouteValueDictionary defaults, RouteValueDictionary constraints, RouteValueDictionary dataTokens)
+ {
+ if (routeUrl == null)
+ throw new ArgumentNullException ("routeUrl");
+
+ var route = new Route (routeUrl, defaults, constraints, dataTokens, new PageRouteHandler (physicalFile, checkPhysicalUrlAccess));
+ Add (routeName, route);
+
+ return route;
+ }
+#endif
protected override void InsertItem (int index, RouteBase item)
{
// FIXME: what happens wrt its name?
if (values == null)
return;
- foreach (var fi in values.GetType ().GetFields ())
- Add (fi.Name, fi.GetValue (values));
- foreach (var pi in values.GetType ().GetProperties ())
- Add (pi.Name, pi.GetValue (values, null));
+ foreach (var pi in values.GetType ().GetProperties ()) {
+ try {
+ Add (pi.Name, pi.GetValue (values, null));
+ } catch {
+ // ignore
+ }
+ }
}
public int Count {
// Author:
// Atsushi Enomoto <atsushi@ximian.com>
//
-// Copyright (C) 2008 Novell Inc. http://novell.com
+// Copyright (C) 2008-2010 Novell Inc. http://novell.com
//
//
System.Web.Routing/FakeHttpWorkerRequest.cs
System.Web.Routing/HttpMethodConstraintTest.cs
System.Web.Routing/KnownResponseHeader.cs
+System.Web.Routing/RequestContext.cs
System.Web.Routing/RouteCollectionTest.cs
System.Web.Routing/RouteDataTest.cs
System.Web.Routing/RouteTest.cs
public override string GetRawUrl ()
{
+#if NET_4_0
+ return "/GetRawUrl";
+#else
return "GetRawUrl";
+#endif
}
public override string GetHttpVerbName ()
--- /dev/null
+//
+// RequestContext.cs
+//
+// Authors:
+// Marek Habersack <mhabersack@novell.com>
+//
+// Copyright (C) 2010 Novell Inc. http://novell.com
+//
+
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+using System;
+using System.IO;
+using System.Text;
+using System.Web;
+using System.Web.Routing;
+
+using NUnit.Framework;
+
+namespace MonoTests.System.Web.Routing
+{
+ [TestFixture]
+ public class RequestContextTest
+ {
+#if NET_4_0
+ [Test]
+ public void DefaultConstructor ()
+ {
+ var rc = new RequestContext ();
+
+ Assert.AreEqual (null, rc.HttpContext, "#A1");
+ Assert.AreEqual (null, rc.RouteData, "#A2");
+ }
+#endif
+ [Test]
+ public void Constructor_HttpContextBase_RouteData ()
+ {
+ RequestContext rc;
+
+ AssertExtensions.Throws<ArgumentNullException> (() => {
+ rc = new RequestContext (null, new RouteData ());
+ }, "#A1");
+
+ var ctx = new HttpContextWrapper (new HttpContext (new HttpRequest ("filename", "http://localhost/filename", String.Empty), new HttpResponse (new StringWriter ())));
+ AssertExtensions.Throws<ArgumentNullException> (() => {
+ rc = new RequestContext (ctx, null);
+ }, "#A2");
+ }
+
+ [Test]
+ public void HttpContext ()
+ {
+ var ctx = new HttpContextWrapper (new HttpContext (new HttpRequest ("filename", "http://localhost/filename", String.Empty), new HttpResponse (new StringWriter ())));
+ var rc = new RequestContext (ctx, new RouteData ());
+
+ Assert.AreSame (ctx, rc.HttpContext, "#A1");
+#if NET_4_0
+ ctx = new HttpContextWrapper (new HttpContext (new HttpRequest ("filename", "http://localhost/filename", String.Empty), new HttpResponse (new StringWriter ())));
+ rc.HttpContext = ctx;
+ Assert.AreSame (ctx, rc.HttpContext, "#A2");
+
+ rc.HttpContext = null;
+ Assert.IsNull (rc.HttpContext, "#A3");
+#endif
+ }
+
+ [Test]
+ public void RouteData ()
+ {
+ var ctx = new HttpContextWrapper (new HttpContext (new HttpRequest ("filename", "http://localhost/filename", String.Empty), new HttpResponse (new StringWriter ())));
+ var rd = new RouteData ();
+ var rc = new RequestContext (ctx, rd);
+
+ Assert.AreSame (rd, rc.RouteData, "#A1");
+#if NET_4_0
+ rd = new RouteData ();
+ rc.RouteData = rd;
+ Assert.AreSame (rd, rc.RouteData, "#A2");
+
+ rc.RouteData = null;
+ Assert.IsNull (rc.RouteData, "#A3");
+#endif
+ }
+ }
+}
Assert.IsNull(c ["x"]);
}
+ [Test]
+ [ExpectedException (typeof (ArgumentException))]
+ public void GetRouteDataNoRequest ()
+ {
+ new RouteCollection ().GetRouteData (new HttpContextStub (true));
+ }
+
[Test]
[ExpectedException (typeof (ArgumentNullException))]
public void GetRouteDataNullArg ()
public void GetRouteDataForNonExistent2 ()
{
var rd = new RouteCollection () { RouteExistingFiles = true }.GetRouteData (new HttpContextStub2 (null, null, null));
- Assert.IsNull (rd);
+ Assert.IsNull (rd, "#A1");
+#if NET_4_0
+ rd = new RouteCollection ().GetRouteData (new HttpContextStub2 (null, null, null));
+ Assert.IsNull (rd, "#A2");
+#else
try {
new RouteCollection ().GetRouteData (new HttpContextStub2 (null, null, null));
- Assert.Fail ("#1");
+ Assert.Fail ("#A3");
} catch (NotImplementedException) {
// it should fail due to the NIE on AppRelativeCurrentExecutionFilePath.
}
+#endif
}
[Test]
Assert.IsNotNull (rd, "#A1");
}
+#if NET_4_0
+ [Test]
+ public void Ignore_String ()
+ {
+ var c = new RouteCollection ();
+
+ AssertExtensions.Throws<ArgumentNullException> (() => {
+ c.Ignore (null);
+ }, "#A1");
+
+ c.Ignore ("{resource}.axd/{*pathInfo}");
+ var hc = new HttpContextStub2 ("~/something.axd/pathinfo", String.Empty, String.Empty);
+ hc.SetResponse (new HttpResponseStub (3));
+ var rd = c.GetRouteData (hc);
+
+ Assert.IsNotNull (rd, "#A1-1");
+ Assert.IsNotNull (rd.RouteHandler, "#A1-2");
+ Assert.AreEqual (typeof (StopRoutingHandler), rd.RouteHandler.GetType (), "#A1-3");
+ Assert.IsTrue (rd.Route is Route, "#A1-4");
+ Assert.IsNotNull (((Route) rd.Route).Constraints, "#A1-5");
+ Assert.AreEqual (0, ((Route) rd.Route).Constraints.Count, "#A1-6");
+ }
+
+ [Test]
+ public void Ignore_String_Object ()
+ {
+ var c = new RouteCollection ();
+
+ AssertExtensions.Throws<ArgumentNullException> (() => {
+ c.Ignore (null, new { allaspx = @".*\.aspx(/.*)?" });
+ }, "#A1");
+
+ c.Ignore ("{*allaspx}", new { allaspx = @".*\.aspx(/.*)?" });
+ var hc = new HttpContextStub2 ("~/page.aspx", String.Empty, String.Empty);
+ hc.SetResponse (new HttpResponseStub (3));
+ var rd = c.GetRouteData (hc);
+
+ Assert.IsNotNull (rd, "#A1-1");
+ Assert.IsNotNull (rd.RouteHandler, "#A1-2");
+ Assert.AreEqual (typeof (StopRoutingHandler), rd.RouteHandler.GetType (), "#A1-3");
+ Assert.IsTrue (rd.Route is Route, "#A1-4");
+ Assert.IsNotNull (((Route) rd.Route).Constraints, "#A1-5");
+ Assert.AreEqual (1, ((Route) rd.Route).Constraints.Count, "#A1-6");
+ Assert.AreEqual (@".*\.aspx(/.*)?", ((Route) rd.Route).Constraints ["allaspx"], "#A1-7");
+
+ c = new RouteCollection ();
+ c.Ignore ("{*allaspx}", "something invalid");
+
+ AssertExtensions.Throws<InvalidOperationException> (() => {
+ rd = c.GetRouteData (hc);
+ }, "#A2");
+ }
+
+ [Test]
+ public void MapPageRoute_String_String_String ()
+ {
+ var c = new RouteCollection ();
+
+ c.MapPageRoute (null, "{foo}-{bar}", "~/some-url");
+ var hc = new HttpContextStub2 ("~/some-url", String.Empty, String.Empty);
+ hc.SetResponse (new HttpResponseStub (3));
+ var rd = c.GetRouteData (hc);
+
+ Assert.IsNotNull (rd, "#A1-1");
+ Assert.IsNotNull (rd.RouteHandler, "#A1-2");
+ Assert.AreEqual (typeof (PageRouteHandler), rd.RouteHandler.GetType (), "#A1-3");
+
+ c = new RouteCollection ();
+ AssertExtensions.Throws<ArgumentNullException> (() => {
+ c.MapPageRoute ("RouteName", null, "~/some-url");
+ }, "#A2");
+
+ c = new RouteCollection ();
+ c.MapPageRoute ("RouteName", String.Empty, "~/some-url");
+ rd = c.GetRouteData (hc);
+
+ Assert.IsNull (rd, "#A2");
+
+ c = new RouteCollection ();
+ // thrown by PageRouteHandler's constructor
+ AssertExtensions.Throws<ArgumentException> (() => {
+ c.MapPageRoute ("RouteName", "~/some-url", null);
+ }, "#A3");
+ }
+
+ [Test]
+ public void MapPageRoute_String_String_String_Bool ()
+ {
+ var c = new RouteCollection ();
+
+ c.MapPageRoute (null, "{foo}-{bar}", "~/some-url", true);
+ var hc = new HttpContextStub2 ("~/some-url", String.Empty, String.Empty);
+ hc.SetResponse (new HttpResponseStub (3));
+ var rd = c.GetRouteData (hc);
+
+ Assert.IsNotNull (rd, "#A1-1");
+ Assert.IsNotNull (rd.RouteHandler, "#A1-2");
+ Assert.AreEqual (typeof (PageRouteHandler), rd.RouteHandler.GetType (), "#A1-3");
+ Assert.IsTrue (((PageRouteHandler) rd.RouteHandler).CheckPhysicalUrlAccess, "#A1-4");
+
+ c = new RouteCollection ();
+ AssertExtensions.Throws<ArgumentNullException> (() => {
+ c.MapPageRoute ("RouteName", null, "~/some-url", true);
+ }, "#A2");
+
+ c = new RouteCollection ();
+ c.MapPageRoute ("RouteName", String.Empty, "~/some-url", true);
+ rd = c.GetRouteData (hc);
+
+ Assert.IsNull (rd, "#A2");
+
+ c = new RouteCollection ();
+ // thrown by PageRouteHandler's constructor
+ AssertExtensions.Throws<ArgumentException> (() => {
+ c.MapPageRoute ("RouteName", "~/some-url", null, true);
+ }, "#A3");
+
+ c.MapPageRoute (null, "{foo}-{bar}", "~/some-url", false);
+ rd = c.GetRouteData (hc);
+
+ Assert.IsNotNull (rd, "#A4-1");
+ Assert.IsNotNull (rd.RouteHandler, "#A4-2");
+ Assert.AreEqual (typeof (PageRouteHandler), rd.RouteHandler.GetType (), "#A4-3");
+ Assert.IsFalse (((PageRouteHandler) rd.RouteHandler).CheckPhysicalUrlAccess, "#A4-4");
+ }
+
+ [Test]
+ public void MapPageRoute_String_String_String_Bool_RVD ()
+ {
+ var c = new RouteCollection ();
+ var defaults = new RouteValueDictionary ();
+
+ c.MapPageRoute (null, "{foo}-{bar}", "~/some-url", true, defaults);
+ var hc = new HttpContextStub2 ("~/some-url", String.Empty, String.Empty);
+ hc.SetResponse (new HttpResponseStub (3));
+ var rd = c.GetRouteData (hc);
+
+ Assert.IsNotNull (rd, "#A1-1");
+ Assert.IsNotNull (rd.RouteHandler, "#A1-2");
+ Assert.AreEqual (typeof (PageRouteHandler), rd.RouteHandler.GetType (), "#A1-3");
+ Assert.IsTrue (((PageRouteHandler) rd.RouteHandler).CheckPhysicalUrlAccess, "#A1-4");
+
+ c = new RouteCollection ();
+ AssertExtensions.Throws<ArgumentNullException> (() => {
+ c.MapPageRoute ("RouteName", null, "~/some-url", true, defaults);
+ }, "#A2");
+
+ c = new RouteCollection ();
+ c.MapPageRoute ("RouteName", String.Empty, "~/some-url", true, defaults);
+ rd = c.GetRouteData (hc);
+
+ Assert.IsNull (rd, "#A2");
+
+ c = new RouteCollection ();
+ // thrown by PageRouteHandler's constructor
+ AssertExtensions.Throws<ArgumentException> (() => {
+ c.MapPageRoute ("RouteName", "~/some-url", null, true, defaults);
+ }, "#A3");
+
+ c.MapPageRoute (null, "{foo}-{bar}", "~/some-url", false, defaults);
+ rd = c.GetRouteData (hc);
+
+ Assert.IsNotNull (rd, "#A4-1");
+ Assert.IsNotNull (rd.RouteHandler, "#A4-2");
+ Assert.AreEqual (typeof (PageRouteHandler), rd.RouteHandler.GetType (), "#A4-3");
+ Assert.IsFalse (((PageRouteHandler) rd.RouteHandler).CheckPhysicalUrlAccess, "#A4-4");
+
+ c.MapPageRoute (null, "{foo}-{bar}", "~/some-url", false, null);
+ rd = c.GetRouteData (hc);
+
+ Assert.IsNotNull (rd, "#A4-1");
+ Assert.IsNotNull (rd.RouteHandler, "#A4-2");
+ Assert.AreEqual (typeof (PageRouteHandler), rd.RouteHandler.GetType (), "#A4-3");
+ Assert.IsFalse (((PageRouteHandler) rd.RouteHandler).CheckPhysicalUrlAccess, "#A4-4");
+ }
+
+ [Test]
+ public void MapPageRoute_String_String_String_Bool_RVD_RVD ()
+ {
+ var c = new RouteCollection ();
+ var defaults = new RouteValueDictionary ();
+ var constraints = new RouteValueDictionary ();
+
+ c.MapPageRoute (null, "{foo}-{bar}", "~/some-url", true, defaults, constraints);
+ var hc = new HttpContextStub2 ("~/some-url", String.Empty, String.Empty);
+ hc.SetResponse (new HttpResponseStub (3));
+ var rd = c.GetRouteData (hc);
+
+ Assert.IsNotNull (rd, "#A1-1");
+ Assert.IsNotNull (rd.RouteHandler, "#A1-2");
+ Assert.AreEqual (typeof (PageRouteHandler), rd.RouteHandler.GetType (), "#A1-3");
+ Assert.IsTrue (((PageRouteHandler) rd.RouteHandler).CheckPhysicalUrlAccess, "#A1-4");
+
+ c = new RouteCollection ();
+ AssertExtensions.Throws<ArgumentNullException> (() => {
+ c.MapPageRoute ("RouteName", null, "~/some-url", true, defaults, constraints);
+ }, "#A2");
+
+ c = new RouteCollection ();
+ c.MapPageRoute ("RouteName", String.Empty, "~/some-url", true, defaults, constraints);
+ rd = c.GetRouteData (hc);
+
+ Assert.IsNull (rd, "#A2");
+
+ c = new RouteCollection ();
+ // thrown by PageRouteHandler's constructor
+ AssertExtensions.Throws<ArgumentException> (() => {
+ c.MapPageRoute ("RouteName", "~/some-url", null, true, defaults, constraints);
+ }, "#A3");
+
+ c.MapPageRoute (null, "{foo}-{bar}", "~/some-url", false, defaults, constraints);
+ rd = c.GetRouteData (hc);
+
+ Assert.IsNotNull (rd, "#A4-1");
+ Assert.IsNotNull (rd.RouteHandler, "#A4-2");
+ Assert.AreEqual (typeof (PageRouteHandler), rd.RouteHandler.GetType (), "#A4-3");
+ Assert.IsFalse (((PageRouteHandler) rd.RouteHandler).CheckPhysicalUrlAccess, "#A4-4");
+
+ c.MapPageRoute (null, "{foo}-{bar}", "~/some-url", false, null, constraints);
+ rd = c.GetRouteData (hc);
+
+ Assert.IsNotNull (rd, "#A4-1");
+ Assert.IsNotNull (rd.RouteHandler, "#A4-2");
+ Assert.AreEqual (typeof (PageRouteHandler), rd.RouteHandler.GetType (), "#A4-3");
+ Assert.IsFalse (((PageRouteHandler) rd.RouteHandler).CheckPhysicalUrlAccess, "#A4-4");
+ }
+
+ [Test]
+ public void MapPageRoute_String_String_String_Bool_RVD_RVD_RVD ()
+ {
+ var c = new RouteCollection ();
+ var defaults = new RouteValueDictionary ();
+ var constraints = new RouteValueDictionary ();
+ var dataTokens = new RouteValueDictionary ();
+
+ c.MapPageRoute (null, "{foo}-{bar}", "~/some-url", true, defaults, constraints, dataTokens);
+ var hc = new HttpContextStub2 ("~/some-url", String.Empty, String.Empty);
+ hc.SetResponse (new HttpResponseStub (3));
+ var rd = c.GetRouteData (hc);
+
+ Assert.IsNotNull (rd, "#A1-1");
+ Assert.IsNotNull (rd.RouteHandler, "#A1-2");
+ Assert.AreEqual (typeof (PageRouteHandler), rd.RouteHandler.GetType (), "#A1-3");
+ Assert.IsTrue (((PageRouteHandler) rd.RouteHandler).CheckPhysicalUrlAccess, "#A1-4");
+
+ c = new RouteCollection ();
+ AssertExtensions.Throws<ArgumentNullException> (() => {
+ c.MapPageRoute ("RouteName", null, "~/some-url", true, defaults, constraints, dataTokens);
+ }, "#A2");
+
+ c = new RouteCollection ();
+ c.MapPageRoute ("RouteName", String.Empty, "~/some-url", true, defaults, constraints, dataTokens);
+ rd = c.GetRouteData (hc);
+
+ Assert.IsNull (rd, "#A2");
+
+ c = new RouteCollection ();
+ // thrown by PageRouteHandler's constructor
+ AssertExtensions.Throws<ArgumentException> (() => {
+ c.MapPageRoute ("RouteName", "~/some-url", null, true, defaults, constraints, dataTokens);
+ }, "#A3");
+
+ c.MapPageRoute (null, "{foo}-{bar}", "~/some-url", false, defaults, constraints, dataTokens);
+ rd = c.GetRouteData (hc);
+
+ Assert.IsNotNull (rd, "#A4-1");
+ Assert.IsNotNull (rd.RouteHandler, "#A4-2");
+ Assert.AreEqual (typeof (PageRouteHandler), rd.RouteHandler.GetType (), "#A4-3");
+ Assert.IsFalse (((PageRouteHandler) rd.RouteHandler).CheckPhysicalUrlAccess, "#A4-4");
+
+ c.MapPageRoute (null, "{foo}-{bar}", "~/some-url", false, null, constraints, dataTokens);
+ rd = c.GetRouteData (hc);
+
+ Assert.IsNotNull (rd, "#A4-1");
+ Assert.IsNotNull (rd.RouteHandler, "#A4-2");
+ Assert.AreEqual (typeof (PageRouteHandler), rd.RouteHandler.GetType (), "#A4-3");
+ Assert.IsFalse (((PageRouteHandler) rd.RouteHandler).CheckPhysicalUrlAccess, "#A4-4");
+ }
+#endif
}
}
Assert.AreEqual (3, rd.Values.Count, "#4");
Assert.AreEqual ("test", rd.Values["action"], "#4-1");
Assert.AreEqual ("xml", rd.Values["type"], "#4-2");
- Assert.AreEqual ("1", rd.Values["page"], "#4-2");
+ Assert.AreEqual ("1", rd.Values["page"], "#4-3");
}
[Test]
var hc = new HttpContextStub ("~/xyzxyzxyzxyzblah", String.Empty);
var rd = r.GetRouteData (hc);
+#if NET_4_0 || !DOTNET
+ // When running on Mono this test succeeds - it was a bug in .NET routing for 3.5 which
+ // we don't reproduce anymore.
+ Assert.IsNotNull (rd, "#1");
+ Assert.AreEqual (r, rd.Route, "#2");
+ Assert.AreEqual (0, rd.DataTokens.Count, "#3");
+ Assert.AreEqual (3, rd.Values.Count, "#4");
+ Assert.AreEqual ("xyz", rd.Values ["foo"], "#4-1");
+ Assert.AreEqual ("xyz", rd.Values ["bar"], "#4-2");
+ Assert.AreEqual ("blah", rd.Values ["baz"], "#4-3");
+#else
Assert.IsNull (rd, "#1");
+#endif
}
[Test]
Assert.AreEqual (0, rd.Values.Count, "#4");
}
+ [Test]
+ public void GetRouteData34 ()
+ {
+ var r = new Route ("{foo}xyz{bar}xyz{baz}", null);
+ var hc = new HttpContextStub ("~/xyzxyzxyzxyzxyzxyzblah", String.Empty);
+ var rd = r.GetRouteData (hc);
+
+#if NET_4_0 || !DOTNET
+ // When running on Mono this test succeeds - it was a bug in .NET routing for 3.5 which
+ // we don't reproduce anymore.
+ Assert.IsNotNull (rd, "#1");
+ Assert.AreEqual (r, rd.Route, "#2");
+ Assert.AreEqual (0, rd.DataTokens.Count, "#3");
+ Assert.AreEqual (3, rd.Values.Count, "#4");
+ Assert.AreEqual ("xyzxyzxyz", rd.Values ["foo"], "#4-1");
+ Assert.AreEqual ("xyz", rd.Values ["bar"], "#4-2");
+ Assert.AreEqual ("blah", rd.Values ["baz"], "#4-3");
+#else
+ Assert.IsNull (rd, "#1");
+#endif
+ }
+
+ [Test]
+ public void GetRouteData35 ()
+ {
+ var r = new Route ("{foo}xyz{bar}xyz{baz}", null);
+ var hc = new HttpContextStub ("~/xyzxyzxyzdabxyzblah", String.Empty);
+ var rd = r.GetRouteData (hc);
+
+ Assert.IsNotNull (rd, "#1");
+ Assert.AreEqual (r, rd.Route, "#2");
+ Assert.AreEqual (0, rd.DataTokens.Count, "#3");
+ Assert.AreEqual (3, rd.Values.Count, "#4");
+ Assert.AreEqual ("xyzxyz", rd.Values ["foo"], "#4-1");
+ Assert.AreEqual ("dab", rd.Values ["bar"], "#4-2");
+ Assert.AreEqual ("blah", rd.Values ["baz"], "#4-3");
+ }
+
+ [Test]
+ public void GetRouteData36 ()
+ {
+ var r = new Route ("xyz{foo}xyz{bar}xyz{baz}", null);
+ var hc = new HttpContextStub ("~/xyzxyzxyzdabxyzblah", String.Empty);
+ var rd = r.GetRouteData (hc);
+
+#if NET_4_0 || !DOTNET
+ // When running on Mono this test succeeds - it was a bug in .NET routing for 3.5 which
+ // we don't reproduce anymore.
+ Assert.IsNotNull (rd, "#1");
+ Assert.AreEqual (r, rd.Route, "#2");
+ Assert.AreEqual (0, rd.DataTokens.Count, "#3");
+ Assert.AreEqual (3, rd.Values.Count, "#4");
+ Assert.AreEqual ("xyz", rd.Values ["foo"], "#4-1");
+ Assert.AreEqual ("dab", rd.Values ["bar"], "#4-2");
+ Assert.AreEqual ("blah", rd.Values ["baz"], "#4-3");
+#else
+ Assert.IsNull (rd, "#1");
+#endif
+ }
+
+ [Test]
+ public void GetRouteData37 ()
+ {
+ var r = new Route ("{foo}xyz{bar}xyz{baz}", null);
+ var hc = new HttpContextStub ("~/xyzxyzxyzxyzxyz", String.Empty);
+ var rd = r.GetRouteData (hc);
+
+#if NET_4_0 || !DOTNET
+ // When running on Mono this test succeeds - it was a bug in .NET routing for 3.5 which
+ // we don't reproduce anymore.
+ Assert.IsNotNull (rd, "#1");
+ Assert.AreEqual (r, rd.Route, "#2");
+ Assert.AreEqual (0, rd.DataTokens.Count, "#3");
+ Assert.AreEqual (3, rd.Values.Count, "#4");
+ Assert.AreEqual ("xyz", rd.Values ["foo"], "#4-1");
+ Assert.AreEqual ("xyz", rd.Values ["bar"], "#4-2");
+ Assert.AreEqual ("xyz", rd.Values ["baz"], "#4-3");
+#else
+ Assert.IsNull (rd, "#1");
+#endif
+ }
+
+ [Test]
+ public void GetRouteData38 ()
+ {
+ // {} matches and substitutes even at partial state ...
+ var r = new Route ("{foo}/bar{baz}", null);
+ var hc = new HttpContextStub ("~/x/bartest", String.Empty);
+ var rd = r.GetRouteData (hc);
+ Assert.IsNotNull (rd, "#1");
+ Assert.AreEqual (r, rd.Route, "#2");
+ Assert.AreEqual (0, rd.DataTokens.Count, "#3");
+ Assert.AreEqual (2, rd.Values.Count, "#4");
+ Assert.AreEqual ("x", rd.Values ["foo"], "#4-1");
+ Assert.AreEqual ("test", rd.Values ["baz"], "#4-2");
+ }
+
+ [Test]
+ public void GetRouteData39 ()
+ {
+ // {} matches and substitutes even at partial state ...
+ var r = new Route ("{foo}/bar{baz}", null);
+ var hc = new HttpContextStub ("~/x/barte", String.Empty);
+ var rd = r.GetRouteData (hc);
+ Assert.IsNotNull (rd, "#1");
+ Assert.AreEqual (r, rd.Route, "#2");
+ Assert.AreEqual (0, rd.DataTokens.Count, "#3");
+ Assert.AreEqual (2, rd.Values.Count, "#4");
+ Assert.AreEqual ("x", rd.Values ["foo"], "#4-1");
+ Assert.AreEqual ("te", rd.Values ["baz"], "#4-2");
+ }
+
+ [Test]
+ public void GetRouteData40 ()
+ {
+ // {} matches and substitutes even at partial state ...
+ var r = new Route ("{foo}/bar{baz}", null);
+ var hc = new HttpContextStub ("~/x/bartes", String.Empty);
+ var rd = r.GetRouteData (hc);
+ Assert.IsNotNull (rd, "#1");
+ Assert.AreEqual (r, rd.Route, "#2");
+ Assert.AreEqual (0, rd.DataTokens.Count, "#3");
+ Assert.AreEqual (2, rd.Values.Count, "#4");
+ Assert.AreEqual ("x", rd.Values ["foo"], "#4-1");
+ Assert.AreEqual ("tes", rd.Values ["baz"], "#4-2");
+ }
+
+ [Test]
+ public void GetRouteData41 ()
+ {
+ // {} matches and substitutes even at partial state ...
+ var r = new Route ("{foo}/bartes{baz}", null);
+ var hc = new HttpContextStub ("~/x/bartest", String.Empty);
+ var rd = r.GetRouteData (hc);
+ Assert.IsNotNull (rd, "#1");
+ Assert.AreEqual (r, rd.Route, "#2");
+ Assert.AreEqual (0, rd.DataTokens.Count, "#3");
+ Assert.AreEqual (2, rd.Values.Count, "#4");
+ Assert.AreEqual ("x", rd.Values ["foo"], "#4-1");
+ Assert.AreEqual ("t", rd.Values ["baz"], "#4-2");
+ }
+
+ [Test]
+ public void GetRouteData42 ()
+ {
+ // {} matches and substitutes even at partial state ...
+ var r = new Route ("{foo}/bartes{baz}", null);
+ var hc = new HttpContextStub ("~/x/bartest1", String.Empty);
+ var rd = r.GetRouteData (hc);
+ Assert.IsNotNull (rd, "#1");
+ Assert.AreEqual (r, rd.Route, "#2");
+ Assert.AreEqual (0, rd.DataTokens.Count, "#3");
+ Assert.AreEqual (2, rd.Values.Count, "#4");
+ Assert.AreEqual ("x", rd.Values ["foo"], "#4-1");
+ Assert.AreEqual ("t1", rd.Values ["baz"], "#4-2");
+ }
+
+ [Test]
+ public void GetRouteData43 ()
+ {
+ // {} matches and substitutes even at partial state ...
+ var r = new Route ("{foo}-{bar}-{baz}", null);
+ var hc = new HttpContextStub ("~/--", String.Empty);
+ var rd = r.GetRouteData (hc);
+ Assert.IsNull (rd, "#1");
+
+ hc = new HttpContextStub ("~/1-2-3", String.Empty);
+ rd = r.GetRouteData (hc);
+ Assert.IsNotNull (rd, "#2");
+ Assert.AreEqual (r, rd.Route, "#2");
+ Assert.AreEqual (0, rd.DataTokens.Count, "#3");
+ Assert.AreEqual (3, rd.Values.Count, "#4");
+ Assert.AreEqual ("1", rd.Values ["foo"], "#4-1");
+ Assert.AreEqual ("2", rd.Values ["bar"], "#4-2");
+ Assert.AreEqual ("3", rd.Values ["baz"], "#4-2");
+ }
+
[Test]
[ExpectedException (typeof (ArgumentNullException))]
public void GetVirtualPathNullContext ()
class HttpContextStub : HttpContextBase
{
HttpRequestStub req;
+ bool returnNullRequest;
public HttpContextStub ()
: this (null)
{
}
+ public HttpContextStub (bool returnNullRequest)
+ : this (null)
+ {
+ this.returnNullRequest = returnNullRequest;
+ }
+
public HttpContextStub (string dummyRequestPath)
: this (dummyRequestPath, null)
{
}
public override HttpRequestBase Request {
- get { return req != null ? req : base.Request; }
+ get {
+ if (returnNullRequest)
+ return null;
+
+ return req != null ? req : base.Request;
+ }
}
}
{
this.response = response;
}
+
+ public void SetRequest (HttpRequestStub request)
+ {
+ this.request = request;
+ }
}
class HttpRequestStub2 : HttpRequestStub
public string RewrittenPath { get; set; }
}
+#if NET_4_0
+ class FakeHttpRequestWrapper : HttpRequestWrapper
+ {
+ string requestUrl;
+ string path;
+ string appPath;
+
+ public FakeHttpRequestWrapper (string requestUrl, string path, string appPath)
+ : base (new HttpRequest (path, "http://localhost/", String.Empty))
+ {
+ this.requestUrl = requestUrl;
+ this.path = path;
+ this.appPath = appPath;
+ }
+
+ public override string AppRelativeCurrentExecutionFilePath
+ {
+ get
+ {
+ return appPath;
+ }
+ }
+ }
+
+ class HttpContextStub4 : HttpContextStub3
+ {
+ HttpRequestWrapper wrapper;
+ public override HttpRequestBase Request
+ {
+ get
+ {
+ return wrapper;
+ }
+ }
+
+ public HttpContextStub4 (string requestUrl, string path, string appPath, bool supportHandler)
+ : base (requestUrl, path, appPath, supportHandler)
+ {
+ wrapper = new FakeHttpRequestWrapper (requestUrl, path, appPath);
+ }
+ }
+
+ class HttpContextStub5 : HttpContextStub2
+ {
+ HttpRequestWrapper wrapper;
+
+ public override HttpRequestBase Request
+ {
+ get
+ {
+ return wrapper;
+ }
+ }
+
+ public HttpContextStub5 ()
+ : this (null, null)
+ {
+ }
+
+ public HttpContextStub5 (string requestUrl, string path)
+ : this (requestUrl, path, null)
+ {
+
+ }
+
+ public HttpContextStub5 (string requestUrl, string path, string appPath)
+ : base (requestUrl, path, appPath)
+ {
+ wrapper = new FakeHttpRequestWrapper (requestUrl, path, appPath);
+ }
+ }
+#endif
public class MyStopRoutingHandler : StopRoutingHandler
{
public IHttpHandler CallGetHttpHandler (RequestContext rc)
m.PostResolveRequestCache (new HttpContextStub2 ("~/foo/bar", null));
}
+#if !NET_4_0
[Test]
[ExpectedException (typeof (InvalidOperationException))]
public void PostResolveRequestCacheNullHttpHandler ()
{
var m = new UrlRoutingModule ();
RouteTable.Routes.Add (new MyRoute ("foo/bar", new NullRouteHandler ()));
+
m.PostResolveRequestCache (new HttpContextStub2 ("~/foo/bar", null));
}
-
+#endif
[Test]
[ExpectedException (typeof (NotImplementedException))]
public void PostResolveRequestCacheNoPath ()
m.PostResolveRequestCache (new HttpContextStub2 ("~/foo/bar", null));
}
+#if !NET_4_0
[Test]
public void PostResolveRequestCacheCallRewritePath ()
{
Assert.AreEqual ("~/UrlRouting.axd", ex.Message, "#2");
}
}
-
+#endif
[Test]
public void PostResolveRequestCache ()
{
var m = new UrlRoutingModule ();
RouteTable.Routes.Add (new MyRoute ("{foo}/{bar}", new MyRouteHandler ()));
+#if NET_4_0
+ var hc = new HttpContextStub4 ("~/x/y", "z", "apppath", false);
+#else
var hc = new HttpContextStub3 ("~/x/y", "z", "apppath", false);
+#endif
hc.SetResponse (new HttpResponseStub (2));
m.PostResolveRequestCache (hc);
+#if NET_4_0
+ Assert.AreEqual (null, hc.RewrittenPath, "#1");
+#else
Assert.AreEqual ("~/UrlRouting.axd", hc.RewrittenPath, "#1");
+#endif
// it internally stores the handler
}
{
var m = new UrlRoutingModule ();
RouteTable.Routes.Add (new MyRoute ("{foo}/{bar}", new MyRouteHandler ()));
+#if NET_4_0
+ var hc = new HttpContextStub4 ("~/x/y", "z", "apppath", true);
+#else
var hc = new HttpContextStub3 ("~/x/y", "z", "apppath", true);
+#endif
hc.HttpHandler = new MyHttpHandler ();
hc.SetResponse (new HttpResponseStub (2));
m.PostResolveRequestCache (hc);
+#if NET_4_0
+ Assert.AreEqual (null, hc.RewrittenPath, "#1");
+#else
Assert.AreEqual ("~/UrlRouting.axd", hc.RewrittenPath, "#1");
+#endif
// It tries to set Handler and causes NIE
m.PostMapRequestHandler (hc);
}
[Test]
+#if !NET_4_0
[ExpectedException (typeof (ApplicationException))]
+#endif
public void Pipeline3 ()
{
var m = new UrlRoutingModule ();
RouteTable.Routes.Add (new MyRoute ("{foo}/{bar}", new MyRouteHandler ()));
+#if NET_4_0
+ var hc = new HttpContextStub5 ("~/x/y", String.Empty, "apppath");
+#else
var hc = new HttpContextStub2 ("~/x/y", String.Empty, "apppath");
+#endif
hc.SetResponse (new HttpResponseStub (2));
+#if NET_4_0
+ Assert.IsNull (m.RouteCollection.GetRouteData (hc), "#0");
+#else
Assert.IsNotNull (m.RouteCollection.GetRouteData (hc), "#0");
m.PostResolveRequestCache (hc);
try {
} catch (ApplicationException ex) {
Assert.AreEqual ("~/UrlRouting.axd", ex.Message, "#2");
}
+#endif
}
}
}
public PageRouteHandler (string virtualPath, bool checkPhysicalUrlAccess)
{
+ if (String.IsNullOrEmpty (virtualPath) || !virtualPath.StartsWith ("~/"))
+ throw new ArgumentException ("VirtualPath must be a non empty string starting with ~/", "virtualPath");
+
VirtualPath = virtualPath;
CheckPhysicalUrlAccess = checkPhysicalUrlAccess;
}