Frage

Ich arbeite mich durch etwas zu lesen ASP.NET MVC und ich habe einen Web-App bei der Arbeit, dass ich von WebForms zu MVC migrieren werden. Eines der Feature-Requests Ich erwarte, dass in dem Prozess zu bekommen, ist eine vereinfachte Ansicht zurückgekehrt sein, wenn der Benutzer von einem mobilen Gerät kommt.

Ich kann nicht ganz sehen, wo der beste Ort, um diese Art von Logik zu implementieren. Ich bin sicher, dass es einen besseren Weg, als das Hinzufügen eines if / else für Browser.IsMobileDevice in jeder Aktion, dass die Renditen einen Blick. Welche Art von Optionen hätte ich dies zu tun?

War es hilfreich?

Lösung

Aktualisieren : Diese Lösung einen subtilen Fehler hat. Der MVC-Framework ruft in FindView / FindPartialView zweimal: einmal mit useCache=true, und wenn das nicht einem Ergebnis zurück, einmal mit useCache=false. Da es für alle Arten von Ansichten nur ein Cache ist, mobile Benutzer Desktop-Ansichten am Ende sehen können, wenn ein Desktop-Browser zuerst ankommen sollte.

Für Interessenten an den benutzerdefinierten Ansicht Engines, dieses Problem zu lösen, hat Scott Hanselman seine Lösung hier aktualisiert:

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

(Apologies für die Antwort Hijack, ich einfach nicht, dass jemand anderes durch diese gehen zu müssen!)

Herausgegeben von roufamatic (2010-11-17)


Das erste, was Sie tun möchten, ist einzuführen, um den Mobile Device Browser Datei zu einem Projekt. Diese Datei können Sie in ohne das, was jemals Gerät Sie wollen Unterstützung gezielt mit den Besonderheiten der wissen, was diese Geräte in ihrem Header senden. Diese Datei hat bereits die Arbeit für Sie erledigt. Sie verwenden dann die Request.Browser Eigenschaft zu schneidern, die Sie zurückgeben möchten anzuzeigen.

Als nächstes kommen mit einer Strategie, wie Sie möchten, dass Ihre Ansichten unter den Ansichten Ordner organisieren. Ich ziehe es die Desktop-Version an der Wurzel zu verlassen und habe dann einen Mobile-Ordner. Zum Beispiel, wie dies die Startansicht Ordner aussehen:

  • Startseite
    • Handy
      • iPhone
        • Index.aspx
      • Blackberry
        • Index.aspx
    • Index.aspx

muss ich mit @Mehrdad nicht einig über eine benutzerdefinierte Ansicht-Engine. Die Ansicht Motor dient mehr als einen Zweck und eines dieser Zwecke ist Ansichten für den Controller zu finden. Sie tun dies die FindView Methode durch zwingende. Bei diesem Verfahren können Sie Ihre Kontrollen tun, wo die Ansicht zu finden. Nachdem Sie wissen, welches Gerät Ihre Website verwenden, können Sie die Strategie, die Sie kam verwenden, um mit Ihren Ansichten für die Organisation der Ansicht für das Gerät zurück.

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

Der obige Code können Sie die Ansicht festgelegt, basierend auf Ihrer Strategie. Der Fall zurück ist die Desktop-Ansicht, wenn keine Aussicht für das Gerät gefunden wurde, oder wenn es kein Standardmobil Ansicht.

Wenn Sie die Logik in Ihrem Controller setzen ist stattdessen eine Ansicht Motor zu schaffen. Der beste Ansatz wäre, eine eigene erstellen Action , dass Sie Ihren Controller ist mit dekorieren können. Dann überschreibt die OnActionExecuted Verfahren, um zu bestimmen welches Gerät die Anzeige Ihrer Website. Sie können prüfen, diese Blog-Post heraus, wie. Die Post hat auch ein paar netten Links zu einigen Mix Videos auf diesem Thema.

Andere Tipps

In dem Model-View-Controller-Muster, es ist der Controller, dass wählt sehen, so, es ist nicht so schlimm, eine if Aussage hinzuzufügen und eine entsprechende Ansicht zurückzukehren. Sie können die if-Anweisung in einer Methode kapseln und nennen es:

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

