November Happy Hour will be moved to Thursday December 5th.

PartialRouting broken in 7.5?

Vote:
 

We are using PartialRouting in our 7.1 site and that is working great but when I upgraded to 7.5 I kept getting a 404 error for those pages inside EPiServer (OnPageEdit-mode). I have solved it in the most ugly way it can be solved by checking for a queryparameter in the request. 
The problem is that it does not identify that it is in PageEditMode so it returns the wrong url to EPiServer. In code. This used to work:

public PartialRouteData GetPartialVirtualPath(
          EducationLocationPage content,
          string language,
          RouteValueDictionary routeValues,
          RequestContext requestContext)
        {
            var contentLink = ContentRoute.GetValue("node", requestContext, routeValues) as ContentReference;

            if (!content.ContentLink.CompareToIgnoreWorkID(contentLink))
            {
                return null;
            }

            if (PageEditing.PageIsInEditMode) return null;

            return new PartialRouteData
            {
                BasePathRoot = ContentReference.StartPage,
                PartialVirtualPath = getPublicUrl(content)
            };
        }

And in 7.5 I had to do like this to be able to get it to work:
public PartialRouteData GetPartialVirtualPath(
          EducationLocationPage content,
          string language,
          RouteValueDictionary routeValues,
          RequestContext requestContext)
        {
            var contentLink = ContentRoute.GetValue("node", requestContext, routeValues) as ContentReference;

            if (!content.ContentLink.CompareToIgnoreWorkID(contentLink))
            {
                return null;
            }

            if (IsInEditMode(requestContext)) return null;

            return new PartialRouteData
            {
                BasePathRoot = ContentReference.StartPage,
                PartialVirtualPath = getPublicUrl(content)
            };
        }

        private static bool IsInEditMode(RequestContext requestContext)
        {
            var uri = requestContext.HttpContext.Request["uri"];
            if (PageEditing.PageIsInEditMode || (!string.IsNullOrEmpty(uri) && uri.Contains("epi.cms.contentdata")))
            {
                return true;
            }
            return false;
        }
    

How can I solve this in a better way?
#81928
Feb 28, 2014 13:46
Vote:
 

You could try to replace 

if (PageEditing.PageIsInEditMode) return null;

with

if (EPiServer.Web.Routing.Segments.RequestSegmentContext.CurrentContextMode != ContextMode.Default) return null;

    

#81929
Edited, Feb 28, 2014 14:06
Vote:
 

I tried that but CurrentContextMode always returned as ContextMode.Default

#81932
Feb 28, 2014 14:24
Vote:
 

What is HttpContext.Current.Request.Url?

#81933
Feb 28, 2014 14:27
Vote:
 

requestContext.HttpContext.Request.Url  = http://lernia.se.local/EPiServer/shell/Stores/context/?uri=epi.cms.contentdata:///20048&dojo.preventCache=1393594567297

#81935
Feb 28, 2014 14:38
Vote:
 

HttpContext.Current is the same

HttpContext.Current.Request.Url = http://lernia.se.local:80/EPiServer/shell/Stores/context/?uri=epi.cms.contentdata%3A%2F%2F%2F20048&dojo.preventCache=1393594767850

#81936
Feb 28, 2014 14:41
Vote:
 

That is a REST request from one of the stores used in Edit mode (that is it is not the "preview" request). I am not sure why your partial router is called in that case, what does the call stack look like?

#81937
Feb 28, 2014 14:42
Vote:
 

Here are the call stack for one of the request to the partial router

