Copied to clipboard

Flag this post as spam?

This post will be reported to the moderators as potential spam to be looked at


  • Arjan 9 posts 62 karma points
    Jun 27, 2013 @ 10:10
    Arjan
    0

    How to map a wildcard like mysite.com/products/*

    What would be the best way in an Umbraco MVC application to map wildcard url's or MVC routes with parameters to one specific template or controller?

    This is the desired scenario:

    1. A content editor cabn make one or more pages of the document type "productcategory". Within the document it will be possible to enter a category name. 

    2. Now there will be one or more product listing pages and below that there will be product detail pages.

    Example:

    Editor creates page called /products/* or in MVC terms /products/{id}.

    Now from the browser I would like to catch all requests in my ProductsControler, e.g.:

    mysite.com/products                     ---> this shows a list of products
    mysite.com/products/iphone1         ----> this shows the iphone1 details
    mysite.com/products/note2
    mysite.com/products/galaxy3
    mysite.com/products/galaxy4

    The ProductsController is able to select the required view based on {id}, I knnow how to handle that.
    I created a solution using url rewriting. E.g. products/iphone1 becomes products?iphone1 and from there it will indeed be routed to the ProductsController. However this is a fixed solution as the rewrite rule is in a config file and the editor won't be able to create the page /produkten/{id}.

    I also created a solution by using an MVC area, which also is a fixed solution. 

    I have spend a lot of time creating custom MVC controllers but ended up with mismatching the UmbracoTemplatePage, causing lots of extra issues such as rendering navigation.
  • Arjan 9 posts 62 karma points
    Jun 30, 2013 @ 11:31
    Arjan
    100

    After 3 days of no answer it is clear to me that there is not a standard solution for url wildcards. Or maybe my quetion was not clear. In the meantime I figured out a solution. I found useful information in this post: http://our.umbraco.org/forum/developers/extending-umbraco/40567-MVC-Creating-Virtual-Pages-via-ControllersRoutes-instead-of-UrlRewriting.

    My solution uses an whic can be implemented from 6.1.0 I believe, so I still wonder how you guys solved this in previous versions. Now let me share my solution. Basically it consists of the class DemoContentFinder:

    public class DemoContentFinder : IContentFinder
    {
        public bool TryFindContent(PublishedContentRequest contentRequest)
        {
            foreach (var node in uQuery.GetNodesByType("Demo").OrderByDescending(n => n.Level))
            {
                if (contentRequest.Uri.AbsolutePath.StartsWith(node.Url + "/", StringComparison.InvariantCultureIgnoreCase))
                {
                    contentRequest.PublishedContent = new UmbracoHelper(UmbracoContext.Current).TypedContent(node.Id);
                    return true;
                }
            }
            return false;
        }
    }
    

    The class is bound in Global.asax:

    protected override void OnApplicationStarting(object sender, EventArgs e)
    {
        base.OnApplicationStarting(sender, e);
    
        ContentFinderResolver.Current.InsertType<DemoContentFinder>();
    }
    

     

    After this code all Umbraco nodes with a document type "Demo" and a path starting with the url of the current request will be resolved to 1 single node. E.g.

    mysite.com/products
    mysite.com/products/iphone1
    mysite.com/products/note2
    mysite.com/products/galaxy3
    mysite.com/products/galaxy4

    All resolve to: mysite.com/products

    From there Umbraco MVC routes to DemoController. In DemoController I parse the remaining of the url, so I can distinguish mysite.com/products from mysite.com/products/iphone1. From there either the view "Demo" is rendered by default, or the view "DemoDetail" is rendered. 

        public class DemoController : RenderMvcController
        {
            public override ActionResult Index(RenderModel model)
            {
                string parameters = Request.Url.AbsolutePath.TrimEnd('/').Substring(model.Content.Url.Length).TrimStart('/');
    
                if (!string.IsNullOrWhiteSpace(parameters))
                {
                    return View("DemoDetail"new DemoRenderModel(model, parameters.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries)));
                }
                return base.Index(model);
            }
        }

     

    Together with the model:

        public class DemoRenderModel : RenderModel
        {
            public string[] Parameters { getset; }
    
            public DemoRenderModel(RenderModel model, string[] parameters)
                : base(model.Content, model.CurrentCulture)
            {
                Parameters = parameters;
            }
        }
    

     

    The string parsing of the url is not very high-tec MVC; suggestions on how to improve are welcome.

     

Please Sign in or register to post replies

Write your reply to:

Draft