Copied to clipboard

Flag this post as spam?

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


  • Pierre 4 posts 34 karma points
    Oct 02, 2020 @ 09:38
    Pierre
    0

    Using custom URL routing for WebAPI after changing from WebApi 2 + MVC to Umbraco

    Hello,

    I'm pretty new into using Umbraco. I'm a computer science student who took over a project that formerly used ASP.Net WebApi2 in combination with MVC, but they merged the project with Umbraco.

    Right now I'm facing the problem, that we have a mobile app that should be connected via and API.

    right now the urls look like this: "umbraco/api/Items/getListItems/{id:int}". and working perfectly fine

    personally I want to remove the /umbraco/ so it begins with /api/. But my real struggle is that I want to have a second (2) additional parameters for only one method in one of my controllers.

    Like: "/api/Items/action/{categoryID}/{userid}"

    As far as I could see there is both a AppStart/RouteConfig.cs & AppStart/WebApiConfig.cs

    RouteConfig.cs contains:

    public static void RegisterRoutes(RouteCollection routes)
        {
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
    
            routes.MapRoute(
                name: "Default",
                url: "{controller}/{action}/{id}",
                defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
            );
        }
    

    and WebApiConfig:

    public static void Register(HttpConfiguration config)
        {
            // Web API routes
            config.MapHttpAttributeRoutes();
    
            config.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{id}",
                defaults: new { id = RouteParameter.Optional }
            );
        }
    

    But as I found out changes have 0 affect on my routes. Not even a customized second entry or modifiyng the default route seems to make a difference.

    I know from earlier projects that I could directly in the controller action say: [System.Web.Http.Route("api/Items/getListItems/{id:int}")] and/or override default route by saying "~/api/..." but I guess they don't affect Umbraco's way to route.

    In the Global.asax I could see that it still uses the old MVC settings:

    public class MvcApplication : System.Web.HttpApplication
    {
        protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();
            GlobalConfiguration.Configure(WebApiConfig.Register);
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);
    
    
        }
    }
    

    Following guides saying I have to use:

    public class MvcApplication : Umbraco.Web.UmbracoApplication
    {
        protected override void OnApplicationStarted(object sender, EventArgs e)
        {
            base.OnApplicationStarted(sender, e);
            AreaRegistration.RegisterAllAreas();
        }
    }
    

    just gives me the error "No suitable method found to override".

    I should probably mention that the "Global.asax" is using the namespace "xxMVC" together with umbraco related files, while the WebAPI is using its own namespace "xxWebServices" and implementing the UmbracoApiController

     public class Controllername : UmbracoApiController
    

    (idk if thats needed or if I just can use the default controller)

    I would be glad if someone knows a solution that could work.

    Thanks in advance!

    Regards Pierre

  • Marc Goodson 2141 posts 14344 karma points MVP 8x c-trib
    Oct 02, 2020 @ 12:22
    Marc Goodson
    0

    Hi Pierre

    Could you use attribute routing for your API - see an example here:

    https://our.umbraco.com/documentation/reference/routing/webapi/#using-mvc-attribute-routing-in-umbraco-web-api-controllers

    regards

    Marc

  • Pierre 4 posts 34 karma points
    Oct 05, 2020 @ 08:03
    Pierre
    0

    Hey Marc,

    thanks for your response. I'm sorry that I'm replying that late, but had a lot of stuff to do.

    Yes I already had a look at hat documentation, but sadly it doesnt seem to work.

    Regards Pierre

  • Marc Goodson 2141 posts 14344 karma points MVP 8x c-trib
    Oct 05, 2020 @ 09:59
    Marc Goodson
    0

    Hi Pierre

    What you have posted though doesn't appear to be following that?

    It looks more like a V7 approach?

    The key thing to getting API attribute routing to work is where you call

    GlobalConfiguration.Configuration.MapHttpAttributeRoutes();

    If you create exactly the example in the documentation with the 'ProductsController' and the Table, Chair etc

    does that work for you?

    regards

    Marc

  • Pierre 4 posts 34 karma points
    Oct 05, 2020 @ 11:16
    Pierre
    0

    Hey Marc,

    sometimes I realy ask myself what the heck I'm doing.

    I followed your suggestion giving it another try now with a new controller and voila, it works like a charm :)

    I'm now even finally able to have more than one additional url paramter if it's needed.

    Thanks for your help and time.

    I have one last question. I'm now calling GlobalConfiguration.Configuration.MapHttpAttributeRoutes(); directly in my controller like the documentation did (Copy & Paste). The only thing I saw is, that this will affect every controller in this particular namespace. This isnt a big deal, since I wanted to remove the /umbraco/ in my urls.

    But do u have a cleaner sugestion how I can implement

    GlobalConfiguration.Configuration.MapHttpAttributeRoutes();
    

    Because right now it looks hmm idk what to call it, but it looks not pretty that one controller contains a part, other controllers arent containing. Is there a better way/solution u would suggest, or is it normal to create a "DefaultController" that then contains the "GlobalConf...".

    Regards Pierre

  • Marc Goodson 2141 posts 14344 karma points MVP 8x c-trib
    Oct 05, 2020 @ 14:51
    Marc Goodson
    100

    Hi Pierre

    I would have that call in its own 'component'

    and I would insert that component to be the 'first' in the stack.

    The example is sort of munged, I wouldn't have the 'ProductsController' in the same file as the AttributeRoutingComponent!

    So normally I would have a folder called 'Composition' and within that a folder called 'Components'

    I'd create a file called 'RegisterComponents.cs' and I'd use this to register any Components that I'm using to extend Umbraco eg:

    [RuntimeLevel(MinLevel = RuntimeLevel.Run)]
    public class RegisterComponents : IComposer
    {
        public void Compose(Composition composition)
        {
           composition.Components().Insert<AttributeRoutingComponent>(); ;
        }
    }
    

    then in the Components folder, I'd have the AttributeRoutingComponent:

    public class AttributeRoutingComponent :IComponent
    {
        public void Initialize()
        {
            GlobalConfiguration.Configuration.MapHttpAttributeRoutes();        
    
        }
    
        public void Terminate()
        {
    
        }
    }
    

    And then all my API controllers I'd have 'elsewhere', usually inside a folder called Api, inside another folder called Controllers and I'd have one file for each controller...

    Is that neater?

    regards

    marc

  • Pierre 4 posts 34 karma points
    Oct 06, 2020 @ 10:14
    Pierre
    0

    Hey Marc,

    Hehe thanks, thats definitely neater & such a approach is what I had in mind.

    My controllers are all in a folder called controllers. I was just curious if it would have been a normal approach to place it in the controller itself, or like u suggested in another separate folder. But yea, placing it separate makes most sence.

    Thanks again for your help & time!

    Regards Pierre

Please Sign in or register to post replies

Write your reply to:

Draft