T4MVC 2.6.10: fluent route value API, shorter way to refer to action, and more

To get the latest build of T4MVC:

Go to T4MVC page on CodePlex

I just posted build 2.6.10.  There were also a few builds in between since I last blogged about 2.6, so this post describes some of those changes (full history here).

Fluent route value API

As you probably know, T4MVC uses a pattern where the route values are encapsulated using a pseudo-call to a controller action, e.g.

     Html.ActionLink("Delete Dinner", MVC.Dinners.Delete(Model.DinnerID))

This adds the controller, the action and the method parameters to the route values in a convenient way with no hard coded strings.

But in some situation, you may need to add extra values to the route that don’t exist in the action method.  Now you can do it as follows:

 Html.ActionLink("Delete Dinner", MVC.Dinners.Delete(Model.DinnerID)
    .AddRouteValue("foo", 17))

You can add multiple values this way using a fluent approach, e.g.

 Html.ActionLink("Delete Dinner", MVC.Dinners.Delete(Model.DinnerID)
    .AddRouteValue("foo", 17)
    .AddRouteValue("bar", "abc"))

As an alternative for adding multiple values, you can write:

 Html.ActionLink("Delete Dinner", MVC.Dinners.Delete(Model.DinnerID)
    .AddRouteValues(new { foo = 17, bar = "abc"}))

Note that in some cases, you may want to omit the action method parameters from the route, possibly because they are meant to come from form data and not from the URL.  For those cases, you can always use the parameter-less override that T4MVC generates (that part is not new), e.g.

 Html.ActionLink("Delete Dinner", MVC.Dinners.Delete()
    .AddRouteValues(new { foo = 17, bar = "abc"}))

The nice thing about this fluent approach is that it doesn’t require adding overloads to all the T4MVC helpers (e.g. Html.ActionLink is this case) to take in the extra route values.  Instead, it automatically applies to any method that uses the T4MVC pattern.

Shortcut to refer to controller actions from within the controller

Suppose you want to redirect to a different action in the same controller.  Normally, in MVC you write something like:

 return RedirectToAction("Details", new { id = dinner.DinnerID });

With T4MVC, you’ve always been able to write:

 return RedirectToAction(MVC.Dinners.Details(dinner.DinnerID));

And now you can simplify it a bit and write:

 return RedirectToAction(Actions.Details(dinner.DinnerID));

So basically, ‘Actions’ is equivalent to MVC.Dinners when you’re within the Dinners controller.

Now some might be tempted to take it a step further and just write:

 return RedirectToAction(Details(dinner.DinnerID));

But that would be horribly wrong, since you would end up actually calling your controller action directly, which is not what you want!  We’re only trying to make a pseudo call to it that captures the route values.

Small breaking change: Actions renamed to ActionNames

This is a result of the previous change.  Unfortunately, the token ‘Actions’ was already used as the way to get all the action names for a controller.  So I ended up renaming it to ActionNames, since Actions was the best name for the new feature above.

So if you’re currently using the pattern ‘MVC.Dinners.Action.Delete’ (to refer to the action name “Delete”), you’ll need to change it to MVC.Dinners.ActionNames.Delete.

Sorry for the little extra pain!

Generate full view paths to allow cross controller references

Previously, when you wrote something like MVC.Dinners.Views.Edit, it would evaluate to “Edit”.  This works fine as long as you are using it from the Dinners controller, which implies that this is the Dinners Edit view as opposed to another controller’s Edit view.

But in some cases, you may want to refer to another controller’s view, and just having the short name no longer works.  So T4MVC was changed to instead make MVC.Dinners.Views.Edit evaluate to the full "~/Views/Dinners/Edit.aspx", which removes all ambiguities.

As far as I know, it should not affect any scenarios that use it, as it never hurts to be more specific.  But let me know if you run into something…

Added way to get area name from both Area and Controller objects

T4MVC now makes the area name available, either from the Area and the Controller.  e.g. you can write MVC.MyArea.Name or MVC.MyArea.MyController.Area, both of which will evaluate to the area name (here “MyArea”).