-1

My goal is for all methods of my CompanyController to share the same "id" parameter without having to explicitly pass it via RouteValueDictionary, as that is cluttersome and error-prone.

So for example, If I am on a page http://FooBar.com/Company/Index/4782 and I want to generate a link to "Profile" method of the same controller I would write @Html.ActionLink("Go to profile", "Profile"), it would produce http://FooBar.com/Company/Profile/4782 and I would not have to specify new {id=id} every time I need such link.

Is there a recommended way?

DenNukem
  • 8,014
  • 3
  • 40
  • 45
  • You coudl extend the html class so there's another overload of `ActionLink` which defaults the id to the current one but I don't know of any other way to do this. Try looking at how ActionLink works using Reflector or a [dotpeek](http://www.jetbrains.com/decompiler/) – Basic Nov 21 '12 at 00:56

2 Answers2

0

Changing the order of parameters in the default route, if you can live with that, yields desired result.

So, if the only route you have is this (note the absence of defaults):

        routes.MapRoute(
            name: "NoDefault",
            url: "{controller}/{action}/{id}/"
        );

and then from the page http://foobar.com/Company/Index/4782 you call

@Html.ActionLink("Manage Products", "ManageProducts", "Company", null, null) 

you get this wrong link (the current page, it seems): http://foobar.com/Company/Index/4782/ So that does not work. However if you reverse the order of parameters in the route like so:

        routes.MapRoute(
            name: "NoDefault",
            url: "{controller}/{id}/{action}"
        );

and start on the same page http://foobar.com/Company/4782/Index/ , then the same ActionLink() call works just fine and generates a correct link: http://foobar.com/Company/4782/ManageProducts

DenNukem
  • 8,014
  • 3
  • 40
  • 45
  • 3
    I suggest that you add this and the information in your other answer to your question. – Robert Harvey Nov 21 '12 at 01:51
  • 3
    Hi @DenNukem - If you edited this so the language you used seemed more like they were coming from a 2nd person, and not you, I think people would feel less *wierd* about this. For instance, get rid of the last sentence, and get rid of the first sentence, and then the answer would look just like someone else posted it. In short, [pretend like you're on Jeopardy](http://blog.stackoverflow.com/2011/07/its-ok-to-ask-and-answer-your-own-questions/) and answer the question like you're answering it for someone else. Good luck! :) – jamesmortensen Nov 21 '12 at 03:16
0

The Actionlink implementation inside System.Web.Mvc.Html.LinkExtensions (System.Web.Mvc, Version=4.0.0.0) is as below...

public static MvcHtmlString ActionLink(this HtmlHelper htmlHelper, string linkText, string actionName, string controllerName, RouteValueDictionary routeValues, IDictionary<string, object> htmlAttributes)
{
  if (string.IsNullOrEmpty(linkText))
    throw new ArgumentException(MvcResources.Common_NullOrEmpty, "linkText");
  else
    return MvcHtmlString.Create(HtmlHelper.GenerateLink(htmlHelper.ViewContext.RequestContext, htmlHelper.RouteCollection, linkText, (string) null, actionName, controllerName, routeValues, htmlAttributes));
}

There are a number of utility overloads with different parameter combinations.

So you should be able to add an extension method to generate your link easily (untested)...

public static MvcHtmlString InternalActionLink(this HtmlHelper htmlHelper, string linkText, string actionName, string controllerName, RouteValueDictionary routeValues, IDictionary<string, object> htmlAttributes)
{
  if (string.IsNullOrEmpty(linkText))
    throw new ArgumentException(MvcResources.Common_NullOrEmpty, "linkText");
  else
    RouteValueDictionary.Values.Add("id", htmlHelper.ViewContext.RequestContext.RouteData)
    return MvcHtmlString.Create(HtmlHelper.GenerateLink(htmlHelper.ViewContext.RequestContext, htmlHelper.RouteCollection, linkText, (string) null, actionName, controllerName, routeValues, htmlAttributes));
}

public static MvcHtmlString InternalActionLink(this HtmlHelper htmlHelper, string linkText, string actionName)
{
  return this.InternalActionLink(htmlHelper, linkText, actionName, (string) null, new RouteValueDictionary(), (IDictionary<string, object>) new RouteValueDictionary());
}

Obviously you'd need to add some simple wrapper overloads to provide the exact functionality you want.

and then just use html.InternalActionLink("Title", "Action") and it will automatically inject the correct Id into the route dictionary when generating the Url.

Incidentally, the following ActionLink() overloads are provided by the framework - the more you implement, the more flexible you'll be...

public static MvcHtmlString ActionLink(this HtmlHelper htmlHelper, string linkText, string actionName, string controllerName, object routeValues, object htmlAttributes)
public static MvcHtmlString ActionLink(this HtmlHelper htmlHelper, string linkText, string actionName, string controllerName, RouteValueDictionary routeValues, IDictionary<string, object> htmlAttributes)
public static MvcHtmlString ActionLink(this HtmlHelper htmlHelper, string linkText, string actionName, string controllerName, object routeValues, object htmlAttributes)
public static MvcHtmlString ActionLink(this HtmlHelper htmlHelper, string linkText, string actionName, string controllerName)
public static MvcHtmlString ActionLink(this HtmlHelper htmlHelper, string linkText, string actionName, RouteValueDictionary routeValues, IDictionary<string, object> htmlAttributes)
public static MvcHtmlString ActionLink(this HtmlHelper htmlHelper, string linkText, string actionName, RouteValueDictionary routeValues)
public static MvcHtmlString ActionLink(this HtmlHelper htmlHelper, string linkText, string actionName, object routeValues, object htmlAttributes)
public static MvcHtmlString ActionLink(this HtmlHelper htmlHelper, string linkText, string actionName, object routeValues)
public static MvcHtmlString ActionLink(this HtmlHelper htmlHelper, string linkText, string actionName)
Basic
  • 26,321
  • 24
  • 115
  • 201