Skip to main content

MVC 3 - Custom view load based on the source of the request

Pornim de la următoarea problema:
Se da o aplicație ASP MVC 3. Se dorește sa încarce view-uri custom pentru fiecare tip de device care o accesează. De exemplu în cazul în care request-ul vine de la un iPhone sau un Windows Phone 7 atunci view-urile care se încarcă o sa fie diferite.
MVC suporta deja crearea unei versiuni de view pentru mobile device, dar acest lucru nu o sa ne fie de ajuns. In funcție de rezoluție sau de brower o sa dorim sa încărcam view-uri total diferite. Informațiile despre ce tip de device accesează resursa le putem găsii in user-agent.
Proprietatea user agent-ul se poate găsii în următoarea locație
HttpContext.Request.UserAgent
Aceasta valoare o sa fie de tip string, unde este necesar sa cautam manual valoarea pe noi o cautam. Pentru IPhone user agent-ul o sa aibe valoarea:
Mozilla/5.0 (iPhone; U; CPU like Mac OS X; en) AppleWebKit/420+ (KHTML, like Gecko) Version/3.0 Mobile/1A543a Safari/419.3
Iar un request de la un Windows Phone 7 o sa aibe următoarea valoare:
Mozilla/4.0 (compatible; MSIE 7.0; Windows Phone OS 7.0; Trident/3.1; IEMobile/7.0) Asus;Galaxy6
Sa presupunem ca o sa avem următoarea structura de fișiere sub directorul Views
Views
Home // Nume control
Index.cshtml
IPhone
Index.cshtml
WF7
Index.cshtml
Pentru a definii maparea la views-uri astfel încît sa fie rezolvate cu view-ul dorit este nevoie sa implementam interfața IViewEngine și sa ne definim un ViewEngine custom. In cadrul acestui ViewEngine pe metodele FindPartialView si FindView o sa fie nevoie sa verificam dacă user agent-ul este de la un anumit agent. In cazul în care request-ul vine de la un anumit device custom atunci este nevoie sa transmitem path-ul unde se găsește view-ul respectiv.
Altfel ajunge sa returnam o instanta noua a ViewEngineResult. Deoarece aceasta nu o sa conțină nici un view găsit, căutarea se va face in continuare în alt ViewEngine din colecție.
public class ApplePhoneViewEngine : IViewEngine
{
...
public ViewEngineResult FindPartialView(ControllerContext context, string viewName, bool useCache)
{
return context.HttpContext.Request.UserAgent.StartWith("iPhone)
? BaseViewEngine.FindPartialView(context, "IPhone/" + viewName, false)
: new ViewEngineResult(new string[] { });
}
...
}
Ne-a mai rămas sa înregistram view engine-ul pe care noi l-am definit mai sus. In Application_Start din Global.asax.cs este nevoie sa adaugăm următorul cod:
ViewEngines.Engines.Add(new ApplePhoneViewEngine());
Codul se poate refactoriza destul de frumos, dar va las pe voi sa faceți acest lucru. Daca doriți sa aflați mai multe informații puteți sa aruncați o privire aici: https://raw.github.com/gist/1077436/a35a62ce4be85ab439dacf44205792ca9ff2791d/customviewengine.cs

Comments

  1. MVC 4 are asa ceva... si e developer preview

    ReplyDelete
  2. Am vazut, dar pana atunci ne descurcam cu ce avem, sunt multumit si cu MVC 3.

    ReplyDelete

Post a Comment

Popular posts from this blog

Windows Docker Containers can make WIN32 API calls, use COM and ASP.NET WebForms

After the last post , I received two interesting questions related to Docker and Windows. People were interested if we do Win32 API calls from a Docker container and if there is support for COM. WIN32 Support To test calls to WIN32 API, let’s try to populate SYSTEM_INFO class. [StructLayout(LayoutKind.Sequential)] public struct SYSTEM_INFO { public uint dwOemId; public uint dwPageSize; public uint lpMinimumApplicationAddress; public uint lpMaximumApplicationAddress; public uint dwActiveProcessorMask; public uint dwNumberOfProcessors; public uint dwProcessorType; public uint dwAllocationGranularity; public uint dwProcessorLevel; public uint dwProcessorRevision; } ... [DllImport("kernel32")] static extern void GetSystemInfo(ref SYSTEM_INFO pSI); ... SYSTEM_INFO pSI = new SYSTEM_INFO(

ADO.NET provider with invariant name 'System.Data.SqlClient' could not be loaded

Today blog post will be started with the following error when running DB tests on the CI machine: threw exception: System.InvalidOperationException: The Entity Framework provider type 'System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer' registered in the application config file for the ADO.NET provider with invariant name 'System.Data.SqlClient' could not be loaded. Make sure that the assembly-qualified name is used and that the assembly is available to the running application. See http://go.microsoft.com/fwlink/?LinkId=260882 for more information. at System.Data.Entity.Infrastructure.DependencyResolution.ProviderServicesFactory.GetInstance(String providerTypeName, String providerInvariantName) This error happened only on the Continuous Integration machine. On the devs machines, everything has fine. The classic problem – on my machine it’s working. The CI has the following configuration: TeamCity .NET 4.51 EF 6.0.2 VS2013 It see

Navigating Cloud Strategy after Azure Central US Region Outage

 Looking back, July 19, 2024, was challenging for customers using Microsoft Azure or Windows machines. Two major outages affected customers using CrowdStrike Falcon or Microsoft Azure computation resources in the Central US. These two outages affected many people and put many businesses on pause for a few hours or even days. The overlap of these two issues was a nightmare for travellers. In addition to blue screens in the airport terminals, they could not get additional information from the airport website, airline personnel, or the support line because they were affected by the outage in the Central US region or the CrowdStrike outage.   But what happened in reality? A faulty CrowdStrike update affected Windows computers globally, from airports and healthcare to small businesses, affecting over 8.5m computers. Even if the Falson Sensor software defect was identified and a fix deployed shortly after, the recovery took longer. In parallel with CrowdStrike, Microsoft provided a too