我怎么会改变ASP.NET 视景的基础上设备的类型?
-
21-09-2019 - |
题
我的工作我的方式通过一些ASP.NET 视的阅读和我有一个网应用程序的工作,我将迁移,从web表单,以软.其中一个要素要求我期望得到的过程必须简化图返回,如果用户来自移动设备。
我不能看看那里的最佳场所是实施这种类型的逻辑。我敢肯定有一个更好的方式比增加一个如果/其他浏览器。IsMobileDevice在每一个行动,返回一个观点。什么样的选择我会不会这样做吗?
解决方案
更新:这种解决方案具有一种细微的错误。该软框架将调入 FindView
/FindPartialView
两次:一旦有 useCache=true
, 如果这不返回的一个结果是,一旦用 useCache=false
.由于只有一个缓对所有类型的意见,移动用户最终可能看到桌面上的风景如果一个桌面浏览器是第一个到达。
对于那些有兴趣在使用定义查引擎了解决这个问题,斯科特Hanselman已经更新了他的解决方案:
http://www.hanselman.com/blog/ABetterASPNETMVCMobileDeviceCapabilitiesViewEngine.aspx
(抱歉回答劫持,我只是不想让别人拥有去过这个!)
编辑roufamatic(萨瓦拉2010-11-17)
第一件事你要做的就是介绍 移动设备浏览器的文件 给你的项目。使用这个文件可以什么都需的设备,以支持,而不必知道具体什么这些设备的送在他们头。此文件已经完成的工作。你再使用的请求。浏览器产量身定制的视图,你要返回。
接下来,想出一个策略就如何你想要整理你的风景下的风景文件夹。我宁愿离开桌面版本的根源然后有一个移动的文件夹。例如家庭景文件夹会是这样的:
- 家
- 移动
- iPhone
- 索引。aspx
- 黑莓
- 索引。aspx
- iPhone
- 索引。aspx
- 移动
我有不同意@Mehrdad关于使用定制图的引擎。看发动机供应多于一个目的,一个目的是寻找视为控制器。你这样做的压倒一切的FindView方法。在这种方法,你可以做你的支票在哪里可以找到。之后您知道哪些装置是使用你的网站,可以使用的战略来与组织的风景返回视为该设备。
public class CustomViewEngine : WebFormViewEngine
{
public override ViewEngineResult FindView(ControllerContext controllerContext, string viewName, string masterName, bool useCache)
{
// Logic for finding views in your project using your strategy for organizing your views under the Views folder.
ViewEngineResult result = null;
var request = controllerContext.HttpContext.Request;
// iPhone Detection
if (request.UserAgent.IndexOf("iPhone",
StringComparison.OrdinalIgnoreCase) > 0)
{
result = base.FindView(controllerContext, "Mobile/iPhone/" + viewName, masterName, useCache);
}
// Blackberry Detection
if (request.UserAgent.IndexOf("BlackBerry",
StringComparison.OrdinalIgnoreCase) > 0)
{
result = base.FindView(controllerContext, "Mobile/BlackBerry/" + viewName, masterName, useCache);
}
// Default Mobile
if (request.Browser.IsMobileDevice)
{
result = base.FindView(controllerContext, "Mobile/" + viewName, masterName, useCache);
}
// Desktop
if (result == null || result.View == null)
{
result = base.FindView(controllerContext, viewName, masterName, useCache);
}
return result;
}
}
上述法允许设置图的基础上你的策略。落后是桌面上来看,如果无视被发现的设备,或者如果没有一个默认的移动图。
如果你决定投入的逻辑控制器,而不是创建一个图的引擎。最好的办法是创建一个自定义 ActionFilterAttribute 你可以装饰你的控制器。然后复盖的 OnActionExecuted 方法来确定哪些设备是看你的站点。你可以检查这个 博客 在如何。后也有一些不错的链接到一些混合的视频在这个非常主题。
其他提示
在模型 - 视图 - 控制器模式,那就是选查看,因此,它不是那么糟糕添加一个if
声明并返回相应的视图控制器。您可以封装if
声明的方法,并调用它:
return AdaptedView(Browser.IsMobileDevice, "MyView.aspx", model);
可替换地,可以创建动态执行基于它是否移动或不是一个视图的视图引擎。我不是这种方法的粉丝,因为我相信,控制器应负责。举例来说,如果你在iPhone上浏览,你可能希望看到完整的桌面版本代替。在前一种方法中,你会通过适当的布尔标志,但在后者,事情变得更加复杂。
我认为,正确的地方堵塞这个功能的定制ViewEngine.但你应该知道的如何 IViewEngine.FindView
方法是通过所谓 ViewEngineCollection
(找到更多的在这 在这里,).
更新 解决方案 建议由科特Hanselman不正常工作。你可以找到我的样本实施这种方法 在这里,.检查readme文件,该文件描述了如何可以重复错误的行为。
我建议另一种方法,检查,如果有人找不到的原ViewEngine如果 useCache
参数 true
, 它检查,如果认存在原ViewEngine用参数 useCache=false
.
它是太复杂把所有的代码这里但你可以找到所提议的方法实现在我的开放源码操场 在这里,.检查 MobileViewEngine
类和单元的测试。
一些MobileViewEngine特点:
- 正常工作与图缓存和使用原始图引擎高速缓存。
- 支持:拍视图的名字和相对路径图(~/Views/Index)用于通过MvcContrib T4的模板。
- 解决"指数"的看如下:
Mobile/Platform/Index
–如果认存在和移动设备的平台(IPhone,安卓等)。 是登记在支持清单。Mobile/Index
-鉴于所有其他移动设备。如果认为不存在可以选择退回到桌面视图的版本。Index
–桌面视图的版本。
- 你可以定制自动观层次(例如
Mobile/ Platform/Manufacturer
)或定制的移动路径图的决议通过加入/更换装置的规则(见MobileDeviceRule
和PlatformSpecificRule
).
希望,这将帮助
这是实际工作,都与T4MVC和在释放模式(其中,被使能的观点高速缓存)的一个版本。它确实需要照顾用户控件和绝对/相对URL的为好。它要求移动装置浏览器文件。
public class MobileCapableWebFormViewEngine : WebFormViewEngine
{
protected override IView CreateView(ControllerContext controllerContext, string viewPath, string masterPath)
{
if (viewPath.EndsWith(".ascx"))
masterPath = "";
return base.CreateView(controllerContext, viewPath, masterPath);
}
public override ViewEngineResult FindView(ControllerContext controllerContext, string viewName, string masterName, bool useCache)
{
useCache = false;
ViewEngineResult result = null;
var request = controllerContext.HttpContext.Request;
if (request.Browser.IsMobileDevice || request["mobile"] != null || request.Url.Host.StartsWith("m."))
{
var mobileViewName = GetMobileViewName(viewName);
result = base.FindView(controllerContext, mobileViewName, masterName, useCache);
if (result == null || result.View == null)
{
result = base.FindView(controllerContext, viewName, "Mobile", useCache);
}
}
if (result == null || result.View == null)
{
result = base.FindView(controllerContext, viewName, masterName, useCache);
}
return result;
}
private static string GetMobileViewName(string partialViewName)
{
var i = partialViewName.LastIndexOf('/');
return i > 0
? partialViewName.Remove(i) + "/Mobile" + partialViewName.Substring(i)
: "Mobile/" + partialViewName;
}
}
您的核心逻辑应该是相同的控制器和唯一的视图,你需要将改变,因此该控制器在你确实需要的if / else语句以服务为每个控制器动作正确的观点,你说。
另一种方法是缠绕你控制器逻辑在一个单独的DLL,并然后具有不同的控制器/路径的移动版本。如果一个普通控制器从移动设备接收到一个请求,你可以将其重定向到包含使用共享控制器逻辑所有的移动控制器移动区域。该解决方案还允许你做“tweeks”特定于移动控制器并且不让它影响你的正常的控制器。