Search code examples
asp.net-coreasp.net-core-mvcasp.net-core-2.0tag-helpersasp.net-core-tag-helpers

How do you pass variable to ASP.NET Core's Tag Helpers attributes?


I need to dynamically generate the route name for my form and pass it to the form tag helper. This is what I have:

@{ string route = GetRouteName(); // returns "MyRouteName" }

<form asp-route="route"></form>
<p>@route</p>

This results in the following markup (note there is no value for action):

<form action="" method="post" novalidate="novalidate">
</form>
<p>MyRouteName</p>

I know that the route name is being generated correctly because it is being put in the p tag, and if I just type it into the asp-route attribute directly it works as expected.

I have tried the following variations with no difference in result:

<form asp-route="GetRouteName()"></form>
<form asp-route="@GetRouteName()"></form>
<form asp-route="@route"></form>

Is there a way to pass a variable to the asp-route attribute?


Solution

  • Obviously <form asp-route="GetRouteName()"></form> won't work as this passes the "GetRouteName()" string instead of the result of the method call.

    However, <form asp-route="@GetRouteName()"></form> or <form asp-route="@route"></form> does definitely work. I've put together a sample to prove this:

    1. Create an empty ASP.NET Core MVC app:

      dotnet new mvc
      
    2. Add a controller for testing (Controllers/TestController.cs):

      public class TestController : Controller
      {
          public IActionResult Index()
          {
              if (HttpMethods.IsGet(Request.Method))
                  return View();
              else
                  return Content($"{Request.Method} {UriHelper.BuildRelative(Request.PathBase, Request.Path, Request.QueryString)}");
          }
      }
      
    3. Add the related view (Views/Test/Index.cshtml):

      @functions { string GetRouteName() => "MyRouteName"; }
      
      @{ string route = GetRouteName(); /* returns "MyRouteName" */ }
      
      <p>Route name: @route</p>
      
      <p>Route: @Url.RouteUrl(route)</p>
      
      <form asp-route="@route">
          <input type="submit" value="Submit" />
      </form>
      
    4. Define a route named MyRouteName in the Startup.Configure method:

      app.UseMvc(routes =>
      {
          routes.MapRoute(
              name: "MyRouteName",
              template: "Test/{action}",
              defaults: new { controller = "Test" });
      
          routes.MapRoute(
              name: "AnotherRouteName",
              template: "",
              defaults: new { controller = "Home", action = "Index" });
      });
      
    5. Start the app, navigate to /Test/Index and verify that the action attribute of the generated HTML form is correct. (Tested on ASP.NET Core 2.0 and 2.1.)

    It's very likely that the problem lies in your route configuration: an empty action attribute is generated when you pass an undefined route name in the asp-route attribute.