所以,
我在 IIS 6 上有一个 MVC 2 站点(通配符应用程序映射/aspnet_isapi.dll hack),我们希望根据他们的首选位置将人们引导到不同的 URL,比如说 la.acme.com 与 nyc.acme.com。
我不希望任何人最终访问 www.acme.com 或 acme.com。
为了做到这一点,我正在做以下事情(我承认这可能不是最好的方法,这就是我问这个问题的原因):
在我的基本控制器中,我正在执行以下操作:
protected override void Initialize(System.Web.Routing.RequestContext requestContext)
{
ReturnURL = requestContext.HttpContext.Request.Url.PathAndQuery;
BaseUrl = requestContext.HttpContext.Request.Url.Host;
if (!requestContext.HttpContext.Request.Url.IsDefaultPort) {
BaseUrl += ":" + requestContext.HttpContext.Request.Url.Port;
}
ViewData["BaseUrl"] = BaseUrl;
base.Initialize(requestContext);
}
protected override void OnActionExecuted(ActionExecutedContext filterContext)
{
var route = filterContext.RequestContext.RouteData;
var controller = route.GetRequiredString("controller");
var action = route.GetRequiredString("action");
string basePlusHttp = "http://" + BaseUrl;
string basePlusHttps = "https://" + BaseUrl;
string actionsToSkip = "ChooseCity|DisplayPhoto|ChooseLocation|Press|ContactUs|AboutUs|TermsOfService|PrivacyPolicy|Logon|Register|Prospect|";
if (!actionsToSkip.Contains(action + "|")) {
if (BaseUrl.Contains("www.acme.com") || basePlusHttp.StartsWith("http://acme.com") || basePlusHttps.StartsWith("https://acme.com")) {
if (filterContext.HttpContext.Request.Cookies["StoreLocationID"] != null && Convert.ToInt32(filterContext.HttpContext.Request.Cookies["StoreLocationID"].Value) > 0) {
filterContext.HttpContext.Response.Redirect("/Home/ChooseCity/" + Convert.ToInt32(filterContext.HttpContext.Request.Cookies["StoreLocationID"].Value) + "?returnURL=" + ReturnURL);
} else {
aspnet_User user = Repository.GetAspnet_User(filterContext.HttpContext.User.Identity.Name);
if (user != null) {
if (user.StoreLocationID != null) {
int storeLocationID = Convert.ToInt32(user.StoreLocationID);
filterContext.HttpContext.Response.Redirect("/Home/ChooseCity/" + storeLocationID + "?returnURL=" + ReturnURL);
} else {
//get location by IP
string zip = getZipFromIP();
if (!string.IsNullOrEmpty(zip)) {
var zipCode = Repository.GetZipCode(zip);
if (zipCode != null) {
var storeLocation = Repository.GetStoreLocationByZipCodeID(zipCode.ZipCodeID);
if (storeLocation != null) {
filterContext.HttpContext.Response.Redirect("/Home/ChooseCity/" + storeLocation.StoreLocationID + "?returnURL=" + ReturnURL);
} else {
filterContext.HttpContext.Response.Redirect("/Home/ChooseLocation/");
}
} else {
filterContext.HttpContext.Response.Redirect("/Home/ChooseLocation/");
}
} else {
filterContext.HttpContext.Response.Redirect("/Home/ChooseLocation/");
}
}
} else {
//get location by IP
string zip = getZipFromIP();
if (!string.IsNullOrEmpty(zip)) {
var zipCode = Repository.GetZipCode(zip);
if (zipCode != null) {
var storeLocation = Repository.GetStoreLocationByZipCodeID(zipCode.ZipCodeID);
if (storeLocation != null) {
filterContext.HttpContext.Response.Redirect("/Home/ChooseCity/" + storeLocation.StoreLocationID + "?returnURL=" + ReturnURL);
} else {
filterContext.HttpContext.Response.Redirect("/Home/ChooseLocation/");
}
} else {
filterContext.HttpContext.Response.Redirect("/Home/ChooseLocation/");
}
} else {
filterContext.HttpContext.Response.Redirect("/Home/ChooseLocation/");
}
}
}
} else { //make sure the storelocation chookie value is correct based on the URL...we should not have a nyc.acme.com url with an 'la' cookie.
if (BaseUrl.Contains("nyc.")) {
if (filterContext.HttpContext.Request.Cookies["StoreLocationID"] == null) {
filterContext.HttpContext.Response.Redirect("/Home/ChooseCity/3?returnURL=" + ReturnURL);
} else {
if (filterContext.HttpContext.Request.Cookies["StoreLocationID"].Value != "3") {
filterContext.HttpContext.Response.Redirect("/Home/ChooseCity/3?returnURL=" + ReturnURL);
}
}
}
if (BaseUrl.Contains("la.")) {
if (filterContext.HttpContext.Request.Cookies["StoreLocationID"] == null) {
filterContext.HttpContext.Response.Redirect("/Home/ChooseCity/5?returnURL=" + ReturnURL);
} else {
if (filterContext.HttpContext.Request.Cookies["StoreLocationID"].Value != "5") {
filterContext.HttpContext.Response.Redirect("/Home/ChooseCity/5?returnURL=" + ReturnURL);
}
}
}
}
}
base.OnActionExecuted(filterContext);
}
这是上面冗长代码的摘要OnActionExecuted
:
如果用户在我们将允许 www.acme.com 或 acme.com(如 PrivacyPolicy)的“操作”上,那么不要再费心了;
如果 url 包含“www”或者它不包含城市前缀,那么让我们继续,因为我们需要修复这种情况;
如果他们有指定首选城市的 cookie (StoreLocationID),则重定向到 /Home/ChooseCity,我们将在其中设置其他 cookie 并重定向到正确的 URL:nyc.acme.com 或 la.acme.com。
如果他们已登录,并且如果他们的用户帐户列出了首选城市,则使用该城市(重定向到 /Home/ChooseCity - 与上面的 3 相同)
他们没有 cookie,也没有存储在用户帐户中,所以使用他们的 IP 获取 zip 并查看 zip 是否在我们覆盖的城市内或周围,如果是,请发送到 /Home/ChooseCity,如上面 3 和 4
最后,如果我们无法确定他们喜欢哪个城市,我们让他们在 /Home/ChooseLocation/ 手动选择
这一切都有效。但是,我们开始随机注意到以下内容......
有时(并且没有看似模式)用户会点击一个链接并最终进入一个完全随机的页面(不是点击链接的目的地)。看起来他们最终到达的位置通常是另一个用户(分开的城市)可能一直在请求的位置(我知道你正在考虑量子纠缠,但我已经排除了这一点)。就好像 IIS 对谁要求什么感到困惑。
我的问题(毕竟)是我上面的逻辑(in OnActionExecuted
)会导致 IIS 出错吗?应该注意的是,即使对于 URL 中带有 nyc 或 la 的用户,也会出现“随机位置”问题......拥有正确 storelocation cookie 的用户。这意味着用户不应该被重定向到“/Home/ChooseCity”或“/Home/ChooseLocation”,因为他们已经正确配置了 URL 和 cookie。