Umzug ASP.NET-WebForms-Elemente in MVC weiterverwenden

Slides:



Advertisements
Ähnliche Präsentationen
Dynamische WEB-Applikationen
Advertisements

Objektorientierte Programmierung
Kurt Rosenberg. C# für.NET oder.NET für C# is(C# == C++ && Java)? true : false ; reines C# Ausblick Überblick.
1. 2 Microsoft.NET Überblick Dirk Primbs Technologieberater Developer Platform & Strategy Group Microsoft Deutschland GmbH.
Zusammenfassung des Kapitels 8
Kurze Einführung in ASP
Design by Contract with JML - Teil 2
Dipl. Inf. (FH) Paul Mizel Compilerbau.NET Compiler / Codegeneratoren / Skriptsprachen.
Binäre Bäume Richard Göbel.
Java: Dynamische Datentypen
Listen Richard Göbel.
FH-Hof Servlets Richard Göbel. FH-Hof Konzept Servlets werden auf der Server-Seite durch ein Formular aufgerufen werten die Eingaben aus einem Formular.
ATHOS Benutzertreffen 2007
AUFGABE 1: Ein Wagen (dargestellt durch ein Rechteck) soll sich von links nach rechts bewegen. Tipp: Timer benutzen AUFGABE 2: Zusätzlich zu Aufgabe.
Vorlesung Informatik 2 Algorithmen und Datenstrukturen (05 – Elementare Datenstrukturen) Prof. Th. Ottmann.
Informatik II, SS 2008 Algorithmen und Datenstrukturen Vorlesung 6 Prof. Dr. Thomas Ottmann Algorithmen & Datenstrukturen, Institut für Informatik Fakultät.
Praxisbeispiel Cocoa Universität zu Köln Historisch-Kulturwissenschaftliche Informationsverarbeitung Re-usable Content in 3D und Simulationssystemen Prof.
Benötigte Applets Startseite: in HTML-Format Applet auf der Startseite Das Applet, das auf der Startseite geladen wird, wird die vier Buttons und die eine.
Dynamische Webseiten Java servlets.
3.1.4 Leser/Schreiber-Ausschluß (reader/writer exclusion)
Objektorientierte Programmierung JDK-Klassenbibliothek
PRJ 2007/1 Stefan Dissmann Motivation Problem: gleiche Datenstrukturen werden für verschiedene Objekte gebraucht: z.B. Listen von Studierenden, Kunden,
Programmiermethodik SS2007 © 2007 Albert Zündorf, University of Kassel 1 GUI Konstruktion: 1. Entwurf mit Papier und Bleistift / Post Ist 2. Eventuell.
Overwiew COM.
F açade P attern By Nicolas Lanquetin. Façade Pattern Structural Pattern Bietet ein gemeinsames Interface, anstatt vieler Interfaces eines Subsystems.
Modulare Programmierung
© 2002 Dr. Cavelius - Ley - Pohlig - Taulien Step by step zum JFrame 1 Zum JFrame Step by step by step by step by step by step by step by step by.
FH-Hof Singleton Pattern Richard Göbel. FH-Hof Motivation Bestimmte Klassen sollen nur ein Objekt haben Nur ein Fabrikobjekt für eine Fabrikklasse Zentraler.
Einfach verkettete Listen
Einfach verkettete Listen (OOP)
Advanced Debugging F9 ist nicht genug Ingo Rammer
1 Softwareentwicklung mit.NET Teil 3 ASP.NET Web Forms Dr. Ralph Zeller.
Servlet III Java Webanwendung Webcontainer Web.xml
Fesselspiele Data Binding in WPF und Silverlight
Medien zwischen Technologie und Gesellschaft Dozent: Herr Prof. Dr. Manfred Thaller SS 13 Referent: Christian Braun.
Automated Software Testing
Martin LöfflerMurat Yilmaz Labor Informationstechnologie.
Abteilung für Telekooperation Übung Softwareentwicklung 1 für Wirtschaftsinformatik Dr. Wieland Schwinger
BAS5SE | Fachhochschule Hagenberg | Daniel Khan | S SPR5 MVC Plugin Development SPR6P.
Mahmoud Zoabi Khaled Isa
Advanced Mapping Persistente Domänenmodelle mit JPA 2.0 und Bean Validation.
RateMe Slides. Ablauf Präsentation des Konzepts (5-10 min) Demonstration der laufenden Software (5-10 min) Fazit der gesammelten Erkenntnisse.
RateMe Slides. Ablauf Präsentation des Konzepts (5-10 min) Demonstration der laufenden Software (5-10 min) Fazit der gesammelten Erkenntnisse.
Developer Day Webseiten auf Windows Azure hosten Britta Labud bbv Software Services AG Roland Krummenacher bbv Software Services AG.
Windows Azure Websites Roland Krummenacher Senior Software Engineer, bbv Software Services
| Basel Developing apps for SharePoint 2013 using Visual Studio 2013 René Modery, Office 365 MVP, 1stQuad Solutions.
3/28/2017 8:11 PM Visual Studio Tools für Office { Rapid Application Development für Office } Jens Häupel Platform Strategy Manager Microsoft Deutschland.
MVVM in Windows 8 und Windows Phone 8
PresenterCompanyContact Windows Azure ASP.NET Web-Anwendungen schnell und zuverlässig bereitstellen.
Entwicklung verteilter Anwendungen I, WS 13/14 Prof. Dr. Herrad Schmidt WS 13/14 Kapitel 1 Folie 2 Microsoft.NET Framework: Quelle:
Entwicklung verteilter Anwendungen II, SS 13 Prof. Dr. Herrad Schmidt SS 13 Kapitel 2 Folie 2 ASP.NET HTTP-Handler (1)
Entwicklung verteilter Anwendungen I, WS 13/14 Prof. Dr. Herrad Schmidt WS 13/14 Kapitel 9 Folie 2 ASP.NET Seitenübergänge
JSP Einführung Skripte Direktiven Tomcat 3.2 Version 1.1
XML IV: Cocoon 2.
Equals, Hashcode und CompareTo Micha Kessler
Making people work together! Folie 1 NEXPLORE AG Stefan von Niederhäusern Einfache Anwendung der SuisseID durch das Software Development KIT
© All rights reserved. Zend Technologies, Inc. Jenseits von var_dump(): Debugging in ZF Jan Burkl System Engineer.
Einfach und doppelt verkettete Listen in JAVA by Jens Weibler
CuP - Java Zwölfte Vorlesung Klassen – Komposition und Vererbung Freitag, 15. November 2002.
Thomas Claudius Huber Senior Consultant Trivadis AG WCF RIA Services Datengetriebene Apps.
RateMe Slides. Ablauf Präsentation des Konzepts (5-10 min) Demonstration der laufenden Software (5-10 min) Fazit der gesammelten Erkenntnisse.
Lind 02/2005 Einführung in JAVA. Lind 02/2005 Beispiel: Mittelwert Es soll ein Programm erstellt werden, das den Mittelwert zweier reeller Zahlen berechnet.
ASP.NET MVC Stefan Lieser Web:
Programmiervorkurs WS 2014/15 Methoden
Die AppDomain Das unbekannte Wesen?
Generative Softwareentwicklung in der Praxis Olaf Kaus, „Java User Group“, Hannover 6.Oktober 2003.
Kay Herzam IT Consulting GmbH Webentwicklung mit ASP.NET 4, Ajax und jQuery.
Web und Mobile Apps Programmieren Marco Jakob Kurzvortrag OSS an Schulen
1.Event Queue.
Azure Mobile Services Deep dive into node.js scripting
 Präsentation transkript:

Umzug ASP.NET-WebForms-Elemente in MVC weiterverwenden Dr. Malte Clasen adesso AG Über Jahre entwickelte ASP.NET WebForms-Anwendungen enthalten oft komplexe Controls und Pages. Das stellt für eine Migration auf ASP.NET eine Hürde dar, weil die dahinter liegende Eingabe- und Darstellungslogik oft nicht ausreichend spezifiziert und dokumentiert ist. Aber auch in Fällen mit guter Spezifikation ist der damit verbundene Implementierungsaufwand nicht zu unterschätzen. In diesem Vortrag wird an einem Beispiel aus der Praxis gezeigt, wie man bestehende WebForms-Controls und -Pages in MVC-Anwendungen und -Layouts integriert und so innerhalb des neuen Frameworks nutzen kann.

Über uns Malte Clasen Softwareentwickler http://malteclasen.de adesso AG IT-Dienstleister http://adesso.de

Rezeptefuchs.de

Rezeptefuchs.de

Gegeben: WebForms-Anwendung Controls (Code) Controls (ASCX) Pages (ASPX)

Lifecycle WebForms / MVC Model Controller erzeugt View rendert Init PreInit InitComplete Load [Control Events] LoadComplete PreRender PreRenderComplete Done SaveStateComplete Render Unload ASP.NET Page Life Cycle Overview: http://msdn.microsoft.com/en-us/library/ms178472.aspx

WebForms in MVC einbetten Lifecycle von WebForms und MVC praktisch nicht vereinbar Komplexität in WebForms-Anwendungen in Controls gebündelt Controls in MVC einbetten sinnvoll für Elemente, die für sich stehen können ungeeignet bei Interaktion mit dem Rest der Seite