> LerniaSE.Web.dll!LerniaSE.Web.Framework.Routing.EducationLocationRouter.GetPartialVirtualPath(LerniaSE.Web.Models.Pages.EducationLocationPage content, string language, System.Web.Routing.RouteValueDictionary routeValues, System.Web.Routing.RequestContext requestContext) Line 64 C#
EPiServer.dll!EPiServer.Web.Routing.Segments.PartialSegment.GetVirtualPathSegment(System.Web.Routing.RequestContext requestContext, System.Web.Routing.RouteValueDictionary values, System.Collections.Generic.HashSet<string> usedValues) Unknown
EPiServer.dll!EPiServer.Web.Routing.ContentRoute.AddVirtualPathFromSegments(System.Text.StringBuilder virtualPath, System.Web.Routing.RequestContext requestContext, System.Web.Routing.RouteValueDictionary values, System.Collections.Generic.HashSet<string> usedValues, int lastNonDefaultIndex) Unknown
EPiServer.dll!EPiServer.Web.Routing.ContentRoute.GetVirtualPath(System.Web.Routing.RequestContext requestContext, System.Web.Routing.RouteValueDictionary values) Unknown
EPiServer.dll!EPiServer.Web.Routing.UrlResolver.GetUrlFromRoute(EPiServer.Core.ContentReference contentRefernce, string language, System.Web.Routing.RouteValueDictionary routeValues, System.Web.Routing.RequestContext requestContext) Unknown
EPiServer.dll!EPiServer.Web.Routing.UrlResolver.GetVirtualPath(EPiServer.Core.ContentReference contentLink, string language, EPiServer.Web.ContextMode contextMode, System.Web.Routing.RouteValueDictionary routeValues, System.Web.Routing.RequestContext requestContext) Unknown
EPiServer.dll!EPiServer.Web.Routing.UrlResolver.GetVirtualPath(EPiServer.Core.ContentReference contentLink, string language, EPiServer.Web.Routing.VirtualPathArguments virtualPathArguments) Unknown
EPiServer.dll!EPiServer.Web.Routing.UrlResolver.GetUrl(EPiServer.Core.ContentReference contentLink, string language, EPiServer.Web.Routing.VirtualPathArguments virtualPathArguments) Unknown
EPiServer.Cms.Shell.UI.dll!EPiServer.Cms.Shell.IContentExtensions.PublicUrl(EPiServer.Core.IContent content, EPiServer.Web.Routing.UrlResolver urlResolver) Unknown
EPiServer.Cms.Shell.UI.dll!EPiServer.Cms.Shell.UI.Rest.CmsContentContextResolver.ToContentDataContext(EPiServer.Core.ContentReference requestedContentReference, EPiServer.Core.IContent content, EPiServer.Cms.Shell.UI.Rest.ContentLanguageInformation languageInformation, System.Uri requestedUri) Unknown
EPiServer.Cms.Shell.UI.dll!EPiServer.Cms.Shell.UI.Rest.CmsContentContextResolver.TryResolveUri(System.Uri uri, out EPiServer.Shell.Rest.ClientContextBase instance) Unknown
EPiServer.Shell.UI.dll!EPiServer.Shell.UI.Rest.ContextStore.ResolveUri(System.Uri uri) Unknown
[Lightweight Function]
System.Web.Mvc.dll!System.Web.Mvc.ReflectedActionDescriptor.Execute(System.Web.Mvc.ControllerContext controllerContext, System.Collections.Generic.IDictionary<string,object> parameters) Unknown
System.Web.Mvc.dll!System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(System.Web.Mvc.ControllerContext controllerContext, System.Web.Mvc.ActionDescriptor actionDescriptor, System.Collections.Generic.IDictionary<string,object> parameters) Unknown
System.Web.Mvc.dll!System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodWithFilters.AnonymousMethod__10() Unknown
System.Web.Mvc.dll!System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(System.Web.Mvc.IActionFilter filter, System.Web.Mvc.ActionExecutingContext preContext, System.Func<System.Web.Mvc.ActionExecutedContext> continuation) Unknown
System.Web.Mvc.dll!System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(System.Web.Mvc.IActionFilter filter, System.Web.Mvc.ActionExecutingContext preContext, System.Func<System.Web.Mvc.ActionExecutedContext> continuation) Unknown
System.Web.Mvc.dll!System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(System.Web.Mvc.IActionFilter filter, System.Web.Mvc.ActionExecutingContext preContext, System.Func<System.Web.Mvc.ActionExecutedContext> continuation) Unknown
System.Web.Mvc.dll!System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(System.Web.Mvc.IActionFilter filter, System.Web.Mvc.ActionExecutingContext preContext, System.Func<System.Web.Mvc.ActionExecutedContext> continuation) Unknown
System.Web.Mvc.dll!System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodWithFilters(System.Web.Mvc.ControllerContext controllerContext, System.Collections.Generic.IList<System.Web.Mvc.IActionFilter> filters, System.Web.Mvc.ActionDescriptor actionDescriptor, System.Collections.Generic.IDictionary<string,object> parameters) Unknown
System.Web.Mvc.dll!System.Web.Mvc.ControllerActionInvoker.InvokeAction(System.Web.Mvc.ControllerContext controllerContext, string actionName) Unknown
EPiServer.Shell.dll!EPiServer.Shell.Services.Rest.RestControllerBase.ExecuteCore() Unknown
System.Web.Mvc.dll!System.Web.Mvc.ControllerBase.Execute(System.Web.Routing.RequestContext requestContext) Unknown
EPiServer.Shell.dll!EPiServer.Shell.Services.Rest.RestHttpHandler.ProcessRequest(System.Web.HttpContextBase httpContext) Unknown
System.Web.dll!System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() Unknown
System.Web.dll!System.Web.HttpApplication.ExecuteStep(System.Web.HttpApplication.IExecutionStep step, ref bool completedSynchronously) Unknown
System.Web.dll!System.Web.HttpApplication.PipelineStepManager.ResumeSteps(System.Exception error) Unknown
System.Web.dll!System.Web.HttpApplication.BeginProcessRequestNotification(System.Web.HttpContext context, System.AsyncCallback cb) Unknown
System.Web.dll!System.Web.HttpRuntime.ProcessRequestNotificationPrivate(System.Web.Hosting.IIS7WorkerRequest wr, System.Web.HttpContext context) Unknown
System.Web.dll!System.Web.Hosting.PipelineRuntime.ProcessRequestNotificationHelper(System.IntPtr rootedObjectsPointer, System.IntPtr nativeRequestContext, System.IntPtr moduleData, int flags) Unknown
System.Web.dll!System.Web.Hosting.PipelineRuntime.ProcessRequestNotification(System.IntPtr rootedObjectsPointer, System.IntPtr nativeRequestContext, System.IntPtr moduleData, int flags) Unknown
[Native to Managed Transition]
[Managed to Native Transition]
System.Web.dll!System.Web.Hosting.PipelineRuntime.ProcessRequestNotificationHelper(System.IntPtr rootedObjectsPointer, System.IntPtr nativeRequestContext, System.IntPtr moduleData, int flags) Unknown
System.Web.dll!System.Web.Hosting.PipelineRuntime.ProcessRequestNotification(System.IntPtr rootedObjectsPointer, System.IntPtr nativeRequestContext, System.IntPtr moduleData, int flags) Unknown
[AppDomain Transition]

