Documente Academic
Documente Profesional
Documente Cultură
- Xmlns
12. Care din urmatoarele nu repezinta un mecanism pentru gestiunea starii in ASP.NET Core?
- Cookies
Medii
Care din urmatoarele afirmatii este adevarata in cee ace priveste XAML
ul?
Separarea codului de design si a logicii programului
Pentru a arata dial box in mod modal care metoda este folosita?
ShowDialog
Care din urmatoarele parti XAML arata imaginea unui buton de control?
< Button> < StackPanel Orientation="Horizontal"> < Image
Source="speaker.png" Stretch="Uniform"/> < TextBlock Text="Play
Sound" /> < /StackPanel> < /Button>
ADO.NET
Care din urmatoarele afirmatii nu este adevarata legata de ADO.NET?
ADO.NET nu suporta arhitectura deconectata.
Intr-o aplicatie ASP vrei sa afisezi o lista de client intr-o pagina web. Lista de clienti
afiseaza 10 clienti deodata, si ti se cere sa editezi client. Care web control e cel
mai pottrivit?
GridView control
Vrei sa stochezi datele care sunt accesibile pentru orice user care se conecteaza la
aplicatia ta Web. Care obiect folosesti?
Application
In aplicatia voastra web, ASP.NET 2.0 vrei sa afisezi o imagine care este selectata
dintr o colectie de imagini. Cum veti face aceasta?
Folosim AdServer control sic reem un fisier XML, care contine configuratia
controaler ului
Care dintre urmatoarele este necesara cand combini datele intr un DataSet?
Un primary key trebuie sa fie definit in obiectele DataTable
Care dintre urmatoarele reprezinta cel mai bine folosirea lui: Table, TableRow si
Table-Cell controls?
Pentru a creea un cotroaler customizat pentru a afisa datele in mod tabular
Echipa:
• Lect. Dr. Florina Covaci, Asist. Dr. Paula Zalhan
Andrew Troelsen, Philip Japikse - Pro C# 7 with .NET and .NET Core
Christian Nagel - Professional C# 7 and .NET Core 2.0
Platforma de elearning:
econ.elearning.ubbcluj.ro/moodle
https://insights.stackoverflow.com/survey/2020
MEDII DE PROGRAMARE ȘI DEZVOLTARE
Istoria .NET (I)
• 2002 .NET framework 1.0 – C# 1.0
• C# 1.0 un nou limbaj de programare dezvoltat pentru .NET
framework - Anders Hejlsberg
• .NET framework continea 3000 de clase la momentul cand a
fost creat
• Furnizează:
• metoda Run() pentru a porni aplicația
• StartupUri – setează sau furnizează valoarea pentru un URI care specifică fereastra care se
deschide automat când o aplicație pornește
• Current –permite accesul din orice parte a aplicatiei la obiectul aplicație care rulează
• Windows – asigură acces la o colecție care reprezintă ferestrele din memorie pentru
aplicația WPF curentă. Pe masură ce se crează noi obiecte de tip fereastră, ele sunt
adaugate in colectia Application.Windows
Func<double, double>
MEDII DE PROGRAMARE ȘI DEZVOLTARE
Bubble Sorter Class
bool swapped = true;
do
{swapped = false;
for (int i = 0; i < sortArray.Length—1; i++)
{
if (sortArray[i] > sortArray[i+1])) // problem with this test
{
int temp = sortArray[i];
sortArray[i] = sortArray[i + 1];
sortArray[i + 1] = temp;
swapped = true;
} } } while (swapped);
• Argumentele handlerului
• Un obiect care a aruncat evenimentul (sender)
• Un obiect care contine informatie specifica evenimentului (de tip
EventArgs)
• Fiecare din aceste clase expune o varietate de obiecte comanda statice pe care le
putem utiliza in aplicatii; trebuie sa cream binding-uri si handlere pentru aceste
comenzi pt a le putea utiliza in aplicatie
Implementarea unei comenzi
1. se decide comanda care se doreste a se utiliza
2. se asociază comanda cu un control sau cu un input
3. se crează metoda care gestionează comanda
4. se crează controlul CommandBinding care leagă obiectul Command
la handlerul de comandă si optional, la o metodă care gestionează
Command.CanExecute
5. se adaugă CommandBinding la collectia Commands a controlului sau
la controlul Window
Invocarea comenzii
• Prin asocierea ei cu un control folosind un input sau invocare cu un input
Crearea CommandBinding
-asociaza o comanda cu un command handler
CommandBinding abinding = new CommandBinding();
abinding.Command = ApplicationCommands.Find;
abinding.Executed += new ExecutedRoutedEventHandler(myCommandHandler);
this.CommandBindings.Add(abinding);
Comenzi Bubbling
• Comenzile se rostogolesc către containerele din varful ierarhiei in care
rezidă controlul unde se invoca comanda
• Fiecare control are propria colecție CommandBinding
• Se poate opri rostogolirea procesarea comenzii prin setarea
Handled=true
private void myCommandHandler(object sender,
ExecutedRoutedEventArgs e)
{
// Handle the command here
e.Handled = true;
}
Dezactivarea comenzilor
• Comenzile care nu sunt asociate in CommandBinding sunt automat dezactivate
• Fiecare control care are in proprietatea Command asignat o comandă disables devine la randul lui dezactivat
• Pentru a dezactiva comenzi care sunt assignate in Command si avem setat si CommandBinding se utilizează
Command.CanExecute
• Este un eveniment care determină dacă o comandă se poate executa
connection.Open();
Obiecte Command
• Clasa SqlCommand derivata din DbCommand este o reprezentare
obiectuala unei interogari SQL sau procedura stocata
command.Parameters.Add(parameter);
…
command.ExecuteNonQuery();
}
Obiecte Data Reader
• Stream-uri de date readonly
• Statement-uri SELECT – e nevoie sa iteram volume mari de date
SqlDataReader myDataReader =
myCommand.ExecuteReader())
{
while (myDataReader.Read())
{
Console.WriteLine("Titlu:”+ myDataReader[„Titlu"] +
“Autor: “+ myDataReader[„Autor"]);
}
Executia command
• ExecuteNonQuery –nu returneaza output,doar nr. de inregistrari
afectate
• Proprietatea
ItemsControl.ItemsSource
• Implicit pentru proprietatea
ItemsSource bindingul e OneWay
Collection views
• Dupa ce un ItemsControl este legat la o colectie de date->operatii de
sortare, filtrare sau grupare a datelor – utilizam collection views –
clase care implementeaza intefata ICollectionView
Membrii DbSet<T>:
• Add – adaugarea unui obiect in colectie ; acestea vor fi marcate cu starea
Added si vor fi inserate in baza de date cand se apeleaza SaveChanges pentru
DBContext
• Create – creaza o noua insanță de tipul specificat
• Find – gasește un rand dupa cheia primară și returnează un obiect
reprezentând acel rând
• Remove – marcheaza un obiect pentru ștergere
DbSet<T> - Exemplu
using (AutoLotEntities context = new AutoLotEntities())
{
context.Cars.Add(new Car() { ColorOfCar = "Black",
MakeOfCar = „BMW",
YearOfCar = „2018" });
context.SaveChanges();
}
modelBuilder.Entity<PostTag>()
.HasOne(pt => pt.Post)
.WithMany(p => p.PostTags)
.HasForeignKey(pt => pt.PostId);
modelBuilder.Entity<PostTag>()
.HasOne(pt => pt.Tag)
.WithMany(t => t.PostTags)
.HasForeignKey(pt => pt.TagId); } }
Operații - Adăugare • Metoda Add() method primeste ca si paramteru
un obiect de tip Car si il adauga la colectia Cars
• Se crează o instanță , se adauga la in clasa context AutoLotEntities
proprietatea DbSet<T>
corespunzătoare din clasa context • Cand un obiect este adăugat la un DbSet<T>,
și apoi se apeleaza SaveChanges() DbChangeTracker marchează starea noului
private static int AddNewRecord() obiect ca fiind EntityState.Added.
{
• La apelul SaveChanges , se generează interogări
using (var context = new
AutoLotEntities()) SQL pentru modificările aflate in așteptare
{
• Dacă există mai mult de o modificare, atunci
var car = new Car() { Make = „Opel",
Color = "Brown", Year=„2017"}; acestea se vor executa in tranzactie
context.Cars.Add(car);
• Daca nu apar erori, datele devin persistente in
context.SaveChanges();
return car.CarId; baza de date si proprietățile database-
} generated (în acest caz CarId) se actualizează cu
} valori din baza de date
Operații : Ștergere
• DbSet<T> • EntityState
private static void RemoveRecord(int carId) private static void RemoveRecordUsingEntityState(int carId)
{ {
using (var context = new AutoLotEntities()) using (var context = new AutoLotEntities())
{ {
Car carToDelete = context.Cars.Find(carId); Car carToDelete = new Car() { CarId = carId };
if (carToDelete != null) context.Entry(carToDelete).State = EntityState.Deleted;
{ try
context.Cars.Remove(carToDelete); {
if (context.Entry(carToDelete).State != EntityState.Deleted) context.SaveChanges();
{ }
throw new Exception("Unable to delete the record"); catch (DbUpdateConcurrencyException ex)
} {
context.SaveChanges(); WriteLine(ex);
Operații: Actualizare
private static void UpdateRecord(int carId)
{
using (var context = new AutoLotEntities())
{
Car carToUpdate = context.Cars.Find(carId);
if (carToUpdate != null)
{
WriteLine(context.Entry(carToUpdate).State);
carToUpdate.Color = "Blue";
WriteLine(context.Entry(carToUpdate).State);
context.SaveChanges();
SavingChanges
• Evenimentul se declansează dupa ce metoda SaveChanges() a fost
apelată, dar înainte ca baza de date să fie actualizată. Entitătile din
tranzactie sunt disponibile prin proprietatea ObjectStateEntry a lui
DbContext
• CurrentValues - valorile curente ale proprietăților entităților
• OriginalValues - valorile originale ale proprietăților entităților
• Entity – entitatea reprezentată de ObjectStateEntry object
• State – starea curentă a entității (Modified, Added, Deleted)
• AcceptChanges – acceptă valorile currente
• ChangeState – actualizeză starea unei unei entități
• GetModifiedProperties – returneaza numele tuturor proprietăților modificate
• RejectPropertyChanges – respinge modificarile
SavingChanges
• Permite respingerea modificărilor pentru un vehicul când acesta are
culoarea roșie
private void OnSavingChanges(object sender, EventArgs eventArgs)
{
var context = sender as ObjectContext;
if (context == null) return;
foreach (ObjectStateEntry item in
context.ObjectStateManager.GetObjectStateEntries(
EntityState.Modified | EntityState.Added))
{
if ((item.Entity as Inventory)!=null)
{
var entity = (Inventory) item.Entity;
if (entity.Color == "Red")
{
item.RejectPropertyChanges(nameof(entity.Color));
Incărcarea datelor
• Incărcarea datelor din baza de date în entități se poate realiza in trei
moduri:
• Lazy
– bazate pe setările de context
• Eager
• Directorul Migrations/LibraryContextModelSnapshot.cs
• Motivatie LINQ
• Aplicatiile vor accesa date la un anumit moment in timpul executiei
• Datele pot fi regasite in fisiere XML, bd relationale, colectii in memorie, siruri
• Acest feature este foarte util cand utilizam LINQ – multe interogari LINQ vor returna o secventa de
tipuri de date, care nu sunt cunoscute pana la momentul compilarii, deci nu vom putea declara tipul
unei variabile explicit
Sintaxa de initializare a obiectelor/colectiilor
• Sintaxa de intializare colectie pentru a umple o lista List<T> cu obiecte Rectangle, fiecare avand
doua obiecte Point care reprezinta o pozitie determinata de doua coordonate (x,y):
List<Rectangle> myListOfRects = new List<Rectangle>
{
new Rectangle {TopLeft = new Point { X = 10, Y = 10 },
BottomRight = new Point { X = 200, Y = 200}},
new Rectangle {TopLeft = new Point { X = 2, Y = 2 },
BottomRight = new Point { X = 100, Y = 100}},
new Rectangle {TopLeft = new Point { X = 5, Y = 5 },
BottomRight = new Point { X = 90, Y = 75}}
};
• Aceasta sintaxa combinata cu variabilele cu tip implicit ne permit declararea de tipuri anonime,
utile la crearea de proiectii LINQ
Expresii Lambda
• operator (=>) permite construirea unei expresii lambda, care poate fi
folosita in orice moment - se invoca o metoda care necesita un
delegate puternic tipizat ca si argument
• Expresiile lambda simplica modul de lucru in .NET, reducand numarul
de linii de cod care trebuie scrise
• ( ArgumentsToProcess ) => { StatementsToProcessThem }
Metode extinse
• Metode extinse permit adaugarea de functionalitati la clasele existente fara a folosi mostenirea, si permit
adaugarea de noi functionalitati la clase sealed
• La crearea unei metode extinse primul paramteru este calificat cu cuvantul cheie this marcand tipul care se
extinde.
• Metodele extinse trebuie definite in cadrul unei clase statice si trebuie declarate folosind cuvantul cheie
static
namespace MyExtensions
{
static class ObjectExtensions
{
// Define an extension method to System.Object.
public static void DisplayDefiningAssembly(this object obj)
{
Console.WriteLine("{0} lives here:\n\t->{1}\n", obj.GetType().Name,
Assembly.GetAssembly(obj.GetType()));
}}}
• Cand creem interogari LINQ, utilizam metode extinse definite in .NET.
Tipuri anonime
• Generarea definitiei unei clase la compilare prin specificarea unui set de perechi nume-valoare
• Pentru a defini un tip anonim declaram o variabila cu tip implicit si specificam datele folosind
sintaxa de initializare a obiectelor
• CSS
• JavaScript si TypeScript
• Librarii de scripting
HTML si CSS
• Cascade Style Sheets - definesc felul in care arata pagina web
• HTML tagul pentru list item <li> definea modul in care este vizualizat-
cerc,disc,patrat ->CSS
• Cu CSS se pot utiliza selectori flexibili pentru elemente HTML si se pot
defini stiluri pentru aceste elemente. Putem selecta un element prin
ID sau nume si se pot defini clase CSS care pot fi referentiate din cod
HTML
• Se pot utiliza template-uri Bootstrap - o colectie de conventii CSS si
HTML care pot fi adaptate facil
• www.getbootstrap.com - documentatie si template-uri
JavaScript si TypeScript
• Putem modifica dynamic elemente client-side
• ECMAScript – standard care defineste functionalitatile
curente si vitoare pentru JavaScript.
• Implementarea Microsoft pentru JavaScript se numeste
JScript.
• TypeScript similar cu JavaScript. Sintaxa TypeScript se
bazeaza pe JavaScript, dar aduce noi functionalitati (ex.
Cod puternic tipizat, adnotari)
• Exista multe similaritati intre C# si TypeScript
• Documentatie la : www.typescriptlang.org.
Librarii de scripting
• Pot fi utilizate server-side impreuna cu ASP.NET Core
• jQuery (http://www.jquery.org) –utilizata pentru a gestiona unitar modul in
care diferite browsere gestioneaza evenimentele
• Angular (https://angular.io) librarie de la Google bazata pe patternul MVC
creata pentru a simplifica dezvoltarea si testarea aplicatiilor web de tip
single-page (Spre deosebire de ASP.NET MVC, Angular ofera patternul MVC
in codul client-side)
• React (https://reactjs.org) librarie de la FaceBook care ofera functionalitati
prin care se pot actualiza facil intefetele utilizator pe masura ce datele se
modifica in background
• Visual Studio ofera template-uri pentru Angular si React
Structura unei aplicatii Web – cu Razor
• In directorul wwwroot regasim continut de tip client-side CSS, JavaScript,
imagini, si orice alt continut non-programatic
• Directorul Pages contine pagini Razor si fisiere suport. Fiecare pagina este o
pereche a urmatoarelor fisiere:
• Un fisier .cshtml care contine markup HTML si cod C# utilizand sintaxa Razor.
• Un fisier .cshtml.cs care contine cod C# pentru a gestiona evenimentele la nivel de
pagina.
• Program.cs
Punctul de start al aplicatiei.
• Startup.cs
• Contine cod care configureaza comportamentul aplicatiei
Clasa Program
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
La pornire aplicatia ASP.NET Core creaza un obiect host
Incarca configurarile din fisierul appsettings.json
Clasa Startup
public void ConfigureServices(IServiceCollection services)
{
services.AddRazorPages();
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
• Cu metoda ConfigureServices se configureaza, in containerul dependency injection ,
servicii necesare aplicatiei. IServiceCollection contine toate serviciile deja inregistrate si
permite adaugarea de noi servicii
• Cu metoda Configure este definit modul de gestionare a cererilor ca o serie de
componente middleware
Configurare Servicii
• Exemplu de trecere in C#
• {} delimiteaza un bloc de cod C#
• Clasa de baza Pagemodel contine o proprietate de tip dictionar, care
este utilizata pentru a trimite date la un View
• Obiectele sunt adaugate folosind perechi de tipul cheie/valoare
• Proprietatea Title este adaugata la dictionarul ViewData
ViewData si Layout
• Proprietatea title este folosita in Pages/Shared/_Layout.cshtml
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-
width, initial-scale=1.0" />
<title>@ViewData["Title"] – Sample App</title>
@*Comentariu*@ spre deosebire de <!-- -->
Setarea Layout-ului
• Se realizeaza in Pages/_ViewStart.cshtml
@{
Layout = "_Layout";
}
• Seteaza pentru toate paginile din directorul Pages, layout-ul definit in
Pages/Shared/_Layout.cshtml
Tag Helpers
• Tag Helpers permit codului de tip server-side sa participe la crearea si
afisarea elementelor HTML in fisiere Razor
• Tag Helpers folosesc limbaj C# si targeteaza elemente HTML bazandu-
se pe numele elementului si numele atributului
• Sunt prefixati cu “asp-”
Ex. Label Tag Helper targeteaza elementul HTML <label> cand
sunt aplicate atributele tag helperului
<label asp-for="Title"></label>
Tag Helpers
public class Book
{ • Genereaza eticheta si atributul for pentru
public int ID { get; set; } un element de tip label
[Display(Name = "Book Title")]
• Tipizare puternica cu proprietatea
public string Title { get; set; }
modelului
public string Author { get; set; }
}
• A generat valoarea pentru atributul “Title”,
Markup Razor care reprezinta id-ul asociat cu elementul
@model Book <input>
<label asp-for="Title"></label> • Tag-Helper-ul genereaza elemente id si for
<input asp-for="Title" /> consistente, astfel incat acestea sa fie
Se genereaza HTML
corect asociate
• Eticheta se genereaza din atributul Display
<label for="Title">Book Title</label>
Ce ofera Tag Helpers?
1. Experienta de dezvoltare asemanatoare HTML – de cele mai multe
ori, markup-ul Razor cu tag helpers este asemanator cu cel standard
HTML. Designeri front-end familiarizati cu HTML/CSS/JavaScript pot
edita markup Razor fara a invata sintaxa Razor
Se genereaza HTML
<a href="/Index">Back to List</a>
<a href="/Edit? id=10">Edit</a>
Tag Helper pentru validare
• Validation Message Tag Helper
• afiseaza un mesaj de validare pentru proprietatea aferenta din modelul nostru
• este utilizat cu atributul asp-validation-for a unui element HTML <span>
• in general il utilizam dupa un tag helper input pentru acceasi proprietate, pentru a
afisa erorile de validare langa input-ul care a cauzat eroarea
<input asp-for="Book.Author" />
<span asp-validation-for="Book.Author"></span>
• Validation Summary Tag Helper afiseaza un rezumat al erorilor de validare
<div asp-validation-summary="ModelOnly"></div>
• Validarea se realizeaza pe baza constrangerilor si atributelor adnotarilor in
clasele din model
Tag Helpers custom
• Tag helper pentru tag-ul <email>Support</email>
• <a href="mailto:support@ubbcluj.ro">support@ubbcluj.ro</a>
using Microsoft.AspNetCore.Razor.TagHelpers;
public class EmailTagHelper : TagHelper
{ public override void Process(TagHelperContext
context, TagHelperOutput output)
{ output.TagName = "a"; // Inlocuieste <email> cu <a>
tag }
}
Tag Helpers custom
• Tag helpers utilizeaza o conventie de nume referitor la elementul pe
care il targeteaza
• Elementul targetat este radacina EmailTagHelper – email -> element
targetat <email>
• clasa EmailTagHelper mosteneste TagHelper. Clasa TagHelper ofera
metodele si proprietatile necesare pentru a crea tag helpers
• metoda suprascrisa Process controleaza ceea ce face tag helper-ul
cand este executat
Utilizare
• Pentru a fi vizibil in paginile Razor utilizam directiva @addTagHelper
• In _ViewImports.cshtml
@{
var quote = " An apple a day keeps the doctor away ";
}
<p>@quote</p>
@{
quote = " The future depends on what you do today ";
}
<p>@quote</p>
Se randeaza
<p> An apple a day keeps the doctor away </p>
<p> The future depends on what you do today </p>
Functii locale in blocuri de cod
• Se pot delcara functii locale cu markup pentru a fi utilizate ca metode
template
@{
void RenderName(string name)
{ <p>Name: <strong>@name</strong></p>
}
RenderName(“John Keller");
RenderName("Martin Johnson");
}
<p>Name: <strong>John Keller</strong></p>
<p>Name: <strong>Martin Johnson</strong></p>
Tranzitie implicita
• Limbajul implicit intr-un bloc de cod este C#, dar poate face implicit
tranzitia la HTML
@{
var inCSharp = true;
<p>Now in HTML, was in C# @inCSharp</p>
}
Tranzitie explicita
• Delimitata - Pentru a defini o sectiune dintr-un bloc de cod care trebuie sa
randeze HTML adaugam tag-ul <text>
return
RedirectToPage("./Index");
}
Binding
[BindProperty]
public Book Book { get; set; }
<form method="post">
<input asp-for="Book.Title" />
</form>
Se face binding cu proprietatea Title
Antiforgery token
• <form method="post">
• <!-- Input and Submit elements -->
• <input name="__RequestVerificationToken" type="hidden"
value="<Antiforgery token >" />
• </form>
• FormTagHelper injecteaza token-uri antiforgery in elementul HTML
form
Atacuri Cross-Site Request Forgery
• Cunoscute si ca atacuri XSRF sau CSRF
• Atacuri asupra aplicatiilor web in care o aplicatie malitioasa poate
influenta interactiunea dintre un client browser si a aplicatie web care
a autentificat anterior acel client
• Posibile pentru ca browserele web trimit token-uri de autentificare
automat cu fiecare cerere catre un website
• Atac One-click sau session riding – profita de sesiunea autenficata
anterior
Exemplu
• Un utilizator se logheaza in www.good-banking-site.com, serverul
autentifica userul si trimite un raspuns care include un cookie de
autentificare
• Site-ul este vulnerabil pentru ca are incredere in cereri care vin
impreuna cu cookie-ul de autentificare
• Utilizatorul viziteaza un site Site-malitios www.bad-banking-site.com
contine un formular
Exemplu
<h1>Congratulations! You're a Winner!</h1>
<form action="http://good-banking-site.com/api/account"
method="post"> <input type="hidden" name="Transaction"
value="withdraw">
<input type="hidden" name="Amount" value="1000000">
<input type="submit" value="Click to collect your prize!">
</form>
-se trimite formularul-browserul face cererea si include automat
cookie-ul de autentificare, iar cerea va rula pe good-banking-site.com si
va putea executa orice operatie pe care o executa un utilizator
autentificat
Gestiunea starii in ASP.NET Core
• HTTP este un protocol stateless.
• Util cand dorim sa permitem link-urilor sa pasteze starea, aceste linkuri putand fi trimise
prin email sau retele de socializare
• Utilizatorii pot modifica usor valoarea query string pt ca ea este vizibilă in browser
• Valorile din query string trebuie validate
• URL query strings sunt publice, nu trebuie folosite pentru a trimite date sensitive
Request.Query["name1"]
Hidden Fields
• Sunt campuri de tip input puse in pagina HTML care nu sunt afisate
utilizatorului
<input type="hidden" value=""/>
• Proprietatea Value - se poate salva date
services.Configure<IdentityOptions>(options => {
// Default Lockout settings.
options.Lockout.DefaultLockoutTimeSpan =
TimeSpan.FromMinutes(5);
options.Lockout.MaxFailedAccessAttempts = 5;
options.Lockout.AllowedForNewUsers = true; });
• Autorizare folder
options.Conventions.AuthorizeAreaFolder("Identity", "/Manage");
options.Conventions.AuthorizeAreaFolder("Identity", "/Manage",
"AtLeast21");
Combinare autorizare cu acces anonim
• Valid
.AuthorizeFolder("/Private").AllowAnonymousToPage("/Private/P
ublic")
• Invalid
.AllowAnonymousToFolder("/Public").AuthorizePage("/Public/Pri
vate")
Autorizarea prin atribut
[Authorize(Policy = "RequireAdministratorRole")]
public class UpdateModel : PageModel
{ public ActionResult OnPost() { }
}
}
Specificare roluri pe baza unei politici (II)
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews();
services.AddAuthorization(options =>
{ options.AddPolicy("MoreRights", policy =>
policy.RequireRole("Administrator", "PowerUser", "BackupAdministrator"));
});
}
Autorizare claim based
• Cand o entitate este creata ii pot fi asociate una/mai multe claim-uri
(revendicare)
• Un claim – o pereche de tipul nume-valoare – reprezinta ceea ce e
subiectul (nu ceea ce face)
• Ex. Permis de conducere – data nastere -> claim
• Autorizarea bazata pe claim verifica valoarea acelui claim si permite
accesul la resurse pe baza acelei valori
Aplicam politica
[Authorize(Policy = "EmployeeOnly")]
public class UpdateModel : PageModel
{ public ActionResult OnPost() { }
}
Adaugare claim cu valori
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews();
services.AddAuthorization(options =>
{ options.AddPolicy("Founders", policy =>
policy.RequireClaim("EmployeeNumber", "1", "2", "3", "4",
"5"));
});
}
Autorizare pe baza unor politici
• Autorizarea pe baza de roluri si claims utilizeaza o serie de building-blocks – cerinta, handler de cerinta, o
politica preconfigurata
• O politica de autorizare contine una sau mai multe cereri – configurate ca parte din serviciul de autorizare
base.OnCreate(savedInstanceState);
Xamarin.Essentials.Platform.Init(this, savedInstanceState);
global::Xamarin.Forms.Forms.Init(this, savedInstanceState);
LoadApplication(new App());
}
Crearea UI
• Interfata aplicatiilor Xamarin.Forms este alcatuita din obiecte care se
mapeaza pe controalele native ale fiecarei platforme targetate
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalAppl
icationData), "TodoSQLite.db3"));
}
return database;
}
}
• Expunem baza de date ca un singleton – o singura conexiune la baza de date este creata
si este mentinuta deschisa cat timp aplicatia ruleaza, evitand operatia costisitoare de
deschidere/inchidere db la fiecare operatie pe bd
Creare Tabel
• Constructorul primeste ca si parametru calea spre fisierul de tip baza
de date
entry.Behaviors.Clear();
Ciclul de viata al aplicatiei
• Clasa Application contine trei metode care pot fi suprascrise pentru a
raspunde modificarilor din ciclul de viata al aplicatiei
• OnStart – apelata cand aplicatia porneste.
• OnSleep – apelata de fiecare data cand aplicatia se muta in background.
• OnResume – apelata cand se face resume la aplicatie, dupa ce a fost trimisa in
background.
• Nu exista o metoda dedicata pentru terminarea aplicatiei
• In cirmcumstante normale (nu are loc un crash), terminarea aplicatiei
se va realiza din starea Onsleep
Persistarea datelor intre starile aplicatiei
• Clasa Application are o proprietate de tip dictionar:
Properties - poate fi folosita pentru a stoca date intre
diferite stari ale aplicatiei
• Dictionarul utilizeaza o cheie de tip string si salveaza
valoarea unui obiect
• Dictionarul este salvat pe dispozitiv in mod automat si
este repopulat cand se realizeaza repornirea aplicatiei
public partial class App : Application
{ const string displayText = "displayText";
public string DisplayText { get; set; }
public App() { ...}
protected override void OnStart() {
Console.WriteLine("OnStart");
if (Properties.ContainsKey(displayText)) {
DisplayText = (string)Properties[displayText]; }
}
protected override void OnSleep() {
Console.WriteLine("OnSleep");
Properties[displayText] = DisplayText; }
Nu este necesara restaurarea datelor la OnResume deoarece
cand aplicatia se afla in background datele sunt in memorie
Libraria Xamarin.Essentials
• Multe din functionalitatile oferite de aplicatiile mobile se bazeaza pe
noi tipuri de date pot fi colectate de la device-urile mobile (localizare
GPS etc.)
• Xamarin.Essentials ofera un API unic multi-platforma pentru aplicatii
Android, iOS sau UWP, care poate fi accesat din codul comun
• Xamarin.Essentials - NuGet package – il downloadam
• Adaugam directiva: using Xamarin.Essentials;
Clasa Geocoding
Mai multi publishers pot publica acelasi mesaj si mai multi subcribers
pot asculta acelasi mesaj
Pattern-uri pentru transferul de date (II)
• Clasa MessagingCenter – clasa statica care contine trei metode Subscribe,
Unsubscribe si Send.
• Mesajele sunt identificate printr-un string si sunt insotite de un obiect
• Constructorul subscrie la un mesaj identificat prin string-ul “Infor-
mationReady.”
• Argumentele indica obiectul care primeste mesajul, numele mesajului si o
expresie Lambda
public HomePage() {
...
MessagingCenter.Subscribe<InfoPage, Information> (this,
"InformationReady", (sender, info) => {
int index = list.IndexOf(info);
if (index != -1) { list[index] = info; } else { list.Add(info); }
});
MessageCenter (II)
async void OnListViewItemSelected(object sender,
SelectedItemChangedEventArgs args)
{ if (args.SelectedItem != null)
{listView.SelectedItem = null;
InfoPage infoPage = new InfoPage();
await Navigation.PushAsync(infoPage);
MessagingCenter.Send<HomePage, Information> (this, "InitializeInfo",
(Information)args.SelectedItem); }
Metoda Send trimite mesaje care sunt primite de toti subscriberii la acel
mesaj
Argumentele metodei Send indica obiectul care trimite mesajul, numele
mesajului si datele care sunt reprezentate de SelectedItem din ListView.
Curs 12
Servicii Web
3. Caching
• Caching trebuie sa fie aplicat cand este posibil, iar resursele trebuie sa se
autodeclare cacheable.
• Daca sunt cacheable, serverul stie durata pentru care raspunsul este valid
• Daca clientul are acces a un raspuns din cache valid, nu se mai executa cererea si
se utilizeaza copia din cache
• Specificare explicita a unei resurse cachable se face in headerul Cache-Control
unde se poate seta si durata valabilitatii copiei
• Imbunatatirea performantei pe partea de client si o mai buna scalabilitate pe
partea de server deoarece se reduce incarcarea
4. Code on demand (optional)
• De cele mai multe ori serviciul returneaza reprezentari statice de resurse -
.json, .xml
• Serviciul poate returna cod executabil pentru a extinde functionalitatea
aplicatiei
[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
[ApiController] – controale multiple
• Cream o clasa de baza
[Route("[controller]")]
public class PetsController : MyControllerBase
Atributul [Route]
• Cand utilizam atributul [ApiController] este necesar atributul [Route]
[ApiController]
[Route("[api/controller]")]
public class WeatherForecastController : ControllerBase
}
PUT
[HttpPut("{id}")] //primeste ID-ul din URL
_context.Entry(shopList).State = EntityState.Modified;
try
{
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!ShopListExists(id))
{
return NotFound();
}
else
{
throw;
}
}
return NoContent();
}
DELETE
[HttpDelete("{id}")]
public async Task<ActionResult<ShopList>> DeleteShopList(int id)
{
var shopList = await _context.ShopList.FindAsync(id);
if (shopList == null)
{
return NotFound();
}
_context.ShopList.Remove(shopList);
await _context.SaveChangesAsync();
return shopList;
}
Arhitectura orientata pe servicii
• Separarea responsabilitatilor din punct de vedere business-oriented
in servicii independente
• Fiecare componenta are propria
logica de business si poate fi
implementata separat
/Products/Details/5
Rutarea prin sintaxa predefinita
• Extrage valorile { controller = Products, action = Details, id = 5 }
• Extragerea valorilor se mapeaza daca exista in aplicatie un Controller
care se numeste ProductsController si o actiune Details :