MVC Custom Route. DataTokens[“Namespaces”] is igno

2019-05-10 09:12发布

问题:

I don't know why while creating a CustomRoute which inherits from Route, the field DataTokens["Namespaces"] is ignored.

And I get the error: Multiple types were found that match the controller named 'Home'. This can happen if the route that services this request ('{action}/{id}') does not specify namespaces to search for a controller that matches the request. If this is the case, register this route by calling an overload of the 'MapRoute' method that takes a 'namespaces' parameter. Here is the sample:

Application_Start()

 public static void RegisterRoutes(RouteCollection routes)
 {
        //Create dataTokens object
        var dataTokens = new RouteValueDictionary();
        var ns = new[] {"MvcDomainRouting.Controllers.Delivery" };
        dataTokens["Namespaces"] = ns;

        //Note is a custom route
        routes.Add("DomainRoute", new DomainRoute(
            domain:"delivery.md",                                            // Domain with parameters
            url:"{action}/{id}",                                             // URL with parameters
            defaults: new { controller = "Home", action = "Index", id = "" },// Parameter defaults
            constraints:null,
            dataTokens: dataTokens,
            routeHandler:new MvcRouteHandler()
        ));
}  

DomainRoute.cs

public class DomainRoute : Route
{
    public string Domain { get; set; }

    public DomainRoute(string domain, string url, object defaults, object constraints,object dataTokens, IRouteHandler routeHandler)
        : base(url, new RouteValueDictionary(defaults), new RouteValueDictionary(constraints), new RouteValueDictionary(dataTokens), routeHandler)
    {
        Domain = domain;
    }

    public override RouteData GetRouteData(HttpContextBase httpContext)
    {
        //Details ommited

        // Route data
        RouteData data = new RouteData(this, RouteHandler);

        // 1.Add defaults
        // 2.Map URL key/values
        // Copy the DataTokens from the Route to the RouteData
        if (DataTokens != null)
        {
            foreach (var prop in DataTokens)
            {
                data.DataTokens[prop.Key] = prop.Value;
            }
        }

        return data;
        // At this point `data` holds the DataTokens["Namespaces"] see picture
    }

}

The stack trace from return data;:

HomeController.cs

namespace MvcDomainRouting.Controllers.Lunch
{
    [HandleError]
    public class HomeController : Controller
    {
        public ActionResult Index()
        {
            ViewData["Message"] = "Welcome to ASP.NET MVC!";

            return View();
        }

        public ActionResult About()
        {
            return View();
        }
    }
}

namespace MvcDomainRouting.Controllers.Delivery
{
    [HandleError]
    public class HomeController : Controller
    {
        public ActionResult Index()
        {
            return Content("Index din delivery");
        }

        public ActionResult About()
        {
            return Content("About din delivery");
        }
    }
}

Thanks in advance to each who is sharing experience.

If more details need please ask.

回答1:

The problem was that I was creating a RouteValueDictionary of RouteValueDictionary.

Here is the fixed version:

Like this:

public DomainRoute( ...,object dataTokens,...)
    : base(...,dataTokens as RouteValueDictionary ,...)
//  instead of
//  : base(...,new RouteValueDictionary(dataTokens),..)
{
    Domain = domain;
}

Or like this

        //....
        constraints:null,
        namespaces: new []{"MvcDomainRouting.Controllers.Delivery" },
        routeHandler:new MvcRouteHandler()
    ));

    public DomainRoute( ...,string[] namespaces,...)
    : base(...,new RouteValueDictionary(){{"Namespaces",namespaces}} ,...)
    {

    }