MVC med Javascript och Ajax. Filip Ekberg

Relevanta dokument
MVC med Javascript och Ajax. Filip Ekberg

MVC med Javascript och Ajax. Filip Ekberg

MVC med Javascript och Ajax. Filip Ekberg

ASP.NET MVC. Copyright Mahmud Al Hakim Innehåll

Asp.net mvc intro PER KVARNBRINK,

Det här dokumentet är till för att ge en översikt över ASP.NET MVC samt hur WCF Services används från.net applikationer.

Översikt. Installation av EasyPHP 1. Ladda ner från Jag använder Release Installera EasyPHP.

Lab 6: ASP.NET 2.0 Providermodellen

Övning MS SQL och MVC del 2

Övning: Arbeta med Azure Explorer

DB, DATA, LOGIC, EXPOSURE (WEB)

Innehåll. Dokumentet gäller från och med version

DIAGNOSTISKT PROV. Tid. Hjälpmedel. Antaganden. Rättning. Övrigt. Diagnostiskt Prov. Klockan Inga

Objektorienterad Programmering (OOP) Murach s: kap 12-16

Klient/server. Översikt. Lektion 1: Webbtekniker från Microsoft. Webbteknik från Microsoft. Klient/server. Designmönster. Utrullning.

Klientprogrammering mot databaser

Säkerhet. Säkerhet. Johan Leitet twitter.com/leitet facebook.com/leitet. Webbteknik II, 1DV449

ASP.NET Thomas Mejtoft

Räkna med ASP.NET MVC 3

Viva la evolución. Peter Backlund

Arbeta med databas. Översikt. Lektion 1: Arbeta med Entity Data Models. Arbeta med Entity Data Models. LINQ (Language Integrated Query).

FactoryCast HMI. Premium & Quantum PLC. MySQL Server och FactoryCast HMI databastjänst

En integration av betalningssystem på hemsida

Övning Arbeta med klasser

Henrik Häggbom Examensarbete Nackademin Våren 2015

För att öppna galleriet, ange adressen

Övning 1: Skapa virtuell maskin för utveckling.

Objektsamlingar i Java

Testramverk och Model based testing med java i praktiken

Mutability och State. Objekt-orienterad programmering och design (DIT953) Niklas Broberg / Johannes Åman Pohjola, 2018

Överföring av filer med Zendto v 1.1. stora filer som inte kan skickas via e-post konfidentiella uppgifter som inte kan skickas via okrypterad e-post

Administrationsmanual ImageBank 2

E12 "Evil is going on"

Grupp Policys. Elektronikcentrum i Svängsta Utbildning AB

// GET: Test1/Index2 // Syftet är att se hur olika url:er leder till olika actions

1ME323 Webbteknik 3 Lektion 6 API. Rune Körnefors. Medieteknik Rune Körnefors

Lösenordsportalen Hosted by UNIT4 For instructions in English, see further down in this document

Alternativet är iwindows registret som ni hittar under regedit och Windows XP 32 bit.

Presentation Edument AB. All Rights Reserved.

Uppstart Agda PS Hosting

Att skriva till och läsa från terminalfönstret

Inkapsling tumregler. Åtkomstmodifikatorer, instantiering, referenser, identitet och ekvivalens, samt klassvariabler. public och private

F4. programmeringsteknik och Matlab

Classes och Interfaces, Objects och References, Initialization

Objektorienterad Programkonstruktion. Föreläsning 7 24 nov 2015

Boss installationsmanual förberedelser

Övning Dictionary. Övning 1. Steg 1: På din virtuella maskin, starta Visual Studio.

Alla rättigheter till materialet reserverade Easec

JobOffice SQL databas på server

Lektion 1 - Programmeringsteknik F1, ht 2003

Labora&on 1 Introduk&on &ll utvecklingsmiljön övningar/uppgi<er

Innehållsförteckning ADSync Windows Azure Active Directory ADSynC- Installation Konfigurera ADSync... 4

