Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ASP.NET MVC Routing - all looks to match the correct route template, but not working

I have a site with a "general" Route structure, and an additional "Translate" area. So at the top level, you have something like:

  • /
  • /About ("generic")
  • /Translate (area)

Within the Translate area, I have:

  • /Translate/Word (WordController, Index action)
  • /Translate/Word/Add (WordController, Add action)
  • /Translate/Word/Improve (WordController, Improve action)

All these work.

However, as soon as I add a further controller to the existing structure, eg. Definition ...

  • /Translate/Definition (DefinitionController, Index action)
  • /Translate/Definition/Add (DefinitionController, Add action)

or Pronunciation ...

  • /Translate/Pronunciation (PronunciationController, Index action)
  • /Translate/Pronunciation/Add (PronunciationController, Add action)

All I get is a 404.

My area's routing configuration is below:

public override void RegisterArea(AreaRegistrationContext context)
    {
        context.MapRoute(
            "Translate_direct",
            "Translate/{controller}/{action}",
            new { action = "Index", controller = "Default", }
        );
        context.MapRoute(
            "Translate_default",
            "Translate/{toLanguageCode}/{query}/{fromLanguageCode}/{controller}/{section}/{action}/{id}",
            new { action = "Index", controller="Default", id = UrlParameter.Optional, section=UrlParameter.Optional }
        );
    }

I have installed Phil Haack's RouteDebugger and have got the following result:

Screenshot

So it appears to match the Controller and Action, but I just get a 404.

For completeness and assurance, my "MVC" file structure is also shown:

enter image description here

I'm clearly missing something obvious but not sure what ... ?


Update:

It seems my namespaces are involved somehow.

My TranslateAreaRegistration class had the namespace Taggloo.Web.Client.Areas.Translate but my PronunciationController had a namespace of *Taggloo.Web.**Mvc.**Client.Areas.Translate.Controllers*

It seems that an error in my namespacing which caused the two to be different (the TranslateAreRegistration class should be in the Taggloo.Web.Mvc.Client.Areas.Translate namespace, too) is the issue. I tried making them both Taggloo.Web.Mvc.... but this didn't work. I've begrudgingly set both to Taggloo.Web.Client... instead and now it works.

So not a solution, a workaround, and despite looking around on this, I'm still none the wiser as to why.

like image 874
Program.X Avatar asked Nov 12 '22 19:11

Program.X


1 Answers

The default area registration in MVC ( System.Web.Mcv.AreaRegistration.RegisterAllAreas ) uses the namespace of the Area's AreaRegistration derived classes to added a Namespace data token to the route definition if you use one of the AreaRegistrationContext.MapRoute overloads.

The DefaultControllerFactory then cross checks the namespace of a controller when matching a route if this Namespaces token defined.

If the controller's namespace is identical ( or starts with if the namespace token ends with .* ) token then the factory will match the controller type and proceed to instantiate the controller. If it's not matched and the ControllerFactory returns null from the GetControllerType method, and ultimately you will get a 404.

You mentioned that you set both to Taggloo.Web.Mvc.... If they were identical it should have worked.

like image 138
Robert Slaney Avatar answered Nov 15 '22 13:11

Robert Slaney