1

「Asp.Net MVC4 in Action」という本をフォローしています。そして今、ある時点で、リクエストが Ajax であるかどうかを確認するためにコード内の if ステートメントに依存する代わりに、アクション メソッド セレクターを使用してそれを区別できると言われています。そして、彼らが行ったことはAcceptAjaxAttribute、次のコードでクラスを作成することです

using System;
using System.Reflection;
using System.Web.Mvc;

namespace CustomAjax
{
    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
    public class AcceptAjaxAttribute : ActionMethodSelectorAttribute
    {
        public override bool IsValidForRequest(ControllerContext controllerContext, MethodInfo methodInfo)
        {
            return controllerContext.HttpContext.Request.IsAjaxRequest();
        }
    }
}

以前はこのように見えたコントローラーの関数

var speaker = _repository.FindSpeaker(id);
if(Request.IsAjaxRequest())
{
   return Json(speaker, JsonRequestBehaviour.AllowGet);
}

return View();

このようなものに変わりました

 [AcceptAjax]
 public ActionResult Details(int id)
 {
     var speaker = _repository.FindId(id);

     return Json(speaker, JsonRequestBehavior.AllowGet);
 }
 [ActionName("Details")]
 public ActionResult Details_NonAjax(int id)
 {
      var speaker = _repository.FindId(id);
      return View();
 }

正直なところ、何が行われているのか、なぜ新しいクラスを作成して [AcceptAjax] を使用したのかわかりません。誰かが私に説明してくれるかもしれません。

4

1 に答える 1

8

内部を持つ 1 つのアクションが存在する前はif、リファクタリング後には、それぞれ異なるタイプの結果を返す 2 つのアクションが存在します。はActionMethodSelectorAttribute、いくつかの条件に基づいて適切なアクションを選択するために使用されます。2 つのアクションは同じ名前 (詳細) を持っているため、ASP.NET MVC はこの属性を使用して、AJAX 要求が使用されているかどうかに基づいていずれかを選択します。

しかし、正直なところ、私はこのアプローチがまったく好きではありません。これで 2 つのアクションがあり、var speaker = _repository.FindId(id);呼び出しを 2 回繰り返しましたが、これはあまり DRY ではありません。これがあればもっといいんじゃない?

[AcceptAjax]
public ActionResult Details(int id)
{
    var speaker = _repository.FindId(id);
    return View(speaker);
}

あなたが私のようで、これがより良いと思うなら、AcceptAjaxAttribute本から得たこれをアクションフィルターに置き換えるだけです:

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class AcceptAjaxAttribute : ActionFilterAttribute
{
    public override void OnActionExecuted(ActionExecutedContext filterContext)
    {
        if (filterContext.RequestContext.HttpContext.Request.IsAjaxRequest())
        {
            var result = filterContext.Result as ViewResultBase;
            if (result != null && result.Model != null)
            {
                filterContext.Result = new JsonResult
                {
                    Data = result.Model,
                    JsonRequestBehavior = JsonRequestBehavior.AllowGet
                };
            }
        }
    }
}

このOnActionExecutedメソッドは、コントローラー アクションの実行が終了して何らかの結果が返された後に呼び出されます。ViewResultBaseこのメソッド内で、コントローラー アクションが(ViewResultまたは) を返したPartialViewResultかどうか、およびモデルが渡されたかどうかを確認します。この場合、この結果を JsonResult に置き換えるだけです。

また、すべてのコントローラー アクションをこの属性で装飾したくない場合は[AcceptAjax]、グローバル アクション フィルターとして次のように登録できます~/App_Start/FilterConfig.cs

public class FilterConfig
{
    public static void RegisterGlobalFilters(GlobalFilterCollection filters)
    {
        filters.Add(new HandleErrorAttribute());
        filters.Add(new AcceptAjaxAttribute());
    }
}
于 2013-05-16T11:54:02.350 に答える