2012-02-20 6 views
0

APS.NETルーティングを使用して、リクエストがAJAXコールとして発信されたかどうかに基づいて、条件付きで別のアクションにルーティングする方法を教えてください。コントローラ上の例えばリクエストがAJAXコールから発信された場合、条件付きでアクションにルーティングしますか?

私は2つのアクションを持っている可能性があります場合に呼び出されるはずです

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

public ActionResult ListJSON() { return Content(...); } 

を私は両方のアクションが同じURLをしたいのですが、ListJSON()要求はAJAX呼び出しとして発生しました。

答えて

0

それはあなたが簡単にIRouteConstraintを実装することで、独自のルート制約条件を定義することができることが判明した。この目的のためには、カスタムルートを使用することができます。

このような何か:

public class AjaxRouteConstraint : IRouteConstraint { 
    public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection) { 
     return httpContext.Request.IsAjaxRequest(); 
    } 
} 

そして、単にルートでこの制約を使用。この制約があるルートは、制約のないルートの前に来なければならない、そうでなければajaxルートは呼び出されません(非ajaxルートは常に一致します)。

URL生成に関しては、これを行うことによっていくつかの結果が生じる可能性があります。しかし、私はそれらを有意にテストしていません。

2

なぜコードが同じ場合に2つの別々のアクションを使用するのですか?これは異なるビュー結果です。あなたは、すべてのコントローラのアクションでこれをしなければならなかった場合、これはすぐに完全な悪夢になるだろう

public ActionResult List() 
{ 
    var model = ... 
    if (Request.IsAjaxRequest()) 
    { 
     return View(model); 
    } 
    return Json(model); 
} 

明らかに:どの程度

ですから、カスタムアクションフィルタには、このロジックを外部化できます。あなたはまた、世界的なアクションとして、このアクションフィルタを登録することができ

public class MyFilterAttribute: ActionFilterAttribute 
{ 
    public override void OnResultExecuted(ResultExecutedContext filterContext) 
    { 
     if (filterContext.HttpContext.Request.IsAjaxRequest()) 
     { 
      var result = filterContext.Result as ViewResultBase; 
      if (result != null) 
      { 
       filterContext.Result = new JsonResult 
       { 
        Data = result.Model, 
        JsonRequestBehavior = JsonRequestBehavior.AllowGet 
       }; 
      } 
     } 
    } 
} 

:あなたがそうのようなMyFilterAttributeを定義することができ

[MyFilter] 
public ActionResult List() 
{ 
    var model = ... 
    return View(model); 
} 

フィルターを使用して、各コントローラーとそれを必要とするアクションに配置する必要がありません。


UPDATE:

としては、コメント欄で説明したが、OPが2つの異なるアクションを必要としているようです。

public class MyRoute : Route 
{ 
    public MyRoute(string url, object defaults) : 
     base(url, new RouteValueDictionary(defaults), new MvcRouteHandler()) 
    { 
    } 

    public override RouteData GetRouteData(HttpContextBase httpContext) 
    { 
     var rd = base.GetRouteData(httpContext); 
     if (rd == null) 
     { 
      return null; 
     } 

     if (httpContext.Request.IsAjaxRequest()) 
     { 
      rd.Values["action"] = rd.GetRequiredString("action") + "json"; 
     } 

     return rd; 
    } 
} 

Application_Startに登録されます:

public static void RegisterRoutes(RouteCollection routes) 
{ 
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); 

    routes.Add(
     "Default", 
     new MyRoute(
      "{controller}/{action}/{id}", 
      new { controller = "Home", action = "Index", id = UrlParameter.Optional } 
     ) 
    ); 
} 
+0

コードは同じではない可能性があります。実行されたクエリと必要なデータは大きく異なる可能性があります。テスト容易性の観点からは、2つのメソッドを持つ方がクリーンですが、要求に基づいてそれらの間をルーティングします。 –

+0

@JosephDaigle、私の更新を参照してください。 –

+0

それは巧妙な考えです。しかし、あなたが "アクション"値を操作しているので、それがどのようにアウトバウンドURLの生成に影響するのだろうかと思います。 –

関連する問題