Ansatz Eingabe: HttpRequest Ausgabe: HttpResponse WebForms-Aufruf simulieren HttpRequest direkt übergeben, wird nicht verändert HttpResponse neu erstellen und die erzeugte Ausgabe in die MVC-Ausgabe integrieren

Vereinfachungen nur ein Control pro HTML-Seite sonst gesonderte Behandlung des form-Tags notwendig nur Controls, keine Pages Pages entweder in den folgenden Code einflechten, oder Pages in ASCX-Controls umwandeln nur Form, kein Head kann analog aus dem HTML-Code übertragen werden

Quellcode https://github.com/malteclasen/MvcMigration.git

Controller private Control CreateItem(Page page); public virtual ActionResult Index() { var item = WebFormsHelper.RenderLegacyItem( CreateItem, HttpContext, PageUrl); ViewBag.ControlHtml = item.ControlHtml; return View("LegacyItem"); } Controller.Index()

Code-Control private Control CreateItem(Page page) { return new WebForms.MyControl(); } CreateItem() Controller.Index()

ASCX-Control ascx als Embedded Resource private Control CreateItem(Page page) { return page.LoadControl( "~/bin/WebForms.dll/" + "WebForms.MyWebUserControl.ascx"); } http://www.cmswire.com/cms/tips-tricks/aspnet-reusing-web-user-controls-and-forms-000915.php http://support.microsoft.com/kb/910441/en-us?spid=8940&sid=global CreateItem() Controller.Index()

Global.asax protected void Application_Start() { … HostingEnvironment. RegisterVirtualPathProvider( new EmbeddedResourcePathProvider()); } Application_Start()

Controller public virtual ActionResult Index() { var item = WebFormsHelper.RenderLegacyItem( CreateItem, HttpContext, PageUrl); ViewBag.ControlHtml = item.ControlHtml; return View("LegacyItem"); } Controller.Index()

WebFormsHelper.RenderLegacyItem() public static ItemContent RenderLegacyItem( Func<Page, Control> contentCreator) { var page = CreatePage(); var content = contentCreator(page); page.AddControl(content); var writer = new StringWriter(); var response = ProcessRequest(page, writer); … WFH.RenderLegacyItem() Controller.Index()

WebFormsHelper.RenderLegacyItem() … TransferCookies(response, HttpContext.Current.Response); var form = GetForm( Clean(stringWriter.ToString())); return new ItemContent { ControlHtml = form, }; } WFH.RenderLegacyItem() Controller.Index()

WebFormsHelper.CreatePage() private static ContainerPage CreatePage() { var page = new ContainerPage { RenderingCompatibility=new Version(3, 5), ClientIDMode=ClientIDMode.AutoID, }; var scriptManager = new ScriptManager { … } AddDefaultScripts(scriptManager); page.AddControl(scriptManager); page.AddHead(new ContentPlaceHolder { ID = "HeadContent"}); return page; } WFH.CreatePage() WFH.RenderLegacyItem() Controller.Index()

ContainerPage private class ContainerPage : Page { private HtmlForm _form = new HtmlForm(); private HtmlHead _head = new HtmlHead(); protected override void OnInit(EventArgs e) … public void AddHead(Control control) … public void AddControl(Control control) … private HttpSessionState _session; public override HttpSessionState Session … } WFH.CreatePage() WFH.RenderLegacyItem() Controller.Index()

ContainerPage.OnInit() protected override void OnInit(EventArgs e) { base.OnInit(e); var html = new HtmlGenericControl("html"); Controls.Add(html); html.Controls.Add(_head); var body = new HtmlGenericControl("body"); html.Controls.Add(body); _form.Enctype = "multipart/form-data"; body.Controls.Add(_form); } CP.OnInit() WFH.CreatePage() WFH.RenderLegacyItem() Controller.Index()

WebFormsHelper.CreatePage() private static ContainerPage CreatePage() { var page = new ContainerPage { RenderingCompatibility=new Version(3, 5), ClientIDMode=ClientIDMode.AutoID, }; var scriptManager = new ScriptManager { … } AddDefaultScripts(scriptManager); page.AddControl(scriptManager); page.AddHead(new ContentPlaceHolder { ID = "HeadContent"}); return page; } WFH.CreatePage() WFH.RenderLegacyItem() Controller.Index()

WebFormsHelper.AddDefaultScripts() private static void AddDefaultScripts( ScriptManager scriptManager) { scriptManager.Scripts.Add(new ScriptReference {Name = "MsAjaxBundle"}); scriptManager.Scripts.Add(new ScriptReference {Name = "WebForms.js", Assembly = "System.Web", Path = "~/Scripts/WebForms/WebForms.js" }); … } WFH.AddDefaultScripts() WFH.CreatePage() WFH.RenderLegacyItem() Controller.Index()

