【发布时间】:2015-10-26 15:26:42
【问题描述】:
想象一个站点绑定了许多域。 f.e. product1.com、product2.com、...
当 product23 出现故障时,想法是让“landingpagecontroller”处理对 product23.com 的所有请求。
这个想法是写一个 ActionFilter 来完成这个:
public class Landingpage : IActionFilter
{
public void OnActionExecuting(ActionExecutingContext filterContext)
{
var DnsSafeHost = filterContext.HttpContext.Request.Url.DnsSafeHost;
if (DnsSafeHost.NeedsLandingpage())
{
//Do actual redirecting
}
}
}
NeedsLandingpage() 返回一个布尔值。如果需要登陆页面控制器服务,则为真。情报将在数据库中找到。
我已经添加了到登录页面控制器的路由。
routes.MapRoute(
name: "Ladingpage",
url: "Landingpage/{id}/{*dummy}",
defaults: new { controller = "LandingPage", action = "Index" }
);
关于如何从 actionfilter 更改路由设置以触发上述路由或实现目标的更好解决方案的任何提示。
********** 已更新 ************
鉴于大家的意见,我想出了以下可行的解决方案,但我对它并不是 100% 满意。因此,欢迎提供更好的解决方案。
我创建了以下 IActionFilter 并将其注册为全局。
public class Landingpage : IActionFilter
{
public void OnActionExecuting(ActionExecutingContext filterContext)
{
var DnsSafeHost = filterContext.HttpContext.Request.Url.DnsSafeHost;
var _LandingPage = LandingPage(DnsSafeHost);
if (_LandingPage != null)
{
if ((String)filterContext.RouteData.Values["controller"] != "Landingpage")
{
filterContext.Result = new RedirectToRouteResult(new RouteValueDictionary(new { controller = "Landingpage", action = "Index", id = _LandingPage }));
filterContext.Result.ExecuteResult(filterContext.Controller.ControllerContext);
}
}
}
private String LandingPage(String DnsSafeHost)
{
if (DnsSafeHost.Contains("<domain to look for>".ToLower())) return "<viewname>";
if (DnsSafeHost.Contains("<domain to look for>".ToLower())) return "<viewname>";
if (DnsSafeHost.Contains("<domain to look for>".ToLower())) return "<viewname>";
return null;
}
}
我不喜欢的解决方案是检查 (String)filterContext.RouteData.Values["controller"]
这是需要的,否则你会陷入循环,因为。
浏览器 -> 路由 -> 过滤器 -> 重定向 -> 路由 -> 过滤器 ...
我认为可能的解决方案是在 Application_BeginRequest (global.asax) 中做一些事情。但我没有找到“重写”请求的方法。因为如果可能的话,流程将是: 浏览器 -> BeginRequest -> RewriteRequest -> 路由 -> 控制器。
我猜,如果您遵循最佳实践,那么在 vNext 中,这似乎不再适用。
Filterconfig.cs
public class FilterConfig
{
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new HandleErrorAttribute());
filters.Add(new Landingpage());
}
}
所有“登陆页面”调用都被重定向到登陆页面控制器。 调用 ViewEngine 是为了检查从 actionfilter 传递的视图名称是否存在,如果不使用默认值。
public class LandingpageController : Controller
{
public ActionResult Index(string id)
{
if (id == null) return View();
if (ViewEngines.Engines.FindView(ControllerContext, id, null).View == null) return View();
ViewBag.Title = id;
return View(id);
}
}
视图示例。
@{
Layout = "_Index_layout.cshtml";
}
<div class="domainname">Landingpage</div>
为了给它一个不同于普通页面的“特殊”布局(例如没有菜单),我为此页面添加了一个自定义布局。
<!DOCTYPE html>
<html>
<head>
<title>@ViewBag.Title</title>
<style>
--- add some styling here ---
</style>
</head>
<body>
@RenderBody()
</body>
</html>
【问题讨论】:
-
可以在这里找到可能的解决方案(特别是Syakur Rahman给出的答案)http://stackoverflow.com/questions/5453338/redirect-from-action-filter-attribute
-
在发布 Q 之前尝试过。它循环多次并退出循环,但从未真正进入控制方法。问题是这是一个重定向,因此一次又一次地执行这个过滤器。我正在寻找一种方法来更改请求,以便通过路由引擎的请求与在浏览器中输入 www.product21.com/landingpage 的请求相同。
-
也许我搞错了。路由是在全局过滤器之前还是之后?
标签: c# asp.net-mvc custom-action-filter