Generating Outgoing URLs in Views in ASP.NET MVC

Almost all MVC Web applications allow users to navigate from one View to another, usually relying on including links in the first View which eventually targets the action method that generates the second. Using simple anchor HTML elements “a” and targeting it’s “href” attribute to a specific controller’s action, maybe seems a good and an obvious solution but it can be dangerous choice. Imagine you have an anchor element like this:

<a href="/Simple/MySegmentVariable">Link</a>

Clicking the link will cause a “MySegmentVariable” action in a “SimpleController” controller process the URL request. But what if in some point you decide to change your URL schema? What if you decide to delete the entire “SimpleController” class and replace it with a new one? All anchor links that used to target this controller will crash. MVC Framework provides you with a much better approach where you use your URL Routing system to generate and produce URLs dynamically in a way that is guaranteed to reflect the URL schema of the application. Let’s create a simple MVC application and take a look at these features.

Open Visual Studio 2012 and create an ASP.NET MVC 4 Web Application, choosing the Basic template and the Razor as my View engine. Add a simple controller named “SimpleController” to the “controllers” folder.

namespace UrlRouting.Controllers
{
    public class SimpleController : Controller
    {

        public ActionResult Index()
        {
            ViewBag.Controller = "Simple";
            ViewBag.Action = "Index";
            return View("DisplayActionController");
        }

        public ActionResult MySegmentVariable(string id ="MyDefaultIdValue")
        {
            ViewBag.Controller = "Simple";
            ViewBag.Action = "MySegmentVariable";
            ViewBag.CustomVariable = id;
            return View();
        }

    }
}

The controller has two action methods which pass both the controller’s and action’s name using a ViewBag object. Create a “DisplayActionController” View inside the Views/Shared folder.

@{ 
    Layout = null; 
}
<!DOCTYPE html>
<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>DisplayActionController</title>
</head>
<body>
    <div>Controller Invoked: @ViewBag.Controller</div>
    <div>Action Invoked: @ViewBag.Action</div>
    <div>
        @Html.ActionLink("This is an outgoing URL", "MySegmentVariable")
    </div>
</body>
</html>

This is the View rendered when the Index action of the Simple controller is invoked. Right click inside the MySegmentVariable action and select “Add view..”. Leave the default values and change the new’s View contents to the following.

@{ 
    Layout = null; 
}
<!DOCTYPE html>
<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>MySegmentVariable</title>
</head>
<body>
    <div>Controller processed the URL: @ViewBag.Controller</div>
    <div>Controller action invoked: @ViewBag.Action</div>
    <div>The custom segment variable is: @ViewBag.CustomVariable</div>
</body>
</html>

This is the View rendered when “MySegmentVariable” action method is invoked. Before start running the application and explaining what are we doing, add a custom route in the “RegisterRoutes” function in the RouteConfig.cs file, where we define application’s URL schema.

public static void RegisterRoutes(RouteCollection routes)
        {
            routes.MapRoute("MyRoute", "{controller}/{action}/{id}",
                new
                {
                    controller = "Simple",
                    action = "Index",
                    id = UrlParameter.Optional
                });
        }

If you don’t know what the above code means, read this post where an MVC Routing System introduction is described. Build and run your application.
generateout1
This is the “DisplayActionController” View render by the Index action in the SimpleController. Notice the link generated by the following line inside the View’s code

@Html.ActionLink("This is an outgoing URL", "MySegmentVariable")

The simplest way to generate an outgoing URL in a view is to call the Html.ActionLink helper method. The above overload has two parameteres. The first one is the text being displayed and the second one, the action method that the link should target. If you hover over the link you can see that the target URL is

http://localhost:"your_port"/Simple/MySegmentVariable

To see Html.ActionLink capabilities, add a new route above the old one and run the application again.

public static void RegisterRoutes(RouteCollection routes)
        {
            routes.MapRoute("NewRoute", "Web/app{action}",
                new { controller = "Simple" });

            routes.MapRoute("MyRoute", "{controller}/{action}/{id}",
                new
                {
                    controller = "Simple",
                    action = "Index",
                    id = UrlParameter.Optional
                });
        }