App_Start\BundleConfig public class BundleConfig { public static void RegisterBundles( BundleCollection bundles) bundles.Add( new ScriptBundle("~/bundles/MsAjaxJs") .Include( "~/Scripts/WebForms/MsAjax/MicrosoftAjax.js", … )); } BC.RegisterBundles()

WebFormsHelper.RenderLegacyItem() public static ItemContent RenderLegacyItem( Func<Page, Control> contentCreator) { var page = CreatePage(); var content = contentCreator(page); page.AddControl(content); var writer = new StringWriter(); var response = ProcessRequest(page, writer); … WFH.RenderLegacyItem() Controller.Index()

WebFormsHelper.ProcessRequest() private static HttpResponse ProcessRequest( IHttpHandler page, TextWriter writer) { var response = new HttpResponse(writer); var context = new HttpContext( HttpContext.Current.Request, response); context.SetSessionStateBehavior( SessionStateBehavior.Required); page.ProcessRequest(context); return response; } WFH.ProcessRequest() WFH.RenderLegacyItem() Controller.Index()

ContainerPage.Session public override HttpSessionState Session { get return _session ?? (_session = GetMockHttpSessionState()); } CP.Session WFH.ProcessRequest() WFH.RenderLegacyItem() Controller.Index()

ContainerPage.GetMockHttpSessionState private static HttpSessionState GetMockHttpSessionState() { var staticObjects = new HttpStaticObjectsCollection(); var itemCollection = new SessionStateItemCollection(); IHttpSessionState sessionStateContainer = new HttpSessionStateContainer(…); … CP.GetMockHttpSessionState() CP.Session WFH.ProcessRequest() WFH.RenderLegacyItem() Controller.Index()

ContainerPage.GetMockHttpSessionState var state = (HttpSessionState) Activator.CreateInstance( typeof(HttpSessionState), BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.CreateInstance, null, new object[] { sessionStateContainer }, CultureInfo.CurrentCulture); return state; } CP.GetMockHttpSessionState() CP.Session WFH.ProcessRequest() WFH.RenderLegacyItem() Controller.Index()

WebFormsHelper.RenderLegacyItem() … TransferCookies(response, HttpContext.Current.Response); var form = GetForm( Clean(stringWriter.ToString())); return new ItemContent { ControlHtml = form, }; } WFH.RenderLegacyItem() Controller.Index()

WebFormsHelper.TransferCookies() private static void TransferCookies( HttpResponse source, HttpResponse target) { foreach (var cookie in source.Cookies.Cast<string>() .Select(key => source.Cookies[key]) .Where(cookie => cookie != null)) target.Cookies.Add(cookie); } WFH.TransferCookies() WFH.RenderLegacyItem() Controller.Index()

WebFormsHelper.RenderLegacyItem() … TransferCookies(response, HttpContext.Current.Response); var form = GetForm( Clean(stringWriter.ToString())); return new ItemContent { ControlHtml = form, }; } WFH.RenderLegacyItem() Controller.Index()

WebFormsHelper.Clean() private static string Clean(string source) { return source.Replace( " ", " "); } WFH.Clean() WFH.RenderLegacyItem() Controller.Index()

WebFormsHelper.RenderLegacyItem() … TransferCookies(response, HttpContext.Current.Response); var form = GetForm( Clean(stringWriter.ToString())); return new ItemContent { ControlHtml = form, }; } WFH.RenderLegacyItem() Controller.Index()

WebFormsHelper.GetForm() private static string GetForm(string rendered) { const string formStartTag = "<form"; const string formEndTag = "</form>"; var formStart = rendered.IndexOf(formStartTag); var formEnd = rendered.LastIndexOf(formEndTag); var form = rendered.Substring(formStart, formEnd-formStart+formEndTag.Length); return form; } WFH.GetForm() WFH.RenderLegacyItem() Controller.Index()

Controller public virtual ActionResult Index() { var item = WebFormsHelper.RenderLegacyItem( CreateItem, HttpContext, PageUrl); ViewBag.ControlHtml = item.ControlHtml; return View("LegacyItem"); } Controller.Index()

View @Html.Raw(ViewBag.ControlHtml)

Zusammenfassung Control laden, ASCX aus Embedded Resource HttpContext und Page erzeugen Page.ProcessRequest aufrufen Cookies transferieren HTML-Code an View übergeben Quellcode auf https://github.com/malteclasen/MvcMigration.git

Dr. Malte Clasen adesso AG Vielen Dank! Dr. Malte Clasen adesso AG

Firma mein Blog: http://malteclasen.de/blog mein Arbeitgeber: http://adesso.de Stellenangebote: http://www.aaajobs.de/