使用一个过滤器来执行不同的行动?
-
19-09-2019 - |
题
我想要避免的有很多的 if Request.IsAjaxRequest()
在我的控制器。我在想,如果我可以凝结这种逻辑的一ActionFilter它可以很容易地通过一项公约在应用程序提供一个第二行动的任何请求 可 使用的Ajax,同时提供一个落后的,如果JavaScript是残疾人。
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请求。
是有一个不同的方式的路线通过的要求不同的行动?或者是我在做什么见和我应该找个更好的方式做事吗?
欢呼
解决方案
AcceptAjaxAttribute
可能是为什么在这里需要;然而,我想提出一种不同的方式思考这个问题。
不是所有Ajax请求都是平等的。Ajax请求可能会试图实现任何以下事情:
- 结合java丰富的网格(如jqGrid);
- 析/transforming XML数据,如RSS;
- 载入的部分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行动选择之间做出选择这些方法是如下的做法 "优雅的降解", ,这基本上已经被取代(至少海事组织)通过 逐步增强.
这就是为什么,虽然我喜欢ASP.NET 视,我主要是避免的 AjaxHelper
, 因为我没有找到,它表示这个概念;它试图隐藏了太多的从你。而不是具有的概念"的Ajax形式"或"阿贾克斯行动",让我们做了区分,并坚持要直HTML,然后 注射阿贾克斯功能单独一旦我们确定客户能够处理它。
这里有一个例子,在jQuery-虽然你可以做到这MS阿贾克斯太:
$(function() {
$("#showdetails").click(function() {
$("#details").load("PartialDetails", { id: <%= Record.ID %> });
return false;
}
});
这是所有需要注入阿贾克斯变成一个视页。开始与一个普通的老HTML link和复盖它与阿贾克斯呼叫 去一个不同的控制器行动.
现在,如果在别的地方你网站上你决定要使用一个网格,而不是的,但是不想打破的网页使用的部分呈现,可以编写这样的东西(让我们说你有一个单一主详细说明页面列表中的"订单"上的左侧面和详细表上的权利):
$(".detaillink").click(function() {
$('#detailGrid').setGridParam({
url: $(this).attr("href").replace(/\/order\/details/i,
"/order/jsondetails")
});
$("#detailGrid").trigger("reloadGrid");
});
这种做法完全分离的客户行为从服务器的行为。服务器是有效说的客户: 如果你想id版本, 问问 为id版本,并哦,对了,这里有一个脚本来换你的链接如果你知道如何运行。 没有行动选择,并欺骗与方法的重载,没有特别嘲笑你要做,以便运行一个简单的测试,没有混乱的过其行动做什么的时候。只是一对夫妇的行JavaScript。控制器的行动是短暂而甜蜜的,正是他们应该的。
这并不是唯一的方法。显然,类如 AcceptAjaxAttribute
之所以存在,是因为它们预计会有一些开发人员使用的请求检测方法。但经过试验相当有两个,我找到这种方式 很多 更容易理解,因此更容易设计代码正确。
其他提示
如何接受阿贾克斯属性在MVC期货?