Hover over the link and see how it’s new target URL reflects the new route we added before.
generateout2
The default Html.ActionLink overload method assumes that you want to target an action method in the same controller that has caused the view to be rendered. If you wish to target another controller’s action you can use a different overload. Create a new controller named “ProductController” in the controllers folder.

namespace UrlRouting.Controllers
{
    public class ProductController : Controller
    {
        public ActionResult Index()
        {
            ViewBag.Controller = "Product";
            ViewBag.Action = "Index";
            return View("DisplayActionController");
        }
        public ActionResult ListProducts()
        {
            ViewBag.Controller = "Product";
            ViewBag.Action = "ListProducts";
            return View("DisplayActionController");
        }
    }
}

In the “DisplayActionController” View add a new Html.ActionLink passing this time both the action’s and the controller’s name you want to invoke.

<div>
        @Html.ActionLink("This is an outgoing URL", "MySegmentVariable")
    </div>
    <div>
        @Html.ActionLink("This targets another controller", "ListProducts", "Product")
    </div>

Build and run your application. Notice the difference at the two generated links in your page.
generateout3
The first outgoing URL was generated using the first route we defined in the “RouteConfig.cs” file, since it requires only an action to be matched. It’s URL is the same we saw before. The second ActionLink though, matched the second route “MyRoute” because it passed a controller’s name as parameter too. If you want, you can pass the extra value for the “Id” segment in the second route too. Comment the first route in the RouteConfig.cs and change the second ActionLink to this.

@Html.ActionLink("This targets another controller", "MySegmentVariable", 
                new { id = "ValueFromActionLink!" })

generateout4
Second’s link URL targets

http://localhost:49529/Simple/MySegmentVariable/ValueFromActionLink!

passing an extra value for the id segment. It may seems little confusing how ActionLink works with the URL Routing system, but since you understand it you have a powerful tool to dynamically generate outgoing URLs in you MVC application.

Advertisements


Categories: ASP.NET

Tags: , , ,

2 replies

  1. Great article. You help me to manage URL to be more user friendly. Thanks again.

  2. Nice post. I was checking continuously this blog andd I am impressed!
    Extremely useful information particularly the
    last part 🙂 I care for such information a lot. I was seeking this particular info for a very long
    time. Thank you and good luck.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Chara Plessa

The purpose of this blog is to broaden my education, promote experimentation and enhance my professional development. Albert Einstein once said that “If you can’t explain it simply, you don’t understand it well enough” and I strongly believe him!

chsakell's Blog

Anything around ASP.NET MVC,WEB API, WCF, Entity Framework & AngularJS

Kumikoro

A Front End Developer's Blog

Muhammad Hassan

Full Stack Developer | ASP.NET | MVC | WebAPI | Advanced Javascript | AngularJS | Angular2 | C# | ES6 | SQL | TypeScript | HTML5 | NodeJS, MS candidate @LUMS, Grad & EX-Adjunct Faculty @NUCES-FAST, seasonal blogger & open-source contributor. Seattle, WA.

Software Engineering

Web development

IEvangelist

.NET, ASP.NET, C#, MVC, TypeScript, AngularJS

leastprivilege.com

Dominick Baier on Identity & Access Control

Happy DotNetting

In Love with Technology

Knoldus

Knols of experience to your advantage

knowshnet

Search - Read - Request - Share

Rahul's space

Learn, Share and Grow with me !

Dhananjay Kumar

Developer Evangelist @Infragistics | MVP @Microsoft |

SQL Authority with Pinal Dave

SQL Server Performance Tuning Expert

Conficient Blog

Random bits of tech from @conficient

Code! Code! Code!

SOLID & KISS

Code Wala

Designing and coding

Microsoft Mentalist

A way to start with Microsoft Technologies

Tony Sneed's Blog

A glimpse into the lives of Tony & Zuzana Sneed

Sriramjithendra Nidumolu

Personal Notes of Sriramjithendra

%d bloggers like this: