2

if Request.IsAjaxRequest()コントローラーにたくさんあるのは避けたいです。このロジックをActionFilterに凝縮できれば、JavaScriptが無効になっている場合にフォールバックを提供しながら、Ajaxを使用する可能性のあるリクエストに2番目のアクションを提供する規則をアプリケーションに採用するのは簡単だと思っていました。

public ActionResult Details(int id)
{
  // called normally, show full page
}

public ActionResult Details_Ajax(int id)
{
  // called through ajax, return a partial view
}

私は当初、次のようなことができると思っていました。

public class AjaxRenameAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        filterContext.RouteData.Values["action"] = filterContext.RouteData.Values["action"] + "_Ajax";

    }

ただし、呼び出すアクションが決定され、その上のフィルターが処理されるため、これは機能しません。

誰かがアクションを呼び出すたびにRedirectResultを返したくないので、Httpリクエストの量を2倍にするのは少し無意味に思えます。

リクエストを介して別のアクションにルーティングする別の方法はありますか?それとも、私がしていることはお勧めできません。もっと良い方法を探す必要がありますか?

乾杯

4

2 に答える 2

2

MvcFuturesのAcceptAjaxAttributeはどうですか?

于 2009-12-14T16:14:37.490 に答える
1

AcceptAjaxAttributeおそらくここで必要なものです。しかし、私はこの問題について別の考え方を提案したいと思います。

すべてのAjaxリクエストが同じというわけではありません。Ajaxリクエストは、次のいずれかを実行しようとしている可能性があります。

  • JSONデータをリッチグリッド(jqGridなど)にバインドします。
  • RSSフィードなどのXMLデータの解析/変換。
  • ページの領域に部分的なHTMLをロードします。
  • スクリプトを非同期にロードします(google.loadこれを実行できます)。
  • クライアントからの一方向のメッセージを処理します。
  • そして、おそらく私が忘れているもう少し。

メソッドのみに基づいて特定の「代替アクション」を「選択」すると、IsAjaxRequest非常に一般的なもの(非同期要求)をサーバー上の特定の機能に結び付けることになります。最終的には、設計がより脆弱になり、コントローラーの単体テストが困難になります(これを行う方法はいくつかありますが、コンテキストをモックすることができます)。

適切に設計されたアクション一貫している必要があります。それは、要求がどのように行われたかではなく、要求がのためにあるかだけを気にする必要があります。例外などの他の属性を指摘する人もいるかもしれませんが、フィルターを区別します。フィルターは、ほとんどの場合、アクションが「代わりに」ではなく、「前」または「後」に発生する必要がある動作を表します。AuthorizeAttribute

ここで要点を説明すると、質問で述べられている目標は良いものです。異なるアクションとして正しく記述されているものについては、間違いなく異なる方法が必要です。

public ActionResult Details(int id)
{
    return View("Details", GetDetails(id));
}

public ActionResult JsonDetails(int id)
{
    return Json(GetDetails(id));
}

public ActionResult PartialDetails(int id)
{
    return PartialView("DetailTable", GetDetails(id));
}

等々。ただし、Ajaxアクションセレクターを使用してこれらの方法から選択することは、プログレッシブエンハンスメントによって本質的に(少なくともIMOに)取って代わられた「グレースフルデグラデーション」の実践に従います。

これが、ASP.NET MVCが大好きなAjaxHelperのに、この概念をうまく表現していないため、ほとんどの場合、を避けている理由です。それはあなたからあまりにも多くを隠そうとします。「Ajaxフォーム」や「Ajaxアクション」の概念を使用する代わりに、区別をなくしてストレートHTMLに固執し、クライアントが処理できることが確実になったら、Ajax機能を個別に挿入しましょう。

これがjQueryの例です-MSAJAXでもこれを行うことができます:

$(function() {
    $("#showdetails").click(function() {
        $("#details").load("PartialDetails", { id: <%= Record.ID %> });
        return false;
    }
});

AjaxをMVCページに挿入するために必要なのはこれだけです。プレーンな古いHTMLリンクから始めて、別のコントローラーアクションに移動するAjax呼び出しでオーバーライドします。

これで、サイトの他の場所で代わりにグリッドを使用したいが、部分レンダリングを使用してページを分割したくない場合は、次のように記述できます(たとえば、単一のマスター/詳細ページがあるとします。左側に「注文」のリスト、右側に詳細表):

$(".detaillink").click(function() {
    $('#detailGrid').setGridParam({
        url: $(this).attr("href").replace(/\/order\/details/i,
            "/order/jsondetails")
    }); 
    $("#detailGrid").trigger("reloadGrid");  
});

このアプローチは、クライアントの動作をサーバーの動作から完全に切り離します。サーバーはクライアントに効果的に言っています: JSONバージョンが必要な場合は、JSONバージョンを要求します。ちなみに、実行方法を知っている場合は、リンクを変換するスクリプトを次に示します。 アクションセレクターやメソッドのオーバーロードをいじくり回す必要はなく、簡単なテストを実行するために特別なモックを作成する必要もありません。どのアクションがいつ何を実行するかについて混乱することもありません。JavaScriptのほんの数行。コントローラーのアクションは短くて甘く、まさに本来あるべき姿です。

これが唯一のアプローチではありません。明らかに、このようなクラスは、AcceptAjaxAttribute一部の開発者が要求検出メソッドを使用することを期待しているために存在します。しかし、両方でかなり実験した後、私はこの方法を推論するのがはるかに簡単であり、したがって正しく設計/コーディングするのが簡単であることに気付きました。

于 2010-01-17T15:44:08.580 に答える