WP-Edit. Robin Larsson Martin Davik. Examensarbete, grundnivå, 15 hp Datavetenskap Internetteknologprogrammet

JavaScript in SharePoint and not just for Apps. Wictor Wilén

JavaScript. Innehåll. Historia. Document object model DHTML. Varför Javascript?

F6 Objektorienterad design. ID1004 Objektorienterad programmering Fredrik Kilander

Lösningsförslag till tentamen

Advoco NetPBX. Konfiguration av Yealink SIP IP-telefoner

Installationsanvisningar VisiWeb. Ansvarig: Visi Closetalk AB Version: 2.3 Datum: Mottagare: Visi Web kund

Kursplanering Utveckling av webbapplikationer

Essential Php Security Författare: Shiflett, Chris Antal sidor: 124 Förlag: O'Reilly

public och private Obs: private inte skyddar mot access från andra objekt i samma klass.

Grundläggande programmering, STS 1, VT Sven Sandberg. Föreläsning 14

Administrationsmanual ImageBank 2

Webbsäkerhet för IT-tekniker VT2014 Johan Leitet Nätverkssäkerhet, 1DV425 johan.leitet.se twitter.com/leitet facebook.

Uppstart. Agda Drift

Programmering B med Visual C

Föreläsning 3: Abstrakta datastrukturer, kö, stack, lista

E11 "Protection" Föreläsning 11, HT2014 Säkerhet, tillgänglighet. Johan Leitet. Kurs: 1dv403 Webbteknik I

Polymorfi. Objektorienterad och komponentbaserad programmering

Mål med lektionen! Repetera och befästa kunskaperna.

Webmail instruktioner

KPMG Secure File Transfer Handledning

Kungliga Tekniska Högskolan Ämneskod 2D4134 Nada Tentamensdag maj - 19 Tentamen i Objektorientering och Java Skrivtid 5 h

Karlstads Universitet, Datavetenskap 1

Laboration 2: Designmönster

Alla rättigheter till materialet reserverade Easec

INLOGGNING 1 (6) Det finns två sätt att logga in i Privera: Med engångslösenord till mobiltelefon Med engångslösenord till e-post

LÖSNINGSFÖRSLAG Programmeringsteknik För Ing. - Java, 5p

Lösningar till tentamen i EDAF25

Föreläsning 3. Stack

Objektorienterad Programkonstruktion. Föreläsning 2 2 nov 2016

Uppdatera Easy Planning till SQL

Objektorienterad Programkonstruktion. Föreläsning 6 23 nov 2015

Grundkurs i programmering, 6 hp (725G61) Dugga 2 tillfälle 2

Programmering med Java. Grunderna. Programspråket Java. Programmering med Java. Källkodsexempel. Java API-exempel In- och utmatning.

TDDD78 Viktiga begrepp, del 2

OOP Objekt-orienterad programmering

Instruktion för användande av Citrix MetaFrame

Surfning. Webbklienter och webbservrar. Specialskrivna webbservrar. Kommunikation med sockets

The Last Adventure. Innehåll. Objektorientering. Språket Java. Java - Paket. Java - synlighet. Den sista lektionen. Repetition.

Allmänna anvisningar: Skriv dina svar på svarsblanketten (se nästa sida) Markera och ange alla svar tydligt och entydigt efter instruktionerna.

DAT043 Objektorienterad Programmering

Lösningsförslag till omtentamen för TDA540 Objektorienterad Programmering

Säkerhet. Föreläsning 6 Säkerhet. Johan Leitet twitter.com/leitet facebook.com/leitet. Webbteknik II, 1DV449

Innehåll. Föreläsning 3. javax.naming.context. javax.sql.datasource. Vad är JDBC? Java Naming and Directory Interface(JNDI) Viktigaste metoder:

Innehåll Security. Chapter 4 och 7 Beginning SQL Server 2008 for Developers

Arv. Objektorienterad och komponentbaserad programmering

