pages net mvc microsoft form for aspnet asp asp.net-mvc views mobile-devices

asp.net-mvc - mvc - razor pages net core



¿Cómo cambiaría las vistas MVC de ASP.NET según el tipo de dispositivo? (5)

Estoy trabajando en la lectura de ASP.NET MVC y tengo una aplicación web en el trabajo que migraré de WebForms a MVC. Una de las solicitudes de funciones que espero obtener en el proceso es que me devuelvan una vista simplificada si el usuario proviene de un dispositivo móvil.

No puedo ver dónde está el mejor lugar para implementar ese tipo de lógica. Estoy seguro de que hay una mejor manera de agregar un if / else para Browser.IsMobileDevice en cada acción que devuelve una vista. ¿Qué tipo de opciones tendría para hacer esto?


Creo que el lugar correcto para conectar esta funcionalidad es ViewEngine personalizado. Pero debe tener en cuenta cómo IViewEngine.FindView método ViewEngineCollection (más información sobre esto here ).

http://www.hanselman.com/blog/ABetterASPNETMVCMobileDeviceCapabilitiesViewEngine.aspx actualizada sugerida por Scott Hanselman no funciona correctamente. Puede encontrar mi ejemplo de implementación de este enfoque here . Verifique el archivo readme que describe cómo puede repetir el comportamiento incorrecto.

Sugiero otro enfoque que verifique si ViewEngine original no encontró una vista y si el parámetro useCache es true , verifica si la vista existe en ViewEngine original con el parámetro useCache=false .

Es demasiado complejo para poner todo el código aquí, pero puede encontrar el enfoque sugerido implementado en mi área de juegos de código abierto here . Verifique la clase y las pruebas unitarias de MobileViewEngine .

Algunas características de MobileViewEngine:

  • Funciona correctamente con el almacenamiento en caché de la vista y utiliza la memoria caché del motor de la vista original.
  • Admite ambos: nombres de vista de toma y rutas de vista relativas (~ / Vistas / Índice) utilizadas por la plantilla MvcContrib T4.
  • Resuelve la vista del "Índice" de la siguiente manera:
    • Mobile/Platform/Index : si existe una vista y una plataforma de dispositivo móvil (iPhone, Android, etc.) está inscrita en la lista compatible.
    • Mobile/Index - ver para todos los demás dispositivos móviles. Si la vista no existe, puede retroceder opcionalmente a la versión de vista de escritorio.
    • Index - para la versión de vista de escritorio.
  • Puede personalizar la jerarquía de la vista móvil (por ejemplo, Mobile/ Platform/Manufacturer ) o personalizar la resolución de la ruta de la vista móvil agregando / cambiando las reglas del dispositivo (consulte MobileDeviceRule y PlatformSpecificRule ).

Esperanza, esto ayudará


En el patrón Modelo-Vista-Controlador, es el controlador el que elige la vista, por lo tanto, no es tan malo agregar una sentencia if y devolver una vista apropiada. Puede encapsular la instrucción if en un método y llamarla:

return AdaptedView(Browser.IsMobileDevice, "MyView.aspx", model);

Alternativamente, puede crear un motor de vista que ejecute dinámicamente una vista basada en si es móvil o no. No soy un fanático de este enfoque ya que creo que el controlador debería estar a cargo. Por ejemplo, si está navegando en un iPhone, es posible que desee ver la versión completa del escritorio. En el primer enfoque, pasaría la bandera booleana apropiada, pero en el segundo, las cosas se complican.


Esta es una versión que realmente funciona, tanto con T4MVC como en modo de lanzamiento (donde está habilitado el almacenamiento en caché de las vistas). También se ocupa de los controles de usuario y de las direcciones URL absolutas / relativas. Requiere el archivo del navegador del dispositivo móvil .

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; } }


Su lógica central debe ser la misma en los controladores y solo la vista que necesita cambiará, por lo que es donde necesita la instrucción if / else para proporcionar la vista correcta para cada acción del controlador, según lo establecido.

Una alternativa sería envolver la lógica del controlador en una dll separada y luego tener diferentes controladores / rutas para la versión móvil. Si un controlador normal recibe una solicitud de un dispositivo móvil, puede redirigirlos a su área móvil que contiene todos sus controladores móviles que usan la lógica del controlador compartido. Esta solución también le permitiría hacer "tweeks" que son específicos de los controladores móviles y no tener un impacto en sus controladores normales.


Actualización : Esta solución tiene un error sutil. El marco MVC llamará a FindView / FindPartialView dos veces: una vez con useCache=true , y si eso no devuelve un resultado, una vez con useCache=false . Dado que solo hay un caché para todos los tipos de vistas, los usuarios de dispositivos móviles pueden terminar viendo las vistas de escritorio si primero llega un navegador de escritorio.

Para aquellos interesados ​​en usar motores de visualización personalizados para resolver este problema, Scott Hanselman ha actualizado su solución aquí:

http://www.hanselman.com/blog/ABetterASPNETMVCMobileDeviceCapabilitiesViewEngine.aspx

(Disculpas por el secuestro de la respuesta, ¡no quiero que nadie más tenga que pasar por esto!)

Editado por roufamatic (2010-11-17)

Lo primero que desea hacer es introducir el archivo del navegador de dispositivos móviles en su proyecto. Al usar este archivo, puede apuntar a cualquier dispositivo que quiera admitir sin tener que conocer los detalles específicos de lo que esos dispositivos envían en sus encabezados. Este archivo ya ha hecho el trabajo por usted. A continuación, utiliza la propiedad Request.Browser para personalizar la vista que desea devolver.

A continuación, desarrolle una estrategia sobre cómo desea organizar sus vistas en la carpeta Vistas. Prefiero dejar la versión de escritorio en la raíz y luego tener una carpeta móvil. Por ejemplo, la carpeta de la vista Inicio se vería así:

  • Casa
    • Móvil
      • iPhone
        • Index.aspx
      • Mora
        • Index.aspx
    • Index.aspx

Tengo que estar en desacuerdo con @Mehrdad sobre el uso de un motor de visualización personalizado. El motor de vista tiene más de un propósito y uno de esos propósitos es encontrar vistas para el controlador. Para ello, anula el método FindView. En este método, puede hacer sus comprobaciones sobre dónde encontrar la vista. Una vez que sepa qué dispositivo está usando su sitio, puede usar la estrategia que ideó para organizar sus vistas y devolver la vista para ese dispositivo.

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; } }

El código anterior le permite configurar la vista según su estrategia. La caída es la vista de escritorio, si no se encontró ninguna vista para el dispositivo o si no hay una vista móvil predeterminada.

Si decide poner la lógica en su controlador en lugar de crear un motor de visualización. El mejor enfoque sería crear un ActionFilterAttribute personalizado ActionFilterAttribute que puedas decorar tu controlador. Luego anule el método OnActionExecuted para determinar qué dispositivo está viendo su sitio. Puedes consultar esta publicación del blog sobre cómo hacerlo. La publicación también tiene algunos enlaces agradables a algunos videos Mix sobre este tema.