Handling QueryString in Custom Item Resolver processor MVC

  • Twitter
  • LinkedIn

Handling QueryString in Custom Item Resolver processor MVC

On a recent project I was tasked with writing a custom item resolver in Sitecore. The goal was to translate http://domain/blog/tag/tag-name to http://domain/blog?tag=tag name.

Since I had done this a before, I quickly wrote the following code

public override void Process(HttpRequestArgs args)
        {
            Assert.ArgumentNotNull(args, "args");
            if (((Context.Item == null) && (Context.Database != null)) && !string.IsNullOrWhiteSpace(args.Url.ItemPath))
            {
                Profiler.StartOperation("Custom resolver");
                try
                {
                    string qsValue = string.Empty;
                    string decodedItemName = MainUtil.DecodeName(args.Url.ItemPath);
                    string blogItemPath = ResolveBlogPath(decodedItemName, out qsValue);
                    Item blogItem = args.GetItem(blogItemPath);
                    if (blogItem != null)
                    {
                        Context.Item = blogItem;
                        NameValueCollection queryStringCollection =
                            StringUtil.ParseNameValueCollection(args.Url.QueryString, '&', '=');
                        queryStringCollection.Add("tag", qsValue);

                        args.Url.QueryString = StringUtil.NameValuesToString(queryStringCollection, "&");
                    }
                }
                catch (Exception ex)
                {
                    Log.Error("could not resolve url", ex, this);
                }
                Profiler.EndOperation();
            }
        }
        protected string ResolveBlogPath(string decodedItemName, out string qsValue)
        {
            qsValue = string.Empty;
            try
            {
                Match match = Regex.Match(StringUtil.EnsurePostfix('/', decodedItemName), @"(^.+/tag/)(.+)/$", RegexOptions.IgnoreCase);
                if (match.Success)
                {
                    qsValue = WebUtil.UrlEncode(match.Groups[2].Value);
                    return match.Groups[1].Value;
                }
            }
            catch (Exception ex)
            {
                Log.Error("could not resolve url", ex, this);
            }
            return string.Empty;
        }
    }

Next, I added my custom processor to the httpRequestBegin pipeline

 

 

The code worked fine for all WebForm pages but it did not work for any item that had MVC layout..

After some investigation and a little help from Sitecore support, I found out that Sitecore traditionally has been rewriting URL in the ExecuteRequest processor step.

        

Here is the magic code:
 args.Context.RewritePath(filePath, args.Context.Request.PathInfo, args.Url.QueryString, false);

This processor is never executed on an MVC solution as Sitecore.Mvc.config adds a new processor TransferRoutedRequest immediately after ItemResolver that routes all MVC requests to the appropriate controller, and aborts the pipeline.

The Fix

The fix is simple, all I had to do was

replace the following line:
args.Url.QueryString = StringUtil.NameValuesToString(queryStringCollection, "&");
With this line:
args.Context.RewritePath(blogItemPath, blogItem.Paths.FullPath, StringUtil.NameValuesToString(queryStringCollection, "&"));

Hope this helps you. You can read more about RewritePath on MSDN - http://msdn.microsoft.com/en-us/library/system.web.httpcontext.rewritepath(v=vs.110).aspx

Related Blogs

Latest Blogs