views:

125

answers:

1

I am creating a modular ASP.NET MVC application using areas. In short, I have created a greedy route that captures all routes beginning with {application}/{*catchAll}.

Here is the action:

// get /application/index  
public ActionResult Index(string application, object catchAll)  
{  
  // forward to partial request to return partial view  
  ViewData["partialRequest"] = new PartialRequest(catchAll);  

  // this gets called in the view page and uses a partial request class to return a partial view  
}  

Example:

The Url "/Application/Accounts/LogOn" will then cause the Index action to pass "/Accounts/LogOn" into the PartialRequest, but as a string value.

// partial request constructor  
public PartialRequest(object routeValues)  
{  
  RouteValueDictionary = new RouteValueDictionary(routeValues);  
}  

In this case, the route value dictionary will not return any values for the routeData, whereas if I specify a route in the Index Action:

ViewData["partialRequest"] = new PartialRequest(new { controller = "accounts", action = "logon" });

It works, and the routeData values contains a "controller" key and an "action" key; whereas before, the keys are empty, and therefore the rest of the class wont work.

So my question is, how can I convert the "/Accounts/LogOn" in the catchAll to "new { controller = "accounts", action = "logon" }"??

If this is not clear, I will explain more! :)

Matt

This is the "closest" I have got, but it obviously wont work for complex routes:

// split values into array
var routeParts = catchAll.ToString().Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries);  

// feels like a hack
catchAll = new
{
  controller = routeParts[0],
  action = routeParts[1]
}; 
A: 

You need to know what part is what in the catchAll parameter. Then you need to parse it yourself (like you are doing in your example or use a regexp). There is no way for the framework to know what part is the controller name and what is the action name and so on, as you haven't specified that in your route.

Why do you want to do something like this? There is probably a better way.

Mattias Jakobsson
That makes sense, thank you!The areas in the MVC application return partial views (so I can have more than one partial view on a page). This is a problem when linking directly to the partial view (such as Accounts/LogOn, which will return a partial view called LogOn). It will return the partial view itself, and not a view that contains the rest of the html page.This is why I wanted to create a greedy route that forces the application to return a view with the partial requests inside.Any ideas?
mwgriffiths
@mwgriffiths, Okay, I see. I guess you mean that you are using Html.RenderAction(...) and want to render different views depending on if you the url is called from that method or directly from the browser? I can see the benefits of that. However, I usually split them into two actions, one for using when I call Html.RenderAction() and another one for when you want to just view the page.
Mattias Jakobsson
@Mattias Jakobsson; A little bit like you described, yes! can you explain a bit more about the last point though? about the two actions? I might be missing the meaning!I don't consider myself a novice in MVC, I thought a strongly typed master page was bad (took 3 days!), but this has me stumped!
mwgriffiths
@mwgriffiths, I would create two actions. One called "LogOn" that have a view with your master page. Then you have another called "LogOnController" or something that you use whenever you want to render a logon box on any other page (when you use Html.RenderAction()).
Mattias Jakobsson
@Mattias Jakobsson; that is simple! :) and may have worked if I didn't want themeing in my application (the use of different master pages that may have different placeholders and then wont work with views that have been set to a different placeholder structure)Can I cast the catchAll property as an object I can use with keys and values??Thanks for your help, btw, I would vote you up but I need 15 posts!
mwgriffiths
@mwgriffiths, I don't see how this would effect theming? There is no way of casting the catchAll as there is no way for the framework to work out the keys. You could run the catchAll string through the routing in the same way the framework does for each request. But that means you will create fake contexts and requests and it will be quite a lot of extra work.
Mattias Jakobsson
@Mattias Jakobsson; Sorry, I am completely wrong, and you are completely right :) - I was literally looking into creating my own route handler, in fact - I had just created one (I just couldnt get the process request event to fire).That is much simpler, thanks!
mwgriffiths