2012-12-11 15 views
7

デフォルトのコントローラ= Homeおよびデフォルトのアクション=インデックスでASP.NET MVC 4の既存のコントローラ/アクション/ IDルーティングを維持したいと思います。 2番目の項目が既知のアクションでない限り、コントローラのインデックスメソッドにルーティングします。例えばASP.NET MVC 4でIDを使用したインデックスへのルーティング

、アクションインデックス付きのコントローラホームを与えられ、送信:

/Home/Send -> controller's Send method 
/Home -> controller's Index method 
/Home/Send/xyz -> controller's Send method with id = xyz 
/Home/abc -> controller's Index method with id = abc 

を私が最初にどちらかのルートを定義する場合は、それが他のものを隠します。どうすればいい?

+0

RouteTableで経路をどのように定義しましたか? –

+0

@FelipeOriani私はどちらか一方を作成すると、他のものを隠すことになります。 –

答えて

2

、私たちは、カスタムConstraintImplementationを使用することができます。

public class MyRouteConstraint : IRouteConstraint 
{ 
    public readonly IList<string> KnownActions = new List<string> 
     { "Send", "Find", ... }; // explicit action names 

    public bool Match(System.Web.HttpContextBase httpContext, Route route 
        , string parameterName, RouteValueDictionary values 
        , RouteDirection routeDirection) 
    { 
    // for now skip the Url generation 
    if (routeDirection.Equals(RouteDirection.UrlGeneration)) 
    { 
     return false; // leave it on default 
    } 

    // try to find out our parameters 
    string action = values["action"].ToString(); 
    string id = values["id"].ToString(); 

    // id and action were provided? 
    var bothProvided = !(string.IsNullOrEmpty(action) || string.IsNullOrEmpty(id)); 
    if (bothProvided) 
    { 
     return false; // leave it on default 
    } 

    var isKnownAction = KnownActions.Contains(action 
          , StringComparer.InvariantCultureIgnoreCase); 

    // action is known 
    if (isKnownAction) 
    { 
     return false; // leave it on default 
    } 

    // action is not known, id was found 
    values["action"] = "Index"; // change action 
    values["id"] = action; // use the id 

    return true; 
    } 

と(デフォルト1前 - の両方が提供されなければならない)ルートマップ、次のようになります。

routes.MapRoute(
    name: "DefaultMap", 
    url: "{controller}/{action}/{id}", 
    defaults: new { controller = string.Empty, action = "Index", id = string.Empty }, 
    constraints: new { lang = new MyRouteConstraint() } 
); 

合計mary:この場合、「アクション」パラメータの値を評価しています。

  • 1)アクションと2)idが提供されている場合は、ここでは扱いません。
  • これが(リストまたは反映された)既知の操作であるかどうか。
  • アクション名が不明な場合のみ、ルート値を変更してください:アクションを「インデックス」に設定し、アクション値をIDに変更してください。

注:

1)RouteConfigで、私はあることを、これを置く:action名前とid値は一意である必要があります...これは私のために働いていた何これは

+0

これから実際のコントローラクラスのタイプを識別し、アクションが一致するかどうかを確認できますか?私は手動でアクション名のリストを作成したくありません。 –

+0

解決策が見つかるかもしれない2つの同様の質問があります(私が呼びかけました):http://stackoverflow.com/questions/13602238、http://stackoverflow.com/questions/13423545コントローラの名前はルートの一部であるため、いくつかのリフレクション...しかし、ほとんどはカスタムメソッドで行う必要があります( –

5

デフォルトのジェネラルワンよりも先に特定のものを実行します。注文は重要です。

routes.MapRoute(name: "single", url: "{controller}/{id}", 
    defaults: new { controller = "Home", action = "Index" }, 
    constraints: new { id = @"^[0-9]+$" }); 

routes.MapRoute(
    name: "Default", 
    url: "{controller}/{action}/{id}", 
    defaults: new { controller = "Home", 
    action = "Index", 
    id = UrlParameter.Optional } 
); 
+0

私のIDは、残念ながら数字である必要はありません。その文字列、そして何でも行く。 –

+1

あなたは経路の制約を取り除くことができます – Shyju

+0

私は制約を取り除くと、コントローラー/アクション(IDなし)に対する要求は、適切なアクションの代わりにコントローラー/ IDと一致します。 –

0

2つの競合するルートがあるため、要件に応じたソリューションはありません。たぶん、特定のものを定義することができます(他のコントローラがない場合)。あなたの行動(例えばを送る)のリストは、よく知られており、その(アクション)名は、いくつかのID値と同じにすることができないという場合には

routes.MapRoute(
     name: "Send", 
     url: "{controller}/Send/{id}", 
     defaults: new { controller = "Home", id = UrlParameter.Optional } 
    ); 
routes.MapRoute(
     name: "Home", 
     url: "Home", 
     defaults: new { controller = "Home", action = "Index" } 

routes.MapRoute(
     name: "Index", 
     url: "{controller}/{id}", 
     defaults: new { controller = "Home", action= "Index", 
          id = UrlParameter.Optional } 
    ); 

routes.MapRoute(
     name: "Default", 
     url: "{controller}/{action}/{id}", 
     defaults: new { controller = "Home", action = "Index", 
               id = UrlParameter.Optional } 
    ); 
0

動作します最初のライン:

routes.MapRoute(name: "single", url: "{controller}/{lastName}", 
      defaults: new { controller = "LeaveRequests", action = "Index" }); 

2)私の制御装置において:

あなたは

http://localhost:34333/leaveRequests/Simpsons 

コントローラを呼び出すとき

public ViewResult Index(string lastName) 
{ 
    if (lastName == null) 
    { 
     return //return somthing 
    } 
    else 
    { 
     return //return something 
    } 
} 

3)それはあなたのシンプソンズのためのすべての要求を提供します。あなたがhttp://localhost:34333/leaveRequests/ を呼び出す場合

これは私

routes.IgnoreRoute( "{}リソース.axd/{*}パス情報")のために働くすべての要求に

0

を与えるだろう。

 routes.MapRoute(
      name: "Default1", 
      url: "{id}", 
      defaults: new { controller = "Home", action = "Index" } 
     ); 

     routes.MapRoute(
      name: "Default", 
      url: "{controller}/{action}/{id}", 
      defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional } 
     ); 
+0

ここでの順序は重要です。 –

1

最も簡単な方法は、コントローラに2つのアクションメソッドを作成することです。 1つはインデックス用、もう1つは送信用で、両方に文字列idパラメータを配置します。重複または過負荷のアクションメソッドを持つことはできないので、その問題を解決します。 Indexメソッドは、IDが存在するかどうか(null)のインデックスパスまたはブランクパスの両方を処理し、そのようにビューを処理します。あなたのSendメソッドは、Indexと全く同じ働きをします。次に、idがnullかどうかに応じて、あなたが好きな方法でルーティング、処理、またはリダイレクトすることができます。これはRouteConfig.csを変更せずに動作するはずです:

public ActionResult Index(string id) {if (id == null) Do A else Do B} 

public ActionResult Send(string id) {if (id == null) Do A else Do B} 

私は長い間、この闘争があったが、これは最も簡単な解決策でした。

関連する問題