Innehåll. dynamisk bindning. och programmering CRC) u Arv, polymorfi och

Starta en webbläsare (t ex Internet Explorer, Mozilla Firefox, Safari) Skriv in nedan adress:

Transkript:

MVC med Javascript och Ajax Filip Ekberg

Hur går det?

MVC med Javascript och Ajax Lektion 6 Inloggning, Testning & Separation of Concerns

mail@filipekberg.se

Dagens mål Introducera inloggning, testning och bra kodstruktur Hur läggere jag till inloggning? Hur testar man ASP.NET MVC kod Hur testar jag en Action, Controller och Modell Hur testar jag mitt service, business eller datalager Vad är enhetstester, automattester, UI-tester och andra typer av tester Hur skriver jag tester utan att gå mot databasen Dependency Injection & Inversion of Control Mock & Fake Repetition Hur introducerar vi EntityFramework Hur använder vi Repository Pattern Hur utyttjar vi AjaxExtensions

Inloggning med ASP.NET Identity

Hur bygger man en säker inloggning?

Varför Hasha och inte Kryptera?

Vad är 2FA?

Authentication Inloggning

Authorization Behörighet

Använder sig av OWIN Som vi pratade om i lektion 1

ASP.NET Identity är Claims-baserat

The ClaimsIdentity class is a concrete implementation of a claims-based identity; that is, an identity described by a collection of claims. A claim is a statement about an entity made by an issuer that describes a property, right, or some other quality of that entity.

Ett Claim innehåller information om användaren

name : Filip Ekberg email : mail@filipekberg.se

Claims skickas fram och tillbaka till webbservern med hjälp av cookies!

Kan man ändra på sina Claims då, i och med att Cookies är osäkert?

Din Cookie är signerad det betyder att om du ändrar på den vet servern detta!

Tänk på HTTPS!

Roles vs Claims

Stöd för OAuth, OpenId, AD, Office 365, Azure AD, med mera

ASP.NET Authentication with Identity https://channel9.msdn.com/series/customizing-aspnet-authentication-with-identity/01

Install-Package Microsoft.Owin.Host.SystemWeb Install-Package Microsoft.AspNet.Identity.OWIN Install-Package Microsoft.AspNet.Identity.EntityFramework

UserManager<IdentityUser>

public class MyIdentityDbContext : IdentityDbContext<IdentityUser> {} var context = new MyIdentityDbContext(); var store = new UserStore<IdentityUser>(context); usermanager = new UserManager<IdentityUser>(store); Hantera allt som har med användaren att göra

Hur registrerar jag en användare?

var user = new IdentityUser { UserName = username, Email = email }; var result = await usermanager.createasync(user, password); if (result.succeeded) { } Skapa användaren med ett anviget lösenord Vi vill verifiera att det gick att skapa användaren Vi kanske har specialvalidering av längd på lösenord

IdentityUser

Nu finns användaren Hur loggar jag in?

Vi måste skapa en Identity

User.Identity När man är inloggad vet ASP.NET detta genom att kolla på en Cookie. Den sätter då User.Identity till en ClaimsPrincipal! ClaimsIdentity : IIdentity

Hur skapar man en Identity då?

var identity = await usermanager.createidentityasync(user, DefaultAuthenticationTypes.ApplicationCookie);

Nu måste vi säga till ASP.NET att vi ska loggas in med dennna identiteten

IAuthenticationManager

Vi använder OWIN för att kunna applicera ASP.NET Identity. Detta konfigurerar vi t.ex. i Startup.cs. Vi kan sen hämta ut detta context här och använda en AuthenticationManager. var authenticationmanager = HttpContext.GetOwinContext().Authentication;

Nu vill vi sätta en Cookie för att säga att vi är inloggad!

var properties = new AuthenticationProperties { IsPersistent = false }; authenticationmanager.signin(properties, identity);

Hur vet ASP.NET vilken Cookie den ska sätta, och ens att den ska kolla efter en Cookie?

