Custom Routing for the Recipe Controllers (MVC)

I’ve been working on re-factoring the add recipe feature to include a draft recipe domain object. However the recipe controller has been steadily expanding, along with the number of unit tests to support it. This was causing me issues as it was getting difficult to scan through the files to find the methods I’m interested in. So I’ve introduced some custom routing and split up the recipe controller.


Original recipe controller signature
This was the recipe controller signature before introducing the customer routing (for brevity in this post I’ve extracted the controller signature to an interface, the interface is not actually used in the project):


    interface IRecipesController
    {
        ActionResult Index(string title);

        ActionResult EditIngredients(string recipeTitle);
        ActionResult EditIngredients(RecipeIngredientsModel ingredientsModel);

        ActionResult EditMethod(string recipeTitle);
        ActionResult AddRecipeIngredient(RecipeIngredientsModel ingredientsModel);
        ActionResult SearchIngredients(RecipeIngredientsModel ingredientsModel);
        ActionResult EditMethod(RecipeMethodModel methodModel);

        ActionResult EditSummary(string recipeTitle);
        ActionResult EditSummary(RecipeSummaryModel summaryModel);   
    }

So that’s 9 public methods, along with some private methods, taking the total up to around 15. I thought that was too many for the class to be easily manageable.


Custom Routing Implementation


In Sharp Architecture projects the custom routing instructions need to be added in the RouteRegistrar.cs file, located in the Web.Controllers assembly. Handily, the Sharp architecture example project had an example similar to what I was trying to achieve, so I just needed to tweak the area and route URL’s to make my customer routing:


    routes.CreateArea("Recipes", "RecipeBook.Web.Controllers.Recipes",
        routes.MapRoute(null, "Recipes/{controller}/{action}", new { action = "Index" }),
        routes.MapRoute(null, "Recipes/{controller}/{action}/{id}")
    );

Coding Tweaks


An interesting result of this routing change was the tweaks that needed to be made to the code:

  • The action links in Views must now use the Html.ActionLinkForAreas() method instead of Html.ActionLink()
  • RedirectToAction calls in controllers must include the controller name
  • Tests for Controller Actions, which redirect to another controller, should make use of the ToController(controllerName) MvcContrib TestHelper extension method.

Revised controller signatures


After implementing the custom routing the controllers and tests could be broken up into 4 separate files with the following method signatures:


    interface IRecipesController    
    {
        ActionResult Index(string title);
    }
    interface ISummaryController    
    {
        ActionResult Edit(string recipeTitle);              
        ActionResult Edit(RecipeSummaryModel summaryModel); //Post        
    }
    interface IMethodController    
    {
        ActionResult Edit(string recipeTitle);
        ActionResult Edit(RecipeMethodModel methodModel);   //Post
    }
    interface IRecipeIngredientsController
    {
        ActionResult Edit(string recipeTitle);
        ActionResult AddRecipeIngredient(RecipeIngredientsModel ingredientsModel);  //Post
        ActionResult Edit(RecipeIngredientsModel ingredientsModel);                 //Post    
        ActionResult SearchIngredients(RecipeIngredientsModel ingredientsModel);    //Post
    }

Comments

Copyright © 2016 - Hook Technologies Ltd - Powered by Octopress