138

I need to be able to construct a link in the Action on the controller to send an email. What is best practice to do this? I don't want to construct it myself in case my routes change.

Should I have a view for each email and render that and send it? That might be a good way of doing it.

Endy Tjahjono
  • 24,120
  • 23
  • 83
  • 123
ScottBelchak
  • 1,417
  • 2
  • 10
  • 6

5 Answers5

245

If you just want to get the path to a certain action, use UrlHelper:

UrlHelper u = new UrlHelper(this.ControllerContext.RequestContext);
string url = u.Action("About", "Home", null);

if you want to create a hyperlink:

string link = HtmlHelper.GenerateLink(this.ControllerContext.RequestContext, System.Web.Routing.RouteTable.Routes, "My link", "Root", "About", "Home", null, null);

Intellisense will give you the meaning of each of the parameters.


Update from comments: controller already has a UrlHelper:

string url = this.Url.Action("About", "Home", null); 
freedomn-m
  • 27,664
  • 8
  • 35
  • 57
Gideon
  • 18,251
  • 5
  • 45
  • 64
  • 17
    Followup: For the second to last parameter (the RouteValueDictionary) here is an example: new System.Web.Routing.RouteValueDictionary(new { id = 1 }) – Matthew M. Mar 23 '10 at 05:49
  • 17
    You don't need to construct a new UrlHelper; there is a .Url property on the controller which will give you one with the correct RequestContext. – Tobias J Nov 14 '13 at 15:34
  • Where does "Root" come from? If I have to hardcode the name of the route I'm trying to match, why not just hardcode the url? – xr280xr May 13 '14 at 23:18
  • @xr280xr: I believe in this example "Root" is the name of the route as defined in the RegisterRoutes method (usually in RouteConfig). For me, it was "Default" (as it was when I created my project). – Andy Sep 23 '14 at 15:51
  • 4
    You don't need to new up a UrlHelper, just access the Url property in the Controller class. – Jay Douglass Dec 05 '16 at 19:23
25

If you need the full url (for instance to send by email) consider using one of the following built-in methods:

With this you create the route to use to build the url:

Url.RouteUrl("OpinionByCompany", new RouteValueDictionary(new{cid=newop.CompanyID,oid=newop.ID}), HttpContext.Request.Url.Scheme, HttpContext.Request.Url.Authority)

Here the url is built after the route engine determine the correct one:

Url.Action("Detail","Opinion",new RouteValueDictionary(new{cid=newop.CompanyID,oid=newop.ID}),HttpContext.Request.Url.Scheme, HttpContext.Request.Url.Authority)

In both methods, the last 2 parameters specifies the protocol and hostname.

Regards.

Scott Baker
  • 10,013
  • 17
  • 56
  • 102
andresfiuba
  • 266
  • 3
  • 3
  • 8
    FYI using `Url.Action(action, controller, routevalue, protocol)` also produces full URL, so you don't have to specify hostname if you don't need to. – Endy Tjahjono Jul 09 '12 at 09:47
  • 1
    I am getting the following URL with the port number doubled how do I fix this please? h t t p://localhost:54383:54383/MyArea/MyController/Details/1 – Patee Gutee Dec 14 '18 at 20:44
12

I had the same issue, and it appears Gidon's answer has one tiny flaw: it generates a relative URL, which cannot be sent by mail.

My solution looks like this:

string link = HttpContext.Request.Url.Scheme + "://" + HttpContext.Request.Url.Authority + Url.Action("ResetPassword", "Account", new { key = randomString });

This way, a full URL is generated, and it works even if the application is several levels deep on the hosting server, and uses a port other than 80.

EDIT: I found this useful as well.

Community
  • 1
  • 1
Moshe
  • 2,638
  • 2
  • 28
  • 32
  • 1
    Please note that this has a major security vulnerability. All it would take is someone modifying the request header to contain a malicious URL as the host and your application would send an official email containing a link to a dangerous website. – V0ldek Apr 02 '19 at 17:47
8

Another way to create an absolute URL to an action:

var relativeUrl = Url.Action("MyAction");  //..or one of the other .Action() overloads
var currentUrl = Request.Url;

var absoluteUrl = new System.Uri(currentUrl, relativeUrl);
Sphinxxx
  • 12,484
  • 4
  • 54
  • 84
4

I know this is an old question, but just in case you are trying to do the same thing in ASP.NET Core, here is how you can create the UrlHelper inside an action:

var urlHelper = new UrlHelper(this.ControllerContext);

Or, you could just use the Controller.Url property if you inherit from Controller.

Darren
  • 4,408
  • 4
  • 39
  • 57