1

我正在关注一本名为“Asp.Net MVC4 in Action”的书。现在他们说,我们可以使用操作方法选择器来区分它,而不是依赖我们代码中的 if 语句来检查请求是否是 Ajax。他们所做的是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

在你有一个带有if内部的动作之前,在重构之后你有 2 个动作,每个动作都返回不同类型的结果。ActionMethodSelectorAttribute用于根据某些条件选择适当的操作。由于 2 个动作具有相同的名称(详细信息),ASP.NET MVC 将使用此属性根据是否正在使用 AJAX 请求来选择一个或另一个。

但老实说,我根本不喜欢这种方法。您现在有 2 个动作,并且重复了var speaker = _repository.FindId(id);两次调用,这不是很干。如果你有这个不是更好吗?

[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(ViewResultPartialViewResult) 以及模型是否已通过。如果是这种情况,我们只需将此结果替换为 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 回答