RouteHandler vs ControllerFactory - PullRequest
1 голос
/ 21 июня 2011

новичок в asp.net mvc (используется v3 + бритва) и мне интересно, как наилучшим образом решить проблему с созданием динамических маршрутов на основе базы данных.По сути, основная навигация по сайту будет занесена в базу данных, и я хочу загрузить их как маршруты.То есть - загрузить список категорий из базы данных, а затем добавить маршруты в механизм маршрутизации, если это возможно ...

mysite.com / cars mysite.com/televisions mysite.com/computers

и т. д....

Каждая категория после косой черты происходит от БД, но есть регулярные записи, такие как / about и / contactus, которых не будет в базе данных, и они были статически введены в global.asax.. мой вопрос:

Для динамических URL базы данных я должен использовать пользовательский RouteHandler или, возможно, создаст ControllerFactory, который будет сопоставлять и обрабатывать запросы для записей, загруженных из базы данных.Возможно ли, чтобы DefaultControllerFactory обрабатывал маршрутизацию, если мои RouteHandler или CustomControllerFactory не находят маршрут в списке из базы данных?Спасибо за любую помощь, самый первый проект с этим, так что я не уверен, что лучший маршрут;) нет каламбура ...

Обновление:

Пробовалиспользуя ограничение маршрута, которое извлекается из базы данных, но теперь оно конфликтует с маршрутом по умолчанию ... вот мое пользовательское ограничение и маршруты:

public class CategoryListConstraint : IRouteConstraint
{
    public CategoryListConstraint()
    {
        var repo = new Repository<Topic>();
        var cats = repo.All();
        var values = new List<string>();
        foreach (var c in cats)
        {
            values.Add(c.URI.Replace("/", "").Replace("?", ""));
        }
        this._values = values.ToArray<string>();
    }

    private string[] _values;

    public bool Match(HttpContextBase httpContext,
      Route route,
      string parameterName,
      RouteValueDictionary values,
      RouteDirection routeDirection)
    {
        // Get the value called "parameterName" from the 
        // RouteValueDictionary called "value"
        string value = values[parameterName].ToString();

        // Return true is the list of allowed values contains 
        // this value.
        return _values.Contains(value);
    }
}

, а вот маршруты:

            Routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

            routes.MapRoute(
                 "Categories",
                 "{category}/{*values}",
                 new { controller = "Category", action = "List" },
                 new CategoryListConstraint()
             );

            Routes.MapRoute(
                "Default", // Route name
                "{controller}/{action}/{id}", // URL with parameters
                new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
            );

Домашняя страница www.mysite.com загружается по маршруту по умолчанию.Все URL-адреса, которые соответствуют списку ограничений, загружаются по маршруту категории ... но если у меня есть www.mysite.com/admin или www.mysite.com/aboutus, они выбираются маршрутом Категории, даже если значения не в списке ограничений.Confused ...

Ответы [ 2 ]

1 голос
/ 26 июня 2011

Нашел точное решение, которое я искал. Код ниже. Мне удалось избежать использования фабрики контроллеров или реализации собственного IRouteHandler с помощью расширения класса RouteBase, который работал отлично и позволил мне передать управление до маршрута mvc по умолчанию, что-то конкретное, что не ударил КСТАТИ - ограничения закончились тем, что не работали должным образом, так как сломали контроллеры, связанные с маршрутом по умолчанию (хотя маршрут по умолчанию был достигнут)

public class CustomRoutingEngine : RouteBase 
{
    public override RouteData GetRouteData(HttpContextBase httpContext)
    {                       
        var routeHandler = new MvcRouteHandler();
        var currentRoute = new Route("{controller}/{*URI}", routeHandler);
        var routeData = new RouteData(currentRoute, routeHandler);

        // implement caching here
        var list = GetConstraintList();

        // set your values dynamically here
        routeData.Values["controller"] = "Category";
        // or
        routeData.Values.Add("action", "List");

        // return the route, or null to have it passed to the next routing engine in the list
        var url = Util.StripSlashOnFrontAndBack(httpContext.Request.Path.ToLower()).Split('/')[0];
        if (list.Contains(url))
            return routeData;
        return null;  // have another route handle the routing
    }


    protected List<string> GetConstraintList()
    {
        using (var repo = new RavenRepository<Topic>())
        {
            var tops = repo.Query().Where(x => x.Hidden == false).ToList()
                .Select(x=>x.Name.ToLower());
            List<string> list = new List<string>();
            list.AddRange(tops);
            repo.Dispose();
            return list ?? new List<string>();
        }
    }

    public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
    {
        //implement this to return url's for routes, or null to just pass it on
        return null;
    }
}

Тогда мой метод регистрации маршрутов выглядит так:

            Routes.Clear();

            // Set Defaults
            Routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

            AreaRegistration.RegisterAllAreas();                

            routes.Add(new App.Helpers.CustomRoutingEngine());

            Routes.MapRoute(
                "Default", // Route name
                "{controller}/{action}/{id}", // URL with parameters
                new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
            );
1 голос
/ 21 июня 2011

Как насчет этого?

Контроллер категорий:

public ActionResult List(string category)
{
    var products = _repo.Get(category); // however you are getting your data
    return View(products);
}

Маршруты

routers.MapRoute(
    "About",
    "About",
    new { controller = "Home", action = "About" });

//... other static routes

routes.MapRoute(
    "CategoriesList",
    "{id}",
    new { controller = "Categories", action = "List" },
    new { id = @"\w+" });

Входящий URL-адрес проверяется на соответствие каждому правилу маршрутизации, чтобы определить, совпадает ли оно с правилом маршрутизации, и именно тогда это правило (и связанный с ним RouteHandler) используется для обработки запроса (и все последующие правила игнорируются).,Это означает, что вы, как правило, хотите структурировать свои правила маршрутизации в порядке «от наиболее конкретного к наименее конкретному»

source

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...