Konfigureras i Startup.cs app.usecookieauthentication(new CookieAuthenticationOptions { AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie, LoginPath = new PathString("/Home/Login") });

Hur kräver jag inloggning på en action?

[Authorize]

Hur skulle inloggningen se ut?

[AllowAnonymous] [HttpPost] [ValidateAntiForgeryToken] public async Task<ActionResult> Login(string username, string password) { var user = await usermanager.findasync(username, password); if (user!= null) { var identity = await usermanager.createidentityasync(user, DefaultAuthenticationTypes.ApplicationCookie); var authenticationmanager = HttpContext.GetOwinContext().Authentication; authenticationmanager.signin(new AuthenticationProperties { IsPersistent = true }, identity); } return RedirectToAction("Index"); } return View();

Hur tillåter jag anonyma användare till en action?

[AllowAnonymous] [HttpPost] [ValidateAntiForgeryToken] public async Task<ActionResult> Login(string username, string password) { }

Vad har Claims med detta att göra?

Claims innehåller t.ex. din email

[Authorize] public ActionResult Index() { var identity = User.Identity as ClaimsIdentity; var email = identity.findfirst("email").value; }

Du kan utöka med egna!

identity.addclaim(new Claim("gender", "Male")); authenticationmanager.signin(properties, identity);

[Authorize] public ActionResult Index() { var identity = User.Identity as ClaimsIdentity; var gender = identity.findfirst("gender").value; }

Detta verkar jättekomplext..

Säkerhet är komplext, och svårt!

Testning

Varför Testa vår kod?

Räcker det inte att kompilera och köra vår applikation?

Dyrt i längden!

Lager-strukturen i MVC gör det enklare att skriva tester för varje lager

Enhetstester (Unit Test) Testa specifik funktionalitet inga externa dependencies

Integrationstester Testa ett realistiskt flöde går mot alla externa dependencies

Controller Business Lager Data Lager Databas Enhetstest Enhetstest Enhetstest Integrationstest

Testbar kod

public class AddressBookRepository { private static List<Entry> entries = new List<Entry>(); public bool Add(Entry entry) { if (entries.any(e => e.name == entry.name)) return false; entries.add(entry); } } return true;

Hur skriver vi ett test för detta?

Ett Test Projekt är bara ett Class Library

Finns massor med olika Test Ramverk

MSTest

NUnit

XUnit

[TestClass] public class AddressBookTests { }

En Test Class per område

Tester definieras genom att skapa metoder

[TestMethod] public void Add_WithDuplicateInformation_ShouldReturnFalse() { }

Långa, beskrivande namn är bra!

Arrange, Act, Assert

1) Skapa object som krävs innan vi kör koden som ska testas 2) Kör koden som ska testas 3) Verifera att resultatet blev som väntat

