Using DisplayModeProvider to choose between views for "Desktop", "Tablet" and "Phone" in a MVC5 web application. It is my understanding that this class selects the correct provider in order and uses the first provider that returns True. However, when I step through the code, I find there is a repeated cycle through the code (it goes through multiple times, sometimes over 10 cycles) before deciding on the proper mode. I'm using WURFL Cloud for device detection. Lastly, I've started caching WURFL results in a Session variable. Thinking there must be something wrong with my code and/or logic. It's in VB.net since it's an evolution of a legacy project. The first block of code is in Application_Start in global.asax. Before it was in a separate class, but moved it to global.asax in an attempt to solve this problem.
DisplayModeProvider.Instance.Modes.Clear()
DisplayModeProvider.Instance.Modes.Add(New DefaultDisplayMode("Phone") With {.ContextCondition = Function(c) c.Request.IsPhone})
DisplayModeProvider.Instance.Modes.Add(New DefaultDisplayMode("Tablet") With {.ContextCondition = Function(c) c.Request.IsTablet})
DisplayModeProvider.Instance.Modes.Add(New DefaultDisplayMode("") With {.ContextCondition = Function(c) c.Request.IsDesktop})
My understanding is the function would check for each context condition and stop at the first one that is true. However, as mentioned above the code repeatedly executes even though one of the functions returns True.
Here are the extension methods I'm using. They reside in a module. The error handling code was added after a "perceived" outage of the WURFL cloud. Each is decorated with the following: System.Runtime.CompilerServices.Extension
Public Function IsPhone(request As HttpRequestBase) As Boolean
Dim ans As Boolean
Try
If Not HttpContext.Current.Session("IsPhone") Is Nothing Then
ans = HttpContext.Current.Session("IsPhone")
Else
wsm = New WURFLServiceModel(New HttpContextWrapper(HttpContext.Current))
ans = wsm.IsPhone
HttpContext.Current.Session("IsPhone") = ans
End If
Catch ex As Exception
...
End Try
Return ans
End Function
Public Function IsTablet(request As HttpRequestBase) As Boolean
Dim ans As Boolean
Try
If Not HttpContext.Current.Session("IsTablet") Is Nothing Then
ans = HttpContext.Current.Session("IsTablet")
Else
wsm = New WURFLServiceModel(New HttpContextWrapper(HttpContext.Current))
ans = wsm.IsTablet
HttpContext.Current.Session("IsTablet") = ans
End If
Catch ex As Exception
...
End Try
Return ans
End Function
Public Function IsDesktop(request As HttpRequestBase) As Boolean
Return True
End Function
Here is the code for the WURFLServiceModel
Imports ScientiaMobile.WurflCloud.Device Public Class WURFLServiceModel Private mIsIOS As Boolean Private mIsTablet As Boolean Private mIsPhone As Boolean Private mResponse As String Private mErrors As Dictionary(Of String, String) Private api_Key As String = "xxxxxxxxxxxxxxxxxxxxxxxxxx" Public Sub New(ByVal request As HttpContextBase) GetDataByRequest(request) End Sub Public Sub GetDataByRequest(context As HttpContextBase) Dim config = New DefaultCloudClientConfig(api_Key) Dim manager = New CloudClientManager(config) Dim info = manager.GetDeviceInfo(context) mIsIOS = info.Capabilities("is_ios") mIsPhone = info.Capabilities("is_smartphone") mIsTablet = info.Capabilities("is_tablet") mBrandName = info.Capabilities("brand_name") mModelName = info.Capabilities("model_name") mErrors = info.Errors mResponse = info.ResponseOrigin End Sub Public ReadOnly Property IsDesktop As Boolean Get Return True End Get End Property Public ReadOnly Property IsIOS As Boolean Get Return mIsIOS End Get End Property Public ReadOnly Property IsTablet As Boolean Get Return mIsTablet End Get End Property Public ReadOnly Property IsPhone As Boolean Get Return mIsPhone End Get End Property
Although the application runs without error, I can't believe the cycling through this routine should be happening. Would like to clear it up, if possible. What am I doing wrong? Many thanks in advance!
As I see it, the issue has more to do with the internal implementation of MVC display modes than the WURFL API. The code bound to the display mode delegate is called back by ASP.NET MVC for each request to render a view, including partial views. This obviously results in multiple calls being made to the WURFL API. In addition, the WURFL Cloud API takes a while to respond because it has to make a HTTP request to the cloud, parse a cookie, and figure out details. The WURFL Cloud is clearly slower than the on-premise WURFL API which uses a direct access memory cache to pick up details of the user agent. I have used WURFL and MVC in a number of web sites and just went through this. For most of such sites I managed to get an on-premise license. As for the cloud, some per-request internal caching perhaps within your WURFLServiceModel class would be helpful so that you end up making a single cloud request for each rendering of the view. I don't particularly like the use of Session, but yes that could just be me. Session is still an acceptable way of do the "internal caching" I was suggesting above.