Saturday, November 2, 2013

Attribute Routing With ASP.net MVC 5

Introduction


What is Routing ?

  • Routing is how ASP.net MVC matches a URI to an Action


What is Attribute Routing ?

  • ASP.net MVC 5 supports a new type of Routing, called Attribute Routing
  • As the name implies, attribute routing uses attributes to define routes
  • Attribute routing gives you more control over the URIs in your web application


How To Enable Attribute Routing ?

  • For that, You have to select the RouteConfig.cs inside the App_Start Folder.
  • After that call MapMvcAttributeRoutes is as below.

RouteConfig.cs

public class RouteConfig
    {
        public static void RegisterRoutes(RouteCollection routes)
        {
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

            routes.MapMvcAttributeRoutes();//Attribute Routing

            //Convention-based Routing
            routes.MapRoute(
                name: "Default",
                url: "{controller}/{action}/{id}",
                defaults: new { controller = "Home", action = "Index",
                                id = UrlParameter.Optional }
            );
        }
    }


Key points of the above code

  • To enable Attribute Routing,You have to call MapMvcAttributeRoutes on RouteConfig File.
  • If you want, You can keep the Convention-based Routing also with the same file is as above.
  • But routes.MapMvcAttributeRoutes(); Should configure before the Convention-based Routing.


How to use Optional URI Parameters ?

  • To that you can add a question mark to the Route parameter
  • Well, It's like this : [Route("Pet/{petKey?}")]

    PetController.cs

  public class PetController : Controller
    {
        // eg: /Pet
        // eg: /Pet/123
        [Route("Pet/{petKey?}")]
        public ActionResult GetPet(string petKey)
        {
            return View();
        }
       }

Key point of the above code

  • In the above example, both /Pet and /Pet/123 will Route to the “GetPet” Action

Above Route on Browser is as below


                  

How to use Default Values URI Parameters ?

  • To that you can specify a default value  to the route parameter
  • It's like this : [Route("Pet/Breed/{petKey=123}")]

       PetController.cs
        
    public class PetController : Controller
     {
        // eg: /Pet/Breed
        // eg: /Pet/Breed/528
        [Route("Pet/Breed/{petKey=123}")]
        public ActionResult GetSpecificPet(string petKey)
        {
            return View();
        }
     }