[TestClass] public class AddressBookTests { [TestMethod] public void Add_WithDuplicateInformation_ShouldReturnFalse() { // ARRANGE var entry = new Entry { Name = "Filip }; var addressbook = new AddressBookRepository(); // ACT var couldaddentryonce = addressbook.add(entry); var couldaddentrytwice = addressbook.add(entry); } } // ASSERT Assert.IsTrue(couldAddEntryOnce); Assert.IsFalse(couldAddEntryTwice);

Vad är skillnaden på att köra Action via ett test och via en webbläsare?

Vad behöver vi veta om hur ASP.NET MVC fungerar internt?

return View(photos); protected internal virtual ViewResult View(string viewname, string mastername, object model) { if (model!= null) this.viewdata.model = model; ViewResult viewresult = new ViewResult(); viewresult.viewname = viewname; viewresult.mastername = mastername; viewresult.viewdata = this.viewdata; viewresult.tempdata = this.tempdata; viewresult.viewenginecollection = this.viewenginecollection; return viewresult; }

var controller = new GalleryController();

var index = controller.index() as ViewResult; public ActionResult Index() { ViewBag.ClientIp ViewBag.QueryString ViewBag.RawUrl = Request.UserHostAddress; = Request.QueryString; = Request.RawUrl; } return View();

Var sätts Request, Response, etc?

ASP.NET hanterar det via sin Request/Reponse Life Cycle

Det sker alltså massor mer än att det bara skapas en instans av vår Controller

Finns det något vi kan göra för att testa delar av funktionaliteten?

Integrationstest är en bättre lösning!

Kan jag inte bara sätta alla värden...

[TestClass] public class GalleryControllerTests { [TestMethod] public void Index_ShouldReturn_IndexViewWithRequestDetailsInViewBag() { // ARRANGE var controller = new GalleryController(); var httprequest = new HttpRequest("", "http://localhost/gallery/", ""); var httpcontext = new HttpContext(httpRequest, new HttpResponse(null)); var requestcontext = new RequestContext(new HttpContextWrapper(httpContext), new RouteData()); controller.controllercontext = new ControllerContext(requestContext, controller); // ACT var index = controller.index() as ViewResult; } } // ASSERT Assert.IsNotNull(index); Assert.AreEqual("/Gallery/", index.viewbag.rawurl);

Får jag ut HTML nu? NEJ!

Testar jag verkligen att rätt HTML returneras via ett enhetstest? NEJ!

Varför inte?

var index = controller.index() as ViewResult; index.executeresult(controller.controllercontext); Det är först nu ASP.NET letar upp vår View, kompilerar Razor-koden, mappar värden och sedan skriver HTML till vår Response stream Detta kommer dock inte fungera, det fattas fortfarande mycket som krävs, vilket är anledninen till att ett integrationstest är mer lämpligt.

Mock & Fake

Lämpligt när vi skriver tester!

Vad är ett Interface?

public ActionResult Index() { var repository = new AddressRepository(); repository.find(x => x.id == Guid.Empty); } return View(repository.All()); public ActionResult Index(IAddressRepository repository) { repository.find(x => x.id == Guid.Empty); } return View(repository.All());

new FakeAddressRepository() new AddressRepository() public ActionResult Index(IAddressRepository repository) { repository.find(x => x.id == Guid.Empty); } return View(repository.All());

[TestClass] public class AddressControllerTests { [TestMethod] public void Index_SimpleCall_ShouldReturn_ViewDataWithAddresses() { var controller = new AddressController(null); ViewResult indexresult = controller.index() as ViewResult; } } Assert.IsNotNull(indexResult.Model);

Skapa en proxy i runtime som aggerar som vi säger till den

NSubstitute http://nsubstitute.github.io/

var repository = Substitute.For<IAddressRepository>(); var controller = new AddressController(repository);

Kan jag returnera fake data?

var { }; addresses = new[] new Address {StreetName = "From a test!"} var repository = Substitute.For<IAddressRepository>(); repository.all().returns(addresses);

Skicka in vår mockade IAddressRepository Vår Action returnerar ett ViewResult var controller = new AddressController(repository); ViewResult indexresult = controller.index() as ViewResult; Assert.IsNotNull(indexResult.Model); Som vi kan få ut en modell ifrån var firstaddressinmodel = ((IEnumerable<Address>) indexresult.model).first(); Assert.AreEqual("From a test!", firstaddressinmodel.streetname); Första Adressen i modellen är samma som vi skickade in genom att säga vad vår mockade klass skulle returnera när vi kallar på All!

Dependency Injection & Inversion of Control

Separation of Concerns

Löst Kopplat

Hur lätt är det att skriva ett test nu som inte går mot databasen?

Dependency Injection

Automatiskt skapa instanser av våra klasser och skicka in de i konstruktorn

Ramverk för att göra detta åt oss i ASP.NET MVC

Autofac https://autofac.org/

Install-Package Autofac.Mvc5 http://docs.autofac.org/en/latest/integration/mvc.html

public class MvcApplication : System.Web.HttpApplication { protected void Application_Start() { SetupContainer(); } } AreaRegistration.RegisterAllAreas(); RouteConfig.RegisterRoutes(RouteTable.Routes);

private void SetupContainer() { var builder = new ContainerBuilder(); builder.registercontrollers(typeof(mvcapplication).assembly); builder.registertype<addressrepository>().as<iaddressrepository>().instanceperlifetimescope(); } var container = builder.build(); DependencyResolver.SetResolver( new AutofacDependencyResolver(container));

Starta en ny konfiguration av hur vi mappar t.ex Interface till Klasser var builder = new ContainerBuilder();

Registrera alla Controllers i vårt assembly (MVC Projektet) builder.registercontrollers(typeof(mvcapplication).assembly);

Manuellt registrera typ-mappning mot interface builder.registertype<addressrepository>().as<iaddressrepository>().instanceperlifetimescope();

Bygg konfigurationen var container = builder.build();

Vad gör en Container? var repository = container.resolve<iaddressrepository>() Gör i princip new AddressRepository()

Varför är det bra då? var controller = container.resolve<addresscontroller>() Containern fattar att den ska automatiskt skjuta in IAddressRepository och skapr därför internet en instans av det objektet! public AddressController(IAddressRepository repository) { this.repository = repository; }

Hur får vi MVC att använda vår container? var container = builder.build(); DependencyResolver.SetResolver( new AutofacDependencyResolver(container));

Sätt en break-point i konsturktorn!

Integrationstester & Automatiska UI Tester

Hur funkar ett integrationstest?

Gör en riktig Request via en browser: Automatiskt!

Selenium http://www.seleniumhq.org/

Körs som vanliga Test i Visual Studio

Install-Package Selenium.WebDriver

Ladda ner Firefox

Ladda ner GeckoDriver https://github.com/mozilla/geckodriver/releases

var firefox = new FirefoxDriver();

[TestClass] public class GalleryControllerTests { [TestMethod] public void Index_ShouldReturn_IndexViewWithListOfImages() { } }

// ARRANGE var firefox = new FirefoxDriver(); firefox.navigate().gotourl("http://localhost:58948/"); RemoveOldPhotos(firefox); Vår ASP.NET MVC webbsida Detta kräver att vi startat projektet! Vid integrationstester vill vi se till att vi jobbar med ett cleant state

// ACT var fileuploadelement = firefox.findelementbyname("file"); fileuploadelement.sendkeys(@"c:\users\filip\desktop\sunset.jpg"); var name = Guid.NewGuid(); var nameelement = firefox.findelementbyid("name"); nameelement.sendkeys(name.tostring()); Peka på en fil som ska laddas upp var submitbutton = firefox.findelementbyid("submit"); submitbutton.click(); Thread.Sleep(2000); Vänta en stund, tills vi vet att vår AJAX-request fått ett svar och vår DOM har uppdaterats Skicka iväg vårt formulär var firsttitle = firefox.findelementbycssselector("div#result div.photo h3");

// ASSERT Assert.AreEqual(name.ToString(), firsttitle.text); firefox.quit();

private static void RemoveOldPhotos(FirefoxDriver firefox) { while (true) { try { Vår DOM uppdateras varje gång, så vi behöver leta efter nya referenser till alla länkar var link = firefox.findelementbycssselector("div#result div.photo div a"); if (link == null) break; } } link.click(); var alert = firefox.switchto().alert(); alert.accept(); } catch { break; } Hittar vi ingen länk att trycka på kastas ett exception, då kan vi helt enkelt gå tillbaka till testet Klicka på OK i Confirm-dialogen

Vår ASP.NET MVC Applikation testat som om en användare besöker den!

När är detta bättre än enhetstester?

Labb 4

Fortsätt med Bildgalleriet Utnyttja Dependency Injection i era Controllers Skriv tester för era Actions i ett nytt testprojekt Testerna skall inte gå hela vägen ner till databasen Skapa ett testprojekt för automatiserade UI tester med hjälp av Selenium

mail@filipekberg.se