0

Is it possible to re-use controllers in ASP MVC? And if so how?

Perhaps re-use isn't the right word. The situation is I have a menu and sub menu navigation bars as shown below (actually there is another nav bar what is shown)- I know the colour scheme needs some work

Nested navigation

The upper bar is populated from a database, so there could be more or less than 3 plans.

The lower bar always has the same three entries. The views for each of these entries are the same regardless of which plan is selected, though they are different from each other. Obviously the data within them is different (populated from different tables).

That is Plan A -> Suggested Points view is the same as Plan B -> Suggested Points view. But Plan A -> Suggested Points view is not same as Plan A -> Accepted Points view

In order to do this with the views I intend to use partial views, so the same view files can be re-used.

However, how can I do the equivalent for the controllers?

What I would like if for url paths such as: /PlanA/SuggestedPoints /PlanB/SuggestedPoints

To my mind I just want the Plan links to set a variable that tells the Points views which database they should hook up to. Which may be the wrong way to think of it and I suspect is incompatible with the url path suggestion above.

B_D
  • 225
  • 2
  • 16
  • Are you set on those URL's? It would be beneficial to be able to include the controller name too.. for example `/Plans/A/SuggestedPoints` or `/Plans/PlanA/SuggestedPoints`... would that work for you? – musefan Dec 08 '15 at 11:50

2 Answers2

1

Suggested Approach

I would suggest it is better to include a controller name in the route, that way you won't get conflicts so easily with other controllers in your app.

You can modify your RouteConfig.cs file and map a new route. Make sure to add the custom route before the "Default" one.

Something like this:

routes.MapRoute(
    "Plans",
    "Plans/{planName}/{action}",
    new { controller = "Plans", action = "Index" }
);

// Default route here.

Then you would have a controller called Plans with each of your actions having a parameter called planName that lets you identify with plan to work with...

public class PlansController : Controller
{
    public ActionResult SuggestedPoints(string planName)
    {
        // create your view here, using the planName to get the correct data.
    }

    public ActionResult AcceptedPoints(string planName)
    {
        // create your view here, using the planName to get the correct data.
    }

    // etc.
}

This method will allow URL's in the following format:

/Plans/PlanA/SuggestedPoints, /Plans/PlanA/SuggestedPoints, /Plans/PlanB/AcceptedPoints, /Plans/PlanB/AcceptedPoints, etc.

NOTE: If your plans are in your database, it may be more beneficial to use an ID for the plan, but the URL's would look less friendly so that is up to you.

Finally, when you want to create your links in your view, you can use the following:

@Html.RouteLink("link text", "SuggestedPoints", new { controller = "Plans", planName = "PlanA" })

Your Exact Request

If you absolutely must use the URL formats you suggested, then you can do the following which requires a route for each action, but be wary that you will need to rely on the uniqueness of the Action names to ensure they don't conflict with other controllers...

routes.MapRoute(
    "SuggestedPoints",
    "{planName}/SuggestedPoints",
    new { controller = "Plans", action = "SuggestedPoints" }
);

routes.MapRoute(
    "AcceptedPoints",
    "{planName}/AcceptedPoints",
    new { controller = "Plans", action = "AcceptedPoints" }
);

routes.MapRoute(
    "RejectedPoints",
    "{planName}/RejectedPoints",
    new { controller = "Plans", action = "RejectedPoints" }
);

// Default route here.

In this instance, the controller will remain the same as my first suggestion above. Which will allows URL's like as follows:

/PlanA/SuggestedPoints, /PlanA/SuggestedPoints, /PlanB/AcceptedPoints, /PlanB/AcceptedPoints, etc.

musefan
  • 47,875
  • 21
  • 135
  • 185
  • Many thanks @musefan, I went with your suggested solution as I'm not too fussed about the exact URLs. I have one follow up if you don't mind. The 'Plan' navigation bar links to the plan name i.e. /PlanA/ etc. but when on /Plan/PlanA/SuggestedPoints and I click on PlanB it takes me to /Plan/PlanA/PlanB. How can I make it take me to /Plan/PlanB... would a simple '../' prepended to it work? And how could I stop it prepending when I'm just at /Plan and click on it? – B_D Dec 08 '15 at 15:41
  • @B_D: I guess you are still using `ActionLink` to create your links? I would suggest you use `Html.RouteLink("link text", "SuggestedPoints", new { planName = "PlanA" })` for example. Note I have note used this before, so don't know it the syntax is 100%. I will also add it to my answer for completeness – musefan Dec 08 '15 at 16:10
  • Let me know if it works please, I don't have the ability to test it at the moment – musefan Dec 08 '15 at 16:17
  • @musefun It's working a charm! Thanks. And you guessed right I was still using ActionLink – B_D Dec 08 '15 at 16:24
0

It can be something like this:

public class PlanController
{
    public ActionResult SuggestedPoints(string plan) //or int planID
    {
       return View();
    }
    public ActionResult AcceptedPoints(string plan) //or int planID
    {
       return View();    
    }
    public ActionResult RejectedPoints(string plan) //or int planID
    {
       return View();    
    }
}

and example urls next:

/Plan/SuggestedPoints/PlanA
/Plan/AcceptedPoints/PlanB
Gene R
  • 3,684
  • 2
  • 17
  • 27