2011-06-21 5 views
1

asp.net mvcの新機能(v3 + razorを使用)を使用して、データベースに基づいて動的ルートを作成する際の問題をどのように解決するのかが不思議です。基本的には、メインのサイトナビゲーションはデータベースに入力され、ルートとしてロードする必要があります。すなわち - 可能ならば、データベースからロードカテゴリリスト、そしてRouteHandler vs ControllerFactory

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

など

...ルーティングエンジンへのルートを追加...

スラッシュの後の各カテゴリはdbから来ますが、/ aboutと/ contactusのようなデータベースにはなく、global.asaxに静的に入力されている通常のエントリがあります。 :

動的データベースのURLでは、カスタムRouteHandlerを使用する必要があります。データベースからロードされたエントリの要求に一致して処理するControllerFactoryを作成します。 RouteHandlerまたはCustomControllerFactoryがデータベースからのリスト内のルートを見つけられない場合、DefaultControllerFactoryにルーティングを処理させることは可能ですか?任意の助けてくれてありがとう、これと非常に最初のプロジェクトは、私は最善のルートが何であるかわからないんだけど。...何のしゃれが意図していない)

更新:

から引っ張るルート制約を使用してみました

  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 
      ); 

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); 
    } 
} 

、ここでのルートです:データベースが、それはここに...今、デフォルトルートと競合するには、私のカスタム制約とルートがあります0

ホームページwww.mysite.comはDefaultルートを使用してロードします。制約リストに一致するすべてのURLはカテゴリルートによって読み込まれますが、www.mysite.com/adminまたはwww.mysite.com/aboutusを持っている場合は、これらの値はカテゴリルートによって選択されます制約リストのではなく、です。混乱しています...

答えて

1

であなたのルーティングルールを構築することを意味します。コードは以下のとおりです。私は、Controller Factoryの使用やカスタム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 
      ); 
+0

注意しなければならないのは、通常のコントローラがデータベースの名前と一致しないことを確認することだけですが、私の場合は不可能です。 – bbqchickenrobot

1

どうしたらよいですか?

カテゴリーコントローラ: - ルートルールはその後、一致した場合、着信URLは、各ルートに対してテストされ

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

//... other static routes 

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

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

ルートは、それが一致するかどうかを確認するルールそのルール(およびそれに関連するRouteHandler)は、リクエストを処理するために使用されます(そして、それ以降のすべてのルールは無視されます)。これは通常、私が探していた正確な解決策を見つけた「最も特定少なくとも特有の」注文

source

+0

ねえデイビッド、あなたの返事のためのthx!その解決策はうまくいくかもしれませんが、唯一の問題は、URLカテゴリには「Category」という単語が含まれていないことです。.... DBのリスト(トップカテゴリ)をルートのルートとみなす必要があります。あなたの投稿を読んだら、IDだけが渡されているかのように見えます...最後のパラメータは何をしていますか? – bbqchickenrobot

+0

ちょうどそれが実装されていて、{controller}/{action}/{id}のデフォルトルートと競合しているようです...私はそのルートを取り除く必要がありますか? – bbqchickenrobot

+0

最後のパラメータは、英数字と_のみに一致する経路制約です。最後にデフォルトルートを設定すると、競合が発生しません。 –

関連する問題