Key point of the above code

    • In the above example, both /Pet/Breed and /Pet/Breed/528 will route to the “GetSpecificPet” Action

    Above Route on Browser is as below





    How to use Route Prefixes ?

    • Normally, the routes in a controller all start with the same prefix
    • Well,It's like this : /Booking

    BookingController.cs

    public class BookingController : Controller
        {
            // eg: /Booking
            [Route("Booking")]
            public ActionResult Index() { return View(); }

            // eg: /Booking/5
            [Route("Booking/{bookId}")]
            public ActionResult Show(int bookId) { return View(); }

            // eg: /Booking/5/Edit
            [Route("Booking/{bookId}/Edit")]
            public ActionResult Edit(int bookId) { return View(); }
        }


    Above Routes on Browser are as below




    How to Set Common Route Prefix ?

    • If you want, you can specify a common prefix for an entire controller
    • To that you can use [RoutePrefix] attribute
    • It's like this : [RoutePrefix("Booking")]
        
           BookingController.cs

        [RoutePrefix("Booking")]
        public class BookingController : Controller
        {

            // eg: /Booking
            [Route]
            public ActionResult Index() { return View(); }

            // eg: /Booking/5
            [Route("{bookId}")]
            public ActionResult Show(int bookId) { return View(); }

            // eg: /Booking/5/Edit
            [Route("{bookId}/Edit")]
            public ActionResult Edit(int bookId) { return View(); }

        }

    Above Routes on Browser are as below




    How to Override the Common Route Prefix ?

    • You can use a tilde (~) on the method attribute to override the route prefix
    • Well,It's like this : [Route("~/PetBooking")]
           
            BookingController.cs

        [RoutePrefix("Booking")]
        public class BookingController : Controller
        {
            // eg: /PetBooking
            [Route("~/PetBooking")]
            public ActionResult PetBooking() { return View(); }
        }

    Above Route on Browser is as below





    How to use Default Route ?

    • You can apply the [Route] attribute on the Controller level and put the Action as a parameter
    • That Route will then be applied on all Actions in the Controller
    • Well,It's like this : [Route("{action=index}")]
          
           BookingController.cs

        [RoutePrefix("Booking")]
        [Route("{action=index}")]
        public class BookingController : Controller
        {
            // eg: /Booking
            public ActionResult Index() { return View(); }

            // eg: /Booking/Show
            public ActionResult Show() { return View(); }

            // eg: /Booking/New
            public ActionResult New() { return View(); }

        }

    Above Routes on Browser are as below





    How to override Default Route ?

    • For that you have to use specific [Route] on a specific Action.
    • It'll override the default settings on the Controller.

           BookingController.cs

        [RoutePrefix("Booking")]
        [Route("{action=index}")]
        public class BookingController : Controller
        {
            // eg: /Booking
            public ActionResult Index() { return View(); }

            // eg: /Booking/Edit/3
            [Route("Edit/{bookId:int}")]
            public ActionResult Edit(int bookId) { return View(); }

        }

    Above overridden Route on Browser is as below






    How to give Route Names ?

    • You can specify a Name for a Route
    • By using that Name, you can easily allow URI generation for it
    • Well,It's like this : [Route("Booking", Name = "Payments")]

      BookingController.cs

     public class BookingController : Controller
        {
            // eg: /Booking
            [Route("Booking", Name = "Payments")]
            public ActionResult Payments() { return View(); }
        }

    • After that you can generate a Link is using Url.RouteUrl
    • It's like this : 
        <a href="@Url.RouteUrl("Payments")">Payments Screen</a>

    Note : On the above code, "Payments" is a Route Name



    Advantages of Attribute Routing Over the Convention-based Routing

    • Attribute Routing gives you more control over the URIs in your web application
    • Easy to Troubleshoot issues
    • No fear of modifying anything will break another route down the line 


    Used Dev. Environment in Article's Source Code

    • Visual Studio 2013 Express
    • .Net Framework 4.5.1
    • ASP.net MVC 5
    • C#

    Conclusion

    • You saw that how easily can configure the URI Routines with Attribute Routing
    • In my next article I will show how to apply Attribute Routing with Route Constraints, Custom Route Constraints and Areas
    • So enjoy this Awesome New Feature of ASP.net MVC 5

    I hope this helps to You.Comments and feedback greatly appreciated.

    If you feel it was a good article,Give me a +1.Thank You.



    You Might Also Like

    24 comments:

    1. Is it possible to use the new MVC5 route attribute to map controllers to subdomains?

      ReplyDelete
      Replies
      1. Hi Swyish,

        At this moment it doesn't support.But if you want you can use below mentioned nuget package to do that.

        PM> Install-Package AttributeRouting

        For more info check this : http://attributerouting.net/#asp-net-mvc

        Delete
    2. Nice recap.
      Thanks for that.

      Cheers

      ReplyDelete
    3. Hey sampath, I have a special scenario. i store all my urls in a database. They haven't a well defined structure. They are basically all "/(keyword)"
      They can return, a public profile, for instance /mrbublegum
      Or also a product page like '/apple-ipad-air'

      Basically i can't hardcore routing urls. How would you proceed ? A wildcard custom router ?

      Thanks for your help

      ReplyDelete
      Replies
      1. Hi Alex,

        I couldn't get exactly what you meant by 'hardcore' here. But if you want, you can write 'Custom Route Constraints' for your scenario. For more info please check the below mentioned article (check under the section 'Custom Route Constraints'). If you have further queries feel free to contact me.

        http://blogs.msdn.com/b/webdev/archive/2013/10/17/attribute-routing-in-asp-net-mvc-5.aspx

        Delete
      2. Sorry for the typo I wanted to write "hardcode" ! Thanks for the link
        This is indeed a Custom Route Constraints. But what is the best way to cache the database access, given the fact that i'm talking about 50000 urls in database.

        Delete
      3. Hi Alex,

        Yep,You can use caching with a SQL dependency for dramatically increase the application performance.Please check the below mentioned links for more info.

        http://msdn.microsoft.com/en-us/library/ms178604.ASPX

        http://www.dotnetcurry.com/showarticle.aspx?ID=263

        I hope this will help to you.Good luck ! :)

        Delete
    4. Hi i have a problem when route mvc 5 with file extension .song
      my url is :
      http://localhost:49625/Right-Here-Waiting-For-You__Richard-Marx_yb.song
      my route config is:
      routes.MapRoute(
      "Song", // Route name
      "{songid}.song", // URL with parameters
      new
      {
      controller = "Song",
      action = "Song",
      });

      It work in mvc3 but in mvc 5 it display 404 error.
      Can you help me with this

      ReplyDelete
      Replies
      1. Hi le,

        Yep,this is definitely a route issue.Please use 'Glimpse' to debug it.It's an awesome tool to find this kind of route issues.Good Luck ! :)

        Here is the link : http://getglimpse.com/

        Delete
    5. Replies
      1. Hi Rai,

        Thanks, I’m glad you enjoyed it ! :)

        Delete
    6. This is nice blog to solve each and every router technical problems. Thanks for sharing this nice blog. Please visit this link--------- Linksys Router Technical Support .

      ReplyDelete
    7. Thanks for Sharing

      ARKA Softwares & Outsourcing is an IT Company focusing on software & Web development and providing offshore outsourcing solutions to enterprises worldwide.website designing company in usa

      ReplyDelete
    8. Valuable source of Information Sir....Thanks for Sharing

      ReplyDelete
    9. Thanks for sharing this useful blog. The Keshri Software Solutions provides Web Application development,Website Promotions, Search Engine Optimizations services.

      Get more details please log on to - http://www.ksoftware.co.in .

      ReplyDelete
    10. you can check good example at http://mvc4all.com/mvc/understanding-the-default-route-declaration/

      ReplyDelete
    11. can we pass directly parameter and get the data - route config
      Ex:
      crowdnews.org/saikrishna
      here saikrishna : is parameter
      controller is :Home
      View is action
      but I should not show home/view

      ReplyDelete
    12. Interesting information. I like your topic. Thanks for sharing it...

      Yii Development Company India

      ReplyDelete
    13. i have done same steps as per above but it showing http 404 error not rendring the view.

      ReplyDelete

    Thanks for your Feedback.