2

I have existing code with below @html.RenderAction() method:

Html.RenderAction("Widget", "Widget", new
{
    wTitle = "World map dashboard",
    wTitleSpan = "",
    wTitleDisplay = "",
    height = "300px;",
    wAction = "GetWorldMapMethod",
    wCssId = "WorldMap",
    cssOptions = "WorldMap",
    ShipSelection = "fleet",
    infoTitle = HttpUtility.HtmlEncode("<b>Info dashboard</b>"),
    infoText = HttpUtility.HtmlEncode("<p>Info</p>")
});

When this is executed, the method GetWorldMapMethod() is called. I'm trying to understand how this parameter action method is getting called.

Here's my routing configuration:

routes.MapRoute(
    "ManagementShipDetails",
    "Management/ShipDetails/{id}/{successMessage}",
    new {controller = "Management", action = "ShipDetails", successMessage = UrlParameter.Optional}
    );

routes.MapRoute(
    "Report",
    "Data/Report/{viewname}",
    new
    {
        controller = "Data",
        action = "Report",
    });

routes.MapRoute(
    "Apikeydelete",
    "Account/DeleteApiKey/{key}",
    new {controller = "Account", action = "DeleteApiKey"}
    );

routes.MapRoute(
    "FleetOverview",
    "Fleet",
    new {controller = "Data", action = "Fleet"}
    );

routes.MapRoute(
    "ShipOverview",
    "{ShipName}/Overview",
    new {controller = "Data", action = "Overview", ShipName = UrlParameter.Optional}
    );

routes.MapRoute(
    "Hull Performance",
    "{ShipName}/HullPerformanceDrop",
    new {controller = "Data", action = "HullPerformanceDrop", ShipName = UrlParameter.Optional}
    );

routes.MapRoute(
    "ReportingViewReport",
    "{ShipName}/Report/{id}",
    new
    {
        controller = "Reporting",
        action = "Report",
        ShipName = UrlParameter.Optional,
        id = UrlParameter.Optional
    }
    );

routes.MapRoute(
    "PortalDataGetValue",
    "PortalData/GetValue/{tag}/{selection}/{date}/{Filter}",
    new {controller = "PortalData", action = "GetValue", Filter = UrlParameter.Optional}
    );

routes.MapRoute(
    "PortalDataGetDashboardData",
    "PortalData/GetDashboardData/{selection}/{date}",
    new {controller = "PortalData", action = "GetDashboardData", Filter = UrlParameter.Optional}
    );

routes.MapRoute(
    "Default", // Route name
    "{controller}/{action}/{id}", // URL with parameters
    new {controller = "Dashboards", action = "Index", id = UrlParameter.Optional} // Parameter defaults
    );   
Jeremy Caney
  • 7,102
  • 69
  • 48
  • 77
Brijraj
  • 177
  • 2
  • 3
  • 13
  • Please show your routeconfig file – AbdulG Jun 19 '20 at 15:49
  • 1
    basically this invokes Widget action of Widget controller where wAction = "GetWorldMapMethod" is route data. I hope your code is handling this parameter in action method and take decision accordingly. Share Controller code for more precise answer – Always_a_learner Jun 20 '20 at 09:38
  • Yes, controller is having Action method "Widget" and "GetWorldMapMethod", so on load method "Widget" gets called after it method "GetWorldMapMethod" gets called. My question is how the method "GetWorldMapMethod" getting called. – Brijraj Jun 21 '20 at 09:21
  • 1
    Well, what is wrong with these blocks or you just wondering about how it works the `RenderAction` extension? – gurkan Jun 25 '20 at 09:16
  • 1
    @gurkan: My read is that the OP inherited this code and is trying to understand how it’s working, since there isn’t an obvious reason for `GetWorldMapMethod()` to be called. – Jeremy Caney Jun 25 '20 at 21:51

1 Answers1

1

TL;DR @Html.RenderAction() doesn’t rely on your routes. It will attempt to call directly into a WidgetController.Widget() action. That action—as well as any any intermediate code, such as an IControllerFactory or IActionFilter—can use your routeValues dictionary to evaluate your custom wAction route variable and respond appropriately. This could include calling into your WidgetController.GetWorldMapMethod() action.

Critically, ASP.NET MVC is not routing to or calling your GetWorldMapMethod(); it is instead being triggered by something in your code.


Full Answer

As @Always_a_learner notes in the comments, without access to your controller code we can't provide a precise answer. That said, we can at least provide some background information and pair that with an educated guess as to what might be going on.

Child Action Routing

First, it's important to note that while @AbdulG requested your RouteConfig details, they're not really relevant here. @Html.RenderAction() requires an actionName parameter and, optionally, accepts a controllerName, thus bypassing any routes you have setup. In fact, because RenderAction() is intended to render a child action, it doesn't make sense to have a public route associated with it.

Given that, independent of your MapRoute() configuration, we can be confident that your call to @Html.RenderAction() is going to first try to execute an action named WidgetController.Widget().

Note: There are advanced scenarios—such as implementing a custom IControllerFactory—where this assumption might not be true, so you should confirm that there isn't e.g. a SetControllerFactory() registration in your Global.asax.cs. If there is, it could potentially intercept the request and route it to a separate action.

Route Data Handling

Second, the third parameter of this @Html.RenderHtml() overload represents your routeValues. So the Widget() action—as well as any intermediate code, such as an IControllerFactory, or any action filters—will have access to those values in order to implement whatever business logic they deem appropriate. This could potentially include calling into a different action.

Given that, my assumption is that somewhere in this pipeline, there will be code that looks something like this:

var wAction = ControllerContext.RouteData.GetRequiresString("wAction");

switch (wAction) {
  case "GetWorldMapMethod":
    GetWorldMapMethod();
    break;
  default:
    break;
}

Note: This is just an example. There are dozens of different approaches for evaluating the contents of the RouteData and responding to it, including e.g. reflection. Still, if you search for wAction in your code base, that should help you isolate what code is handling that route value.

Debugging

If you're using an IDE like Visual Studio, the easiest solution would be to fire up a debugger, add a breakpoint to your @Html.RenderAction() call, and step through the execution pipeline. That will expose any advanced functionality—such as intermediate IControllerFactory or IActionFilter code being applied—and will also allow you to identify exactly when and where the code is calling into your GetWorldMapMethod() action.

Conclusion

As noted at the top, I'm afraid I can't provide a concrete answer to exactly how your GetWorldMapMethod() is getting called based on the information provided. But, hopefully, this answer will provide you with a solid enough foundation to understand the variables and reverse engineer the code base you're working with.

If you can follow up with your controller code, I'll be happy to update this answer with more specific guidance as well.

Jeremy Caney
  • 7,102
  • 69
  • 48
  • 77
  • As an aside, I'm assuming you inherited this code base from a previous developer, and they aren't around to answer questions. If so, you definitely have my sympathy! As a consultant, I've inherited quite a few legacy code bases with minimal documentation, which necessitates a lot of reverse engineering to understand how pieces are wired up. That can become especially complicated if they're relying on more advanced features under the hood, which may not be immediately apparent if you don't know where to look for it. – Jeremy Caney Jun 25 '20 at 21:22
  • It's also worth noting that the routing is a bit more explicit in ASP.NET Core, where the `RenderAction()` has been removed, in favor of View Components. View Components are like miniature MVC's for partial views, thus operating similar to `RenderAction()`. There, you explicitly invoke View Components by name, so there's no confusion about the routing. (Though they're still subject to interception by a `IViewComponentActivator`, which serves a similar role to the `IControllerFactory` in ASP.NET MVC.) – Jeremy Caney Jun 25 '20 at 23:25