From d9eb8b426ce945b223f44f9d837cb1b4a305e23a Mon Sep 17 00:00:00 2001 From: "shannon@ShandemVaio" Date: Tue, 7 Aug 2012 04:55:27 +0600 Subject: [PATCH] Added TODO notes for NiceUrlProvider to fix an issue for Stephan. --- src/Umbraco.Tests/UmbracoModuleTests.cs | 18 +- src/Umbraco.Web/Routing/NiceUrlProvider.cs | 15 +- src/Umbraco.Web/UmbracoModule.cs | 185 +++++++-------------- 3 files changed, 81 insertions(+), 137 deletions(-) diff --git a/src/Umbraco.Tests/UmbracoModuleTests.cs b/src/Umbraco.Tests/UmbracoModuleTests.cs index d12fbd80e8..c4a9fa3e8f 100644 --- a/src/Umbraco.Tests/UmbracoModuleTests.cs +++ b/src/Umbraco.Tests/UmbracoModuleTests.cs @@ -130,11 +130,9 @@ namespace Umbraco.Tests Assert.AreEqual(assert, result); } - [TestCase("/default.aspx?path=/", true)] - [TestCase("/default.aspx?path=/home.aspx", true)] - [TestCase("/default.aspx?path=/home.aspx?altTemplate=blah", true)] - [TestCase("/default.aspx?p=/home.aspx", false)] //missing path - [TestCase("/defaul.aspx?path=/home.aspx", false)] //not default path + [TestCase("/", true)] + [TestCase("/home.aspx", true)] + [TestCase("/home.aspx?altTemplate=blah", true)] public void Process_Front_End_Document_Request(string url, bool assert) { var httpContextFactory = new FakeHttpContextFactory(url); @@ -159,11 +157,13 @@ namespace Umbraco.Tests SetupUmbracoContextForTest(umbracoContext, template); - var result = _module.ProcessFrontEndDocumentRequest( - httpContext, - umbracoContext); + _module.AssignDocumentRequest(httpContext, umbracoContext, httpContext.Request.Url); - Assert.AreEqual(assert, result); + Assert.AreEqual(assert, umbracoContext.DocumentRequest != null); + if (assert) + { + Assert.AreEqual(assert, umbracoContext.DocumentRequest.Node != null); + } } diff --git a/src/Umbraco.Web/Routing/NiceUrlProvider.cs b/src/Umbraco.Web/Routing/NiceUrlProvider.cs index dd3c370332..28ee454493 100644 --- a/src/Umbraco.Web/Routing/NiceUrlProvider.cs +++ b/src/Umbraco.Web/Routing/NiceUrlProvider.cs @@ -70,8 +70,19 @@ namespace Umbraco.Web.Routing // route is / eg "-1/", "-1/foo", "123/", "123/foo/bar"... int pos = route.IndexOf('/'); path = route.Substring(pos); - int id = int.Parse(route.Substring(0, pos)); // will be -1 or 1234 - domainUri = id > 0 ? DomainUriAtNode(id, current) : null; + + //TODO: Fix this! When I view a node on the front-end (for example the root) it + // caches the route as '/' + // then when i view that node in the back office, this used to throw an exception + // because there was not '-1' prefixing it. + // If i reset the app pool, then go look at the node in the back office, it caches it as '-1/' + // so there are inconsistencies on how these routes are cached! + + int id = int.Parse(route.Substring(0, pos));// will be -1 or 1234 + + domainUri = id > 0 ? DomainUriAtNode(id, current) : null; + + } else { diff --git a/src/Umbraco.Web/UmbracoModule.cs b/src/Umbraco.Web/UmbracoModule.cs index 065e669c74..293472d327 100644 --- a/src/Umbraco.Web/UmbracoModule.cs +++ b/src/Umbraco.Web/UmbracoModule.cs @@ -32,65 +32,41 @@ namespace Umbraco.Web /// /// /// - internal bool ProcessFrontEndDocumentRequest( + /// + internal void AssignDocumentRequest( HttpContextBase httpContext, - UmbracoContext umbracoContext) + UmbracoContext umbracoContext, + Uri uri) { if (httpContext == null) throw new ArgumentNullException("httpContext"); if (umbracoContext == null) throw new ArgumentNullException("umbracoContext"); if (umbracoContext.RoutingContext == null) throw new ArgumentNullException("umbracoContext.RoutingContext"); - if (httpContext.Request.Url.LocalPath.InvariantStartsWith("/default.aspx") - && !string.IsNullOrWhiteSpace(httpContext.Request.QueryString["path"])) - { - //the path is the original path that the request came in on before we've rewritten it, - //this is required because TransferRequest does not maintain the httpcontext - var path = httpContext.Request.QueryString["path"]; - var qry = httpContext.Request.QueryString["qry"]; - Uri uri; - try - { - uri = UriUtility.ToFullUrl(path + qry, httpContext); - } - catch (Exception ex) - { - //if this fails then the path could not be parsed to a Uri which could be something malicious - LogHelper.Error(string.Format("Could not parse the path {0} into a full Uri", path), ex); - return false; - } + //Create a document request since we are rendering a document on the front-end - //Create a document request since we are rendering a document on the front-end - - // create the new document request which will cleanup the uri once and for all - var docreq = new DocumentRequest(uri, umbracoContext); - //assign the routing context to the umbraco context - umbracoContext.DocumentRequest = docreq; + // create the new document request which will cleanup the uri once and for all + var docreq = new DocumentRequest(uri, umbracoContext); + //assign the routing context to the umbraco context + umbracoContext.DocumentRequest = docreq; - // note - at that point the original legacy module did something do handle IIS custom 404 errors - // ie pages looking like /anything.aspx?404;/path/to/document - I guess the reason was to support - // "directory urls" without having to do wildcard mapping to ASP.NET on old IIS. This is a pain - // to maintain and probably not used anymore - removed as of 06/2012. @zpqrtbnk. - // - // to trigger Umbraco's not-found, one should configure IIS and/or ASP.NET custom 404 errors - // so that they point to a non-existing page eg /redirect-404.aspx + // note - at that point the original legacy module did something do handle IIS custom 404 errors + // ie pages looking like /anything.aspx?404;/path/to/document - I guess the reason was to support + // "directory urls" without having to do wildcard mapping to ASP.NET on old IIS. This is a pain + // to maintain and probably not used anymore - removed as of 06/2012. @zpqrtbnk. + // + // to trigger Umbraco's not-found, one should configure IIS and/or ASP.NET custom 404 errors + // so that they point to a non-existing page eg /redirect-404.aspx - docreq.LookupDomain(); - if (docreq.IsRedirect) - httpContext.Response.Redirect(docreq.RedirectUrl, true); - Thread.CurrentThread.CurrentUICulture = Thread.CurrentThread.CurrentCulture = docreq.Culture; - docreq.LookupDocument(); - if (docreq.IsRedirect) - httpContext.Response.Redirect(docreq.RedirectUrl, true); + docreq.LookupDomain(); + if (docreq.IsRedirect) + httpContext.Response.Redirect(docreq.RedirectUrl, true); + Thread.CurrentThread.CurrentUICulture = Thread.CurrentThread.CurrentCulture = docreq.Culture; + docreq.LookupDocument(); + if (docreq.IsRedirect) + httpContext.Response.Redirect(docreq.RedirectUrl, true); - if (docreq.Is404) - httpContext.Response.StatusCode = 404; - - // it is up to default.aspx to figure out what to display in case - // there is no document (ugly 404 page?) or no template (blank page?) - return true; - } - - return false; + if (docreq.Is404) + httpContext.Response.StatusCode = 404; } /// @@ -177,27 +153,23 @@ namespace Umbraco.Web //assign the routing context back to the umbraco context umbracoContext.RoutingContext = routingContext; - //Does a check to see if this current request contains the information in order to process the - //request as a front-end request. If not, then its because the rewrite hasn't taken place yet. - //if we need to rewrite, then we'll cleanup the query strings and rewrite to the front end handler. - if (!ProcessFrontEndDocumentRequest(httpContext, umbracoContext)) + var uri = httpContext.Request.Url; + var lpath = uri.AbsolutePath.ToLower(); + + // legacy - no idea what this is + LegacyCleanUmbPageFromQueryString(ref uri, ref lpath); + + //do not continue if this request is not a front-end routable page + if (EnsureUmbracoRoutablePage(uri, lpath, httpContext)) { - var uri = httpContext.Request.Url; - var lpath = uri.AbsolutePath.ToLower(); + //create and assign the document request now that we know its a document being rendered on the front end + AssignDocumentRequest(httpContext, umbracoContext, uri); - // legacy - no idea what this is - LegacyCleanUmbPageFromQueryString(ref uri, ref lpath); - - //do not continue if this request is not a front-end routable page - if (EnsureUmbracoRoutablePage(uri, lpath, httpContext)) - { - RewriteToPath(HttpContext.Current, lpath, uri.Query); - //RewriteToPath(HttpContext.Current, "", docreq.Uri.Query); - } - else - { - LogHelper.Debug("End processing request, not transfering to handler {0}", () => uri); - } + RewriteToUmbracoHandler(HttpContext.Current, uri.Query, false); + } + else + { + LogHelper.Debug("End processing request, not transfering to handler {0}", () => uri); } @@ -343,72 +315,33 @@ namespace Umbraco.Web return true; } - private static void RewriteToPath(HttpContext context, string currentPath, string currentQuery) - where THandler : IHttpHandler + /// + /// Rewrites to the Umbraco handler. + /// NOTE: this is a WIP until MVC is implemented properly, currently only webforms is supported. + /// + /// + /// + /// + private static void RewriteToUmbracoHandler(HttpContext context, string currentQuery, bool isMvc) { - - if ((context.CurrentHandler is THandler)) return; - - var rewritePath = "~/default.aspx?path=" - + context.Server.UrlEncode(currentPath) - + "&qry=" - + context.Server.UrlEncode(currentQuery); - - if (currentPath.StartsWith(rewritePath, StringComparison.InvariantCultureIgnoreCase)) return; - - var isMvc = TypeHelper.IsTypeAssignableFrom(typeof(MvcHandler)); + var rewritePath = "~/default.aspx" + currentQuery; LogHelper.Debug("Transfering to " + rewritePath); - if (HttpRuntime.UsingIntegratedPipeline) + //NOTE: We do not want to use TransferRequest even though many docs say it is better with IIS7, turns out this is + //not what we need. The purpose of TransferRequest is to ensure that .net processes all of the rules for the newly + //rewritten url, but this is not what we want! + // http://forums.iis.net/t/1146511.aspx + + // Pre MVC 3 + context.RewritePath(rewritePath, false); + if (isMvc) { - context.Server.TransferRequest(rewritePath, true); - } - else - { - // Pre MVC 3 - context.RewritePath(rewritePath, false); - if (isMvc) - { - IHttpHandler httpHandler = new MvcHttpHandler(); - httpHandler.ProcessRequest(context); - } + IHttpHandler httpHandler = new MvcHttpHandler(); + httpHandler.ProcessRequest(context); } } - //// transfers the request using the fastest method available on the server - //void TransferRequest(string path, HttpContextBase httpContext) - //{ - // LogHelper.Debug("Transfering to " + path); - - // var integrated = HttpRuntime.UsingIntegratedPipeline; - - // // fixme - are we doing this properly? - // // fixme - handle virtual directory? - // // fixme - this does not work 'cos it resets the HttpContext - // // so we should move the DocumentRequest stuff etc back to default.aspx? - // // but, also, with TransferRequest, auth & co will run on the new (default.aspx) url, - // // is that really what we want? I need to talk about it with others. @zpqrtbnk - - // // NOTE: SD: Need to look at how umbraMVCo does this. It is true that the TransferRequest initializes a new HttpContext, - // // what we need to do is when we transfer to the handler we send a query string with the found page Id to be looked up - // // after we have done our routing check. This however needs some though as we don't want to have to query for this - // // page twice. Again, I'll check how umbraMVCo is doing it as I had though about that when i created it :) - - // integrated = false; - - // // http://msmvps.com/blogs/luisabreu/archive/2007/10/09/are-you-using-the-new-transferrequest.aspx - // // http://msdn.microsoft.com/en-us/library/aa344903.aspx - // // http://forums.iis.net/t/1146511.aspx - - // if (integrated) - // httpContext.Server.TransferRequest(path); - // else - // httpContext.RewritePath(path); - //} - - - #region Legacy // "Clean umbPage from querystring, caused by .NET 2.0 default Auth Controls"