Alternativ können Sie eine Ansicht Engine erstellen, die dynamisch eine Ansicht auf Basis ausführt, sei es mobil oder nicht. Ich bin kein Fan von diesem Ansatz, da ich die Steuerung glaube verantwortlich sein sollte. Zum Beispiel, wenn Sie auf dem iPhone surfen, können Sie die vollständige Desktop-Version stattdessen sehen wollen. Im ersteren Ansatz, würden Sie die entsprechende Boolesche Flag, aber in der zweiten passieren, Dinge komplizierter geworden.

ich denke, dass das der richtige Ort, um diese Funktionalität zu stecken benutzerdefinierte Viewengine ist. Aber Sie sollten sich bewusst sein, wie IViewEngine.FindView Verfahren durch die ViewEngineCollection genannt wird (Weitere auf diese hier ).

Lösung vorgeschlagen von Scott Hanselman funktioniert nicht richtig. Sie können meine Probe Umsetzung dieses Ansatzes hier finden. Überprüfen Sie Readme-Datei, die beschreibt, wie Sie eine falsche Verhalten wiederholen kann.

Ich schlage vor, einen anderen Ansatz, dass überprüft, ob eine Ansicht nicht von Original Viewengine gefunden wurde und wenn useCache Parameter ist true, es prüft, ob Ansicht exist in Original Viewengine mit dem Parameter useCache=false.

Es ist zu komplex, den gesamten Code hier zu setzen, aber Sie können den vorgeschlagenen Ansatz in meiner Open-Source implementiert finden Spielplatz hier . Überprüfen MobileViewEngine Klasse und Komponententests.

Einige MobileViewEngine Funktionen:

  • Arbeiten korrekt mit Blick Caching und Verwendungen Original-Ansicht-Engine-Cache.
  • Unterstützt:. Shot Blick Namen und relative Ansicht Pfade (~ / Ansichten / Index), die von MvcContrib T4-Vorlage
  • Resolves "Index" Ansicht wie folgt:
    • Mobile/Platform/Index -. Wenn Ansicht vorhanden ist, und ein mobiles Gerät Plattform (iPhone, Android etc.) wird in den unterstützten Liste eingetragen
    • Mobile/Index - Ansicht für alle anderen mobilen Geräten. Wenn die Ansicht nicht der Fall ist vorhanden Sie optional auf Desktop-Version anzeigen Rückfall können.
    • Index - für Desktop-Version anzeigen.
  • Sie können mobile Ansicht Hierarchie anpassen (z Mobile/ Platform/Manufacturer) oder mobile Auflösung Ansicht Pfad durch das Hinzufügen / Ändern von Geräteregeln (siehe MobileDeviceRule und PlatformSpecificRule).

Hoffnung, dies wird dazu beitragen,

Dies ist eine Version, die tatsächlich funktioniert, beide mit T4MVC und im Release-Modus (in dem Caching von Ansichten aktiviert ist). Es braucht Pflege von Benutzersteuerelementen und absoluten / relativen Urls auch. Es erfordert die Mobile Device Browser Datei .

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

Ihre Kernlogik sollte gleich in den Controllern sein und nur die Ansicht benötigen Sie wird sich ändern, so dass die Steuerung, wo der Sie die if / else-Anweisung brauchen die richtige Ansicht für jeden Controller-Aktion zu dienen, wie Sie angegeben.

Eine Alternative wäre, Sie in einem separaten DLL-Controller-Logik wickeln und haben dann verschiedene Controller / Pfade für die mobile Version. Wenn ein regelmäßiger Controller eine Anfrage von einem mobilen Gerät empfängt können Sie diese auf Ihren Mobilbereich umleiten, die alle Ihre mobilen Controller enthalten, die die gemeinsame Controller-Logik verwenden. Diese Lösung würde auch erlauben, zu tun ‚tweeks‘, die speziell für den mobilen Controller sind und es nicht Ihre regelmäßigen Controller auswirken.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top