Project: FIle > New > Project > ASP.NET > MVC
/ControllerName/ActionName/Parameters
Ex: /student/create/parameters..
/home/about/...
= class Home / method About
Numele claselor / metodelor trebuie sa coincida cu numele controllelor/actionurilor
Cu cat o ruta e scrisa mai jos in cod, are mai multa 'prioritate'. Ruta default trebuie sa fie mereu ultima in cod.
Ca la function overloading, routele nu trebuie sa aiba conflicte
Route custom:
routes.MapRoute(
name: "Concatenare",
url: "concatenare/{param1}/{param2}",
(sau) url: "{controller}/{action}/{param1},
defaults: new {
controller = "Example",
action = "Concatenare",
param1 = "Daverave", // Default
param2 = UrlParameter.Optional } );
Ca sa ignoram o ruta:
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
Controllers > Right Click > Add > Controller
- Un controller mereu are 'Controller' la sfarsit in nume
Note: Asta e complet optional! By default, cand ai un controller, linkul se mapeaza ca localhost:420/ControllerName/MethodName!
-
In App_Start > RouteConfig.css, add this:
routes.MapRoute( name: "AUniqueID", url: "mycontr/mymethod/{param1}/{param2}", defaults: new { controller = "MyContr", action = "MyMethod", param1 = UrlParameter.Optional, param2 = UrlParameter.Optional } );
-
Fac o clasa MyContrController, cu o metoda (public, string) MyMethod(string param1, string param2)
Daca vrem ca un parametru CHIAR sa fie optional, trebuie sa ii punem in metoda int? param2
Proceseaza URL-urile
Aici avem toate metodele de prelucrare CRUD
Trebuie sa se numeasca CevaController (cu Controller la sfarsit)
Right Click pe folder > Add > Controller
- Publice, non-statice, overloadable
Putem face 2 actiuni cu acelasi nume dar alti parametri SI alte tipuri de request! (Ex: GET si POST)
public ActionResult Index(){
return View(); // Intoarce automat viewul Index.cshtml
}
Pot lua ca parametri clase mai complexe:
public ActionResult Show(Student stud)
Putem sa le redenumim pt mapping asa:
[ActionName("about")]
public ActionResult AboutPage()
Sau sa nu intre in routing
[NonAction]
public...
Ca sa le facem post sau delete sau whatever; by default ele sunt get
[HttpPost]
public ...
ATENTIE: Put si Delete nu merg in forms! (Nuj de ce) La form trebuie sa punem:
La form trebuie sa punem method="post"
Daca la metoda ii zicem return View();
El o sa returneze browserului pagina cu numele Controllerul/Metoda.cshtml
Nice!
Dar ca sa fim siguri, pune si tu
return View("MyCSHTMLFileName");
Poate sa intoarca o groaza de chestii, gen json, html, etc
Clasele astea inheriteaza ActionResult si intorc:
ViewResult : HTML return View(...)
ContentResult : String return Content(...)
JsonResult : JSON return Json(...)
return RedirectToRoute(...)
return File(bytes, mimetype, downloadName)
Stocheza date intre 2 requesturi (DAR NU 3 SAU MAI MULTE!)
TempData["name"] = "Dave";
...
name = TempData["name"].ToString();
...
if(TempData.ContainsKey("name"))
Views > Folderul controllerului > click dreapta > add > view
- Un view e un .cshtml
- By default, daca facem o clasa controller cu o metoda, daca scriem
localhost:.../theclass/themethod/parametri
El o sa mearga oricum :) Pasam variabile din controller method in cshtml:
ViewBag.property = value;
Apoi il inseram in .cshtml:
<h4>@ViewBag.property</h4>
Numele inputurilor se binduiesc automat pe parametrii metodelor
<form method="post" action="/Panda/Add">
<label>Nume</label>
<input type="text" name="Name" />
<label>Adresa e-mail</label>
<input type="text" name="Email" />
<label>Age</label>
<input type="text" name="Age" />
<button type="submit">Adauga pandalau</button>
</form>
Note: Nu exista by default Delete si Put, asa ca trebuie sa punem asta inauntrul formului ca sa il facem sa mearga (lasam method="post" sus)
@Html.HttpMethodOverride(HttpVerbs.Delete)
Putem insera C# in html:
@foreach (var panda in ViewBag.SelectedPandas) {
<p>@panda.Name</p>
<p>@panda.Email</p>
}
Iata forms cu Html Helpers:
<form...
@Html.Label("Name", "Nume pentru panda")
@Html.TextBox("Name", "defaultut", new {@class="form-control"}
</form>
Better yet
<form ... action="/Panda/Edit/@Model.PandaId">
@Html.Editor("Name")
</form>
@Html.Editor("Lalala")
@Html.ValidationMessage("Lalala", "Not valid!!!", new {@class...}
Warning: Asta ar pute sa nu mearga! Vezi cum e corect In controller, putem sa verificam daca datele modelului sunt valide.
if (ModelState.IsValid) { ...
Sunt anotatii magice pe care le punem la metodele unui controller ca sa faca chestii.
Ex:
[OutputCache(Duration = 3600)] Prima oara cand e accesat linkul se salveaza si se intoarce
Putem crea un nou layout:
Copy la Views/Shared/_Layout.cshtml > paste > rename in '_MyLayout'
Il folosim: adaugam la o pagina .cshtml, sus de tot unde e aia cu Title:
Layout = "~/Views/Shared/_MyLayout.cshtml";
Cream in Views/Shared un view si dam tick la 'Create as partial view' si il numim MyPartialView
<p> @Model.Name </p>
<p> @Model.Age </p>
<p> @Model.Email </p>
Si il folosim asa (ii dam ca parametru un model):
@Html.Partial("MyPartialView", pandalaulMeu);
Setup: Tools > NuGet Package Manager > aia din mijloc > Entity Framework
Models > Click Dreapta > Create class
Un model seminifica un tabel SQL; fiecare chestie din model trebuie sa corespunda cu SQL, si de aia ii punem anotari la fiecare:
[Key] [MinLength(10)] [MaxLength(10)] [Required]
[Required(ErrorMessage = "Campul este obligatoriu")]
[EmailAddress(ErrorMessage = "Adresa nu este valida")]
Pentru proiect, trebuie sa avem si un DbContext:
Ex: ArticolDBContext : DbContext
El contine:
public ArticleDBContext() : base("ArticleConnectionString") { }
public DbSet<Article> Articles { get; set; }
public DbSet<Category> Categories {get; set; }
Din pacate C# e un bulangiu si nu creeaza singur databaseul, asa ca trebuie sa il cream noi folosind SQL din command window din visual studio.
Bun. In controllerul nostru, trebuie sa avem o instanta a acelui ArticolDBContext:
ArticolDBContext db = new ArticolDBContext();
Il vom folosi ca sa accesam chestii din baza de date si sa le punem in ViewBag:
El foloseste un fel de pseudo-sql:
var articles = from article in db.Articles select article;
E o mizerie dar asta e _=)_/
Un model (clasa .cs) poate sa aiba o relatie cu alt tabel. Daca un PANDA are un REED, atunci REED are:
[ForeignKey("Panda")]
public int PandaId {get; set;}
public Panda Panda {get; set;}
Iar PANDA are:
public ICollection<Reed> Reeds {get; set;}
Il adaugam cu db.Pandas.
Setup:
App_Data > Add > Sql Server Database > Orice nume
-
Creeaza tabelul respectiv:
Dublu click pe databaseul tocmai creeat > Tables > Create table
CREATE TABLE [dbo].[Pandas] ( [Name] VARCHAR(255) NOT NULL PRIMARY KEY, [Email] VARCHAR(255) NOT NULL, [Age] INT NOT NULL )
-
In Web.config de jos de tot din proiect, adauga asta si modifica acel PandaConnectionString sa matchuiasca cum e in DbContextul tau SI pathul catre database!
<connectionStrings> <add name="PandaConnectionString" providerName="System.Data.SqlClient" connectionString="Data Source=(LocalDB)\MSSQLLocalDB;AttachDbFilename=C:\Users\Dave\source\repos\Lab6\Lab6\App_Data\MySqlDatabase.mdf;Integrated Security=True"/> </connectionStrings>
Note: Ai grija sa ai facut setupul cum trebuie!
db.Pandas.Add(panda);
db.SaveChanges();
from panda in db.Pandas
orderby panda.Name
select panda;
Sau
db.Pandas.Find(name)
if (TryUpdateModel(student)) {
student.Name = requestStudent.Name;
student.Email = requestStudent.Email;
student.CNP = requestStudent.CNP;
student.City = requestStudent.City;
db.SaveChanges();
}
Pentru setup, vezi Complete project setup mai jos.
Ca sa restrictionam accesul userului laun controller/view, punem un annotation:
[Authorize(Roles = "Administrator")]
- Create Project
Project: FIle > New > Project > ASP.NET Web Application (.NET Framework) > MVC, Change Authentication > Individual User Accounts > OK
- Setup la Identity Framework
-
In App_Start/Startup.Auth.cs, paste this DUPA cele 3 randuri cu
app.CreatePerOw...
:app.CreatePerOwinContext<ApplicationRoleManager>(ApplicationRoleManager.Create);
-
In App_Start/IdentityConfig.cs, adaugam asta:
public class ApplicationRoleManager : RoleManager<IdentityRole> { public ApplicationRoleManager(IRoleStore<IdentityRole, string> store) : base(store){} public static ApplicationRoleManager Create(IdentityFactoryOptions<ApplicationRoleManager> options, IOwinContext context) { var roleStore = new RoleStore<IdentityRole>(context.Get<ApplicationDbContext>()); return new ApplicationRoleManager(roleStore); } }
-
In Startup.cs, adaugam astea:
public void Configuration(IAppBuilder app) { ConfigureAuth(app); // Se apeleaza o metoda in care se adauga contul de administrator si rolurile aplicatiei createAdminUserAndApplicationRoles(); } private void createAdminUserAndApplicationRoles() { ApplicationDbContext context = new ApplicationDbContext(); var roleManager = new RoleManager<IdentityRole>(new RoleStore<IdentityRole>(context)); var UserManager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(context)); // Se adauga rolurile aplicatiei if (!roleManager.RoleExists("Administrator")) { // Se adauga rolul de administrator var role = new IdentityRole(); role.Name = "Administrator"; roleManager.Create(role); // se adauga utilizatorul administrator var user = new ApplicationUser(); user.UserName = "[email protected]"; user.Email = "[email protected]"; var adminCreated = UserManager.Create(user, "Administrator1!"); if (adminCreated.Succeeded) { UserManager.AddToRole(user.Id, "Administrator"); } } if (!roleManager.RoleExists("Editor")) { var role = new IdentityRole(); role.Name = "Editor"; roleManager.Create(role); } if (!roleManager.RoleExists("User")) { var role = new IdentityRole(); role.Name = "User"; roleManager.Create(role); } }
-
Install Entity Framework (if not installed automatically)
Tools > NuGet Package manager > Manage NuGet Packages For Solution > Cauta Entity Framework and install it
-
Create Controller
Controllers > Right Click > New Controller > PandaController.cs
-
Create Model
Models > Add > Class > Panda.cs
-
In IdentityModels.cs, adaugam un collection de Pandala ApplicationDbContext:
public DbSet<Panda> Pandas { get; set; }
-
Adauga un database:
App_Data > Add > Sql Server Database > Orice nume
-
Creeaza tabelul respectiv:
Dublu click pe databaseul tocmai creeat > Tables > Create table
CREATE TABLE [dbo].[Pandas] ( [Name] VARCHAR(255) NOT NULL PRIMARY KEY, [Email] VARCHAR(255) NOT NULL, [Age] INT NOT NULL )
-
In Web.config de jos de tot din proiect, adauga asta si modifica acel PandaConnectionString sa matchuiasca cum e in DbContextul tau SI pathul catre database!
`
-
-
Create View
- In PandaController, add o functie Index:
public ActionResult Index(){ return View(); }
-
Views > Panda > Add > View > Index.cshtml
- In PandaController, add o functie Index:
[Authorize(Roles = "User,Editor,Administrator")]
var g = db.Albums.Find(id);
var query = "SELECT * FROM albums WHERE AlbumId = (SELECT MAX (AlbumId) FROM albums); ";
Album maxIDalbum = db.Albums.SqlQuery(query).FirstOrDefault();
ViewBag.ConversationMessages = db.ConversationMessages.Where(x => x.ConversationId == id).OrderBy(x => x.Timestamp);
User.Identity.GetUserId()
db.Conversations.Add(convo);
db.SaveChanges();
public ActionResult Edit(int id, Album elem)
[ForeignKey("UserId")]
public virtual ApplicationUser User { get; set; }
[DatabaseGenerated(DatabaseGeneratedOption.None)]
<form method="post" action="/Conversation/New">
@Html.Hidden("UserId", User.Identity.GetUserId())
@Html.Label("Username", "I want to talk to... (username)")
@Html.TextBox("Username", null, new { @class = "form-control" })
<button type="submit">Talk now!</button>
</form>
Ciclul de viata al unei pagini web - Cursul 1 Arhitectura MVC - Cursul 2