#81941
Feb 28, 2014 14:47
Vote:
 

From the call stack it seems the request originates from

IContentExtensions.PublicUrl(this IContent) 

so it should get the public url meaning it should get the url for ContextMode.Default.

How/Where do you see/get the 404?

#81942
Feb 28, 2014 14:53
Vote:
 

I get it when calling for example this page

http://lernia.se.local/EPiServer/Cms#context=epi.cms.contentdata:///20048

And I see it in the OnPageEdit-iframe

#81944
Feb 28, 2014 14:59
Vote:
 

My guess is that your code is also called in a stackframe with 

IContentExtensions.PreviewUrl(this IContent) 

which will be used to generate the preview url, and the return value from there is what is causing the 404. 

However in this case you should not use PageEditing.PageIsInEditMode or EPiServer.Web.Routing.Segments.RequestSegmentContext.CurrentContextMode since both of those are designed for "ordinary" content request (that is for REST store request they will always say ContextMode.Default) and checks for the "Main" request. 

Instead you should use the passed in parameter requestContext (is not the same as on HttpContext.Current) and check 

if (requestContext.GetContextMode() != ContextMode.Default) return null;

    

GetContextMode is an extension method so add a using for EPiServer.Web.Routing. 

 

    

 

#81945
Edited, Feb 28, 2014 15:17
Vote:
 

Working great!

Thanks!

#81946
Feb 28, 2014 15:22
This topic was created over six months ago and has been resolved. If you have a similar question, please create a new topic and refer to this one.
* You are NOT allowed to include any hyperlinks in the post because your account hasn't associated to your company. User profile should be updated.