Search code examples
dotnetnukedotnetnuke-7

Is there any possibility to add multiple routes in DNN's route mapper


I have implemented a module in which i have divided that into two parts:

  1. A Web Project:
    Which is having my UI Pages as ascx and ajax call to triggering my Web API and get the data from that.
  2. A Class Library:
    Which is having my API Controllers and the route mapper class. ALl working fine but browser processed a error as "404".It means URL Not Found .I am confused as where i did mistake.

Here is my Router Mapper Class:-

using DotNetNuke.Web.Api;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI.WebControls;

namespace NewController 
{
   public class RouteMapper : IServiceRouteMapper
    {
        public void RegisterRoutes(IMapRoute mapRouteManager)
        {
            mapRouteManager.MapHttpRoute("NewController", "default", "{controller}/{action}",
                new[] { "NewController" });
        }
    }
}

I have checked my namespace and folder name many times as well but did not found any fault there.

My Controller namespace is like below:-
using DotNetNuke.Common.Utilities;
using DotNetNuke.Web.Api;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;

namespace NewController
{
    public class NewInfoController : DnnApiController
    {
        [AllowAnonymous]
        [HttpGet]
        public HttpResponseMessage HelloWorld()
        {
            return Request.CreateResponse(HttpStatusCode.OK, "Hello World!");
        }
    }
}

Getting URL in the proper way as well as:- curl 'http://localhost/dnn7/DesktopModules/NewController/API/NewInfo/HelloWorld'

Or

The Problem is because i am having multiple API Controllers? Do i need to Configure multiple Routes? If yes than how?


Solution

  • First, I think you may have a misunderstanding of the routing. It looks like you are using the namespace name in your url. Unless your module is called 'NewController', your url would not work. DNN routing is very similar to Web Api routing except that you have to specify the module folder name as such /DesktopModules/<moduleFolderName>/API/. So if you have a module called 'MyModule' and your controller is in a namespace called 'NewController', the address would be

    'http://localhost/dnn7/DesktopModules/MyModule/API/NewInfo/HelloWorld'

    The default route would then look like this;

    mapRouteManager.MapHttpRoute(
       "MyModule", 
       "default",
       "{controller}/{action}",
       new[] { "NewController" });
    

    which can also be rewritten with named parameters as such

    mapRouteManager.MapHttpRoute(
       moduleFolderName: "MyModule",
       routeName: "default",
       url: "{controller}/{action}/{id}",
       defaults: new { id = RouteParameter.Optional },
       namespaces: new[] { "NewController" }
       );
    

    See this link for more info

    Regarding your second part, can you have multiple routes? Of course;

    Say your controller has the following actions

    namespace NewController
    {
        public class NewInfoController : DnnApiController
        {
            [AllowAnonymous]
            [HttpGet]
            public HttpResponseMessage HelloWorld()
            {
                return Request.CreateResponse(HttpStatusCode.OK, "Hello World!");
            }
    
            [HttpGet]
            public HttpResponseMessage GetItemByName(string name)
            {
                //your logic here
            }
    
            [HttpGet]
            public HttpResponseMessage GetItemByNameAndLocation(string name, string location)
            {
                //your logic here
            }
        }
    }
    

    then your routing class would look like this

    namespace NewController
    {
        public class RouteMapper : IServiceRouteMapper
        {
            public void RegisterRoutes(IMapRoute mapRouteManager)
            {
                mapRouteManager.MapHttpRoute(
                    moduleFolderName: "MyModule",
                    routeName: "itemByName",
                    url: "{controller}/{action}/{name}",
                    defaults: new { name = "" },
                    namespaces: new[] { "NewController" }
                );
    
                mapRouteManager.MapHttpRoute(
                    moduleFolderName: "MyModule",
                    routeName: "itemByNameAndLocation",
                    url: "{controller}/{action}/{name}/{location}",
                    defaults: new { name = "", location = "" },
                    namespaces: new[] { "NewController" }
                );
    
                mapRouteManager.MapHttpRoute(
                    moduleFolderName: "MyModule",
                    routeName: "default",
                    url: "{controller}/{action}/{id}",
                    defaults: new { id = RouteParameter.Optional },
                    namespaces: new[] { "NewController" }
                );
            }
        }
    }
    

    Now http://localhost/dnn7/DesktopModules/MyModule/API/NewInfo/GetItemByName/someName will be handled by the first route, http://localhost/dnn7/DesktopModules/MyModule/API/NewInfo/GetItemByNameAndLocation/someName/someLocation will be handled by the second route. Anything that doesn't match those two will be handled by the last default route. Remember hierarchy in routing is important!

    What if you want to shorten the urls to say

    http://localhost/dnn7/DesktopModules/MyModule/API/fetch/someName

    and

    http://localhost/dnn7/DesktopModules/MyModule/API/fetchByNameAndLocation/someName/someLocation

    Notice we didn't specify the Controller and the Action. All we have to do is change the first two routes to

    mapRouteManager.MapHttpRoute(
        moduleFolderName: "MyModule",
        routeName: "itemByName",
        url: "fetch/{name}",
        defaults: new { controller = "NewInfo", action = "GetItemByName", name = "" },
        namespaces: new[] { "NewController" }
    );
    
    mapRouteManager.MapHttpRoute(
         moduleFolderName: "MyModule",
         routeName: "itemByNameAndLocation",
         url: "fetchByNameAndLocation/{name}/{location}",
         defaults: new { controller = "NewInfo", action = "GetItemByNameAndLocation", name = "", location = "" },
         namespaces: new[] { "NewController" }
    );
    

    If you are familiar with Web Api, you'll notice DNN's services routing is very similar since it's just a wrapper around the underlying Web Api's routing. Good luck!