Copied to clipboard

Flag this post as spam?

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


  • Robert Gillman 7 posts 78 karma points
    Nov 29, 2016 @ 01:34
    Robert Gillman
    0

    Overriding 404 and routing to custom controller/view

    Wasn't quite sure how to word that title, but I'll try my best to explain the situation.

    So we have all the site content under one "Homepage" node, but also a second "Components" node which stores all the large-list data, such as list of people with usually thousands of records. Each of those people is represented by (let's say) a "Person" doctype with a corresponding model in a "Parts" namespace (ie. Site.Application.Models.Parts.Person).

    This list of people is rendered into a table using React, but because the data is imported, we can't set the template, and the document url is not user friendly. So in the model I am generating a user friendly url, but of course following that reaches a 404 page.

    Since the url is in a format such as mysite.com/content/person-database/john-smith-1234, I need Umbraco to parse that url and pass that Person model to a Person view.

  • Dennis Adolfi 1082 posts 6447 karma points MVP 5x c-trib
    Nov 29, 2016 @ 10:19
    Dennis Adolfi
    0

    Hi Robert.

    It sounds like you need to create you own ContentFinder and Custom UrlProvider. That way you can either set you own custom URL.s for all the persons, or catch the url that otherwise becomes a 404, and based on the url find the correct Person to return to the view.

    Jeroen Breuer wrote a very good tutorial on how to do this. Its from 2014 but it still works the same. Have a look at this URL: http://24days.in/umbraco/2014/urlprovider-and-contentfinder/.

    Best of luck to you!!

  • Marc Goodson 2148 posts 14353 karma points MVP 8x c-trib
    Nov 29, 2016 @ 10:22
    Marc Goodson
    2

    Hi Robert

    You have a couple of options,

    1) add a rule for finding your content in Umbraco based on your nice url

    or

    2) map a custom Umbraco route for your Url pattern to a custom RenderMvcController that can then build your model and pass to whichever template/view you require.

    First Option:

    To add a rule, you create a class that implements the interface IContentFinder eg:

    public class FindContentByMyNiceUrlFormat : IContentFinder
      {
          public bool TryFindContent(PublishedContentRequest contentRequest)
         {
           // read in the path from the PublishedContentRequest.
           var path = contentRequest.Uri.AbsolutePath;
    
           // find your published content item based on the requested url
    
           var umbracoHelper = new UmbracoHelper(UmbracoContext.Current);
    

    // for example this would look for a TextPage document with a property called 'nicerUrl' ,matching the path var matchingContent = umbracoHelper.TypedContentSingleAtXPath("//TextPage[nicerUrl/text() = '" + path + "']");

           if (matchingContent == null)
           {
    // return false, there is no matching content
               return false;
           }  
                contentRequest.PublishedContent = matchingContent;
    return true;
      }
      }
    

    Once you have your IContentFinder rule, you register with Umbraco by using the ContentFinderResolver on application startup: ContentFinderResolver.Current.InsertTypeBefore

    to add your rule to the queue of ContentFinders...

    More information on IContentFinders can be found here:

    https://our.umbraco.org/documentation/reference/routing/request-pipeline/icontentfinder

    Second Option

    To map a custom route through Umbraco see https://our.umbraco.org/documentation/Reference/Routing/custom-routes

    but basically you again OnApplicationStarting, you can register custom umbraco routes by adding a mapping to the routes table:

    routes.MapUmbracoRoute(
        "test",
        "Products/{action}/{sku}",
        new
        {
            controller = "MyProduct",
            sku = UrlParameter.Optional
        },
        new UmbracoVirtualNodeByIdRouteHandler(1234));
    

    This example maps all requests from /Products/action/productref through to a specific mvc controller called MyProductController, which must inherit RenderMvcController

    In order for this to work Umbraco needs to have an IPublishedContent item to associate with the request, and you achieve this by creating an UmbracoVirtualNodeRouteHandler (in the example above there is one in the core that hardcodes the request to an id 1234) - But you can create your own rules here by creating a class that inherits UmbracoVirtualNodeRouteHandler, and override FindContent and then use it in the Mapping above.

    Then in your controller's details action you can return a view:

    public ActionResult Details(RenderModel model, string sku) { if (model == null || model.Content == null || String.IsNullOrEmpty(sku)) { return HttpNotFound(); }

       var product = ProductService.GetById(sku);
       var vm = new ProductViewModel(model.Content);
    

    //map properties to your view model Mapper.Map(product, vm); return View(vm); }

    Conclusion

    I think an IContentFinder is the simplest way to do the job, but you mention building a custom model, and so the Custom Route will give you more control over what is passed to the view.

Please Sign in or register to post replies

Write your reply to:

Draft