我有一个有效的MVC网站。为了增加其视觉吸引力,我想重新创建所有视图以使用Bootstrap。这不需要对模型或控制器进行任何更改。
在过渡期间,我希望根据是否设置特定的“Beta模式”cookie,将用户定向到不同的视图。例如,他们将被引导到以下之一:
Index.cshtml
Index.beta.cshtml
如何在不更改每个控制器中的代码的情况下完成此操作?
答案 0 :(得分:1)
在我关联的帖子之后,我做了一个天真的实施。注意:这是未经测试的测试。对于我的测试,我硬编码IsBeta返回true,然后它找不到任何视图(因为我没有名为ViewName.beta.cshtml的视图)。将Index.cshtml重命名为Index.beta.cshtml后,它按预期解析了索引视图。
public class BetaViewEngineTest : RazorViewEngine
{
public BetaViewEngineTest() : base()
{
AreaViewLocationFormats = new string[] { "~/Areas/{2}/Views/{1}/{0}%1.cshtml",
"~/Areas/{2}/Views/{1}/{0}%1.vbhtml",
"~/Areas/{2}/Views/Shared/{0}%1.cshtml",
"~/Areas/{2}/Views/Shared/{0}%1.vbhtml" };
AreaMasterLocationFormats = new string[] { "~/Areas/{2}/Views/{1}/{0}%1.cshtml",
"~/Areas/{2}/Views/{1}/{0}%1.vbhtml",
"~/Areas/{2}/Views/Shared/{0}%1.cshtml",
"~/Areas/{2}/Views/Shared/{0}%1.vbhtml" };
AreaPartialViewLocationFormats = new string[] { "~/Areas/{2}/Views/{1}/{0}%1.cshtml",
"~/Areas/{2}/Views/{1}/{0}%1.vbhtml",
"~/Areas/{2}/Views/Shared/{0}%1.cshtml",
"~/Areas/{2}/Views/Shared/{0}%1.vbhtml" };
ViewLocationFormats = new string[] { "~/Views/{1}/{0}%1.cshtml",
"~/Views/{1}/{0}%1.vbhtml",
"~/Views/Shared/{0}%1.cshtml",
"~/Views/Shared/{0}%1.vbhtml" };
MasterLocationFormats = new string[] { "~/Views/{1}/{0}%1.cshtml",
"~/Views/{1}/{0}%1.vbhtml",
"~/Views/Shared/{0}%1.cshtml",
"~/Views/Shared/{0}%1.vbhtml" };
PartialViewLocationFormats = new string[] { "~/Views/{1}/{0}%1.cshtml",
"~/Views/{1}/{0}%1.vbhtml",
"~/Views/Shared/{0}%1.cshtml",
"~/Views/Shared/{0}%1.vbhtml" };
FileExtensions = new string[] { "cshtml", "vbhtml" };
}
protected override IView CreateView(ControllerContext controllerContext, string viewPath, string masterPath)
{
return base.CreateView(controllerContext, IsBeta(controllerContext) ? viewPath.Replace("%1", ".beta") : viewPath.Replace("%1", ""), masterPath);
}
protected override IView CreatePartialView(ControllerContext controllerContext, string partialPath)
{
return base.CreatePartialView(controllerContext, IsBeta(controllerContext) ? partialPath.Replace("%1", ".beta") : partialPath.Replace("%1", ""));
}
protected override bool FileExists(ControllerContext controllerContext, string virtualPath)
{
var isBeta = IsBeta(controllerContext);
if (isBeta)
{
return base.FileExists(controllerContext, virtualPath.Replace("%1", ".beta"));
}
else
{
return base.FileExists(controllerContext, virtualPath);
}
}
private bool IsBeta(ControllerContext ctx)
{
bool isBeta = false;
var httpCookie = ctx.HttpContext.Request.Cookies["Beta"];
if (httpCookie != null)
Boolean.TryParse(httpCookie.Value, out isBeta);
return isBeta;
}
}
几乎忘了,Global.asax.cs,添加以下几行:
ViewEngines.Engines.Clear();
ViewEngines.Engines.Add(new BetaViewEngineTest());
答案 1 :(得分:1)
杰克的答案..
public class BetaViewEngine : RazorViewEngine
{
private readonly IBetaCookieChecker _betaCookieChecker;
public ToolsViewEngine(IBetaCookieChecker betaCookieChecker)
{
_betaCookieChecker = betaCookieChecker;
}
public override ViewEngineResult FindView(ControllerContext controllerContext, string viewName, string masterName, bool useCache)
{
if (_betaCookieChecker.UserHasBetaCookie())
{
ViewLocationFormats = new[]
{
"~/Views/{1}/{0}.beta.cshtml",
};
PartialViewLocationFormats = new[]
{
"~/Views/{1}/{0}.beta.cshtml",
"~/Views/Shared/{0}.beta.cshtml",
};
}
return base.FindView(controllerContext, viewName, masterName, useCache);
}
}
IBetaCookieChecker
会对Jack的IsBeta
方法产生类似的影响。
您还需要在global.asax中注入IBetaCookieChecker
,或许像ViewEngines.Engines.Add(new ToolsViewEngine(container.Resolve<IBetaCookieChecker>()));