BIT 286: Web Applications Lecture 04: Thursday, January 15, 2015 ASP.Net MVC - 2 Examining the Edit Methods and Edit View https://docs.asp.net/en/latest/tutorials/ first-mvc-app/controller-methodsviews.html Using Entity Framework attributes to annotate model fields Using the Tag helpers (to generate path via routing) Postbacks 2nd method with bound object Redirecting Anti-forgery token using System; using System.ComponentModel.DataAnnotations; 3 using System.Data.Entity; namespace MvcMovie.Models Using EF attributes to better define DB table { public class Movie { public int ID { get; set; } public string Title { get; set; } [Display(Name = "Release Date")] // default was “ReleaseDate” [DataType(DataType.Date)] public DateTime ReleaseDate { get; set; } public string Genre { get; set; } public decimal Price { get; set; } } public class MovieDBContext : DbContext { public DbSet<Movie> Movies { get; set; } } } using System; using System.ComponentModel.DataAnnotations; 4 using System.Data.Entity; namespace MvcMovie.Models Using EF attributes to better define DB table { public class Movie { public int ID { get; set; } public string Title { get; set; } [Display(Name = "Release Date")] // default was “ReleaseDate” [DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)] public DateTime ReleaseDate { get; set; } public string Genre { get; set; } public decimal Price { get; set; } } public class MovieDBContext : DbContext { public DbSet<Movie> Movies { get; set; } } } 5 C# Attributes (aka “Annotations” in Java) “C# provides a mechanism for defining declarative tags, called attributes, which you can place on certain entities in your source code to specify additional information.” “Entities” – classes, methods, instance variables, etc. “The information that attributes contain can be retrieved at run time through reflection. You can use predefined attributes or you can define your own custom attributes. ” -MSDN NUnit used these ( [Test], [TestFixture], [Category], etc) 6 Date formats There’s a page for the DisplayFormat attribute According to the docs, this can use Various standard formatting codes for C#’s date&time types Custom formats (This is what the page is using) For example, "{0:dddd, MMMM d, yyyy}" will produce: Friday, January 1, 1999 7 Tag Helpers MVC 6 Anchor Tag Helper 8 In Views/Movies/Index.cshtml: <td> </td> <a asp-action="Edit" asp-route-id="@item.ID">Edit</a> | <a asp-action="Details" asp-route-id="@item.ID">Details</a> | <a asp-action="Delete" asp-route-id="@item.ID">Delete</a> This generates: <td> </td> <a href="/Movies/Edit/2">Edit</a> | <a href="/Movies/Details/2">Details</a> | <a href="/Movies/Delete/2">Delete</a> MVC 6 Anchor Tag Helper 9 In Views/Movies/Index.cshtml: <a asp-action="Edit" asp-route-id="@item.ID">Edit</a> This generates: <a href="/Movies/Edit/2">Edit</a> This actually builds the path based on the routing info in Startup.cs/Configure() Routes You can change your routing and all the links will change You can choose a different controller with asp-controller=“Product” You can pass parameters via asp-route-<PARAMETER NAME> Parameter must be specified in the route (in Startup.cs/Configure()) MVC 6 Anchor Tag Helper: Named Routes 10 “Another option is to specify the controller and action using a named route. For example, if your application had a route named login defined as follows in your MVC route configuration: routes.MapRoute( name: "login", template: "login", defaults: new { controller = "Account", action = "Login" }); then you can bind an anchor tag to that route as follows: <a asp-route="login">Login</a>” From http://www.davepaquette.com/archive/2015/06/01/mvc-6anchor-tag-helper.aspx#Named_Routes 11 WE STOPPED HERE on 5/2/2016 12 How does the Edit page work? Go to localhost:xxxx/Movies, then click on the ‘Edit’ link for something The URL in the browser will be something like http://localhost:54203/Movies/Edit/2 This is done using an HTTP GET request Change something, click ‘Save’ Browser needs to sends the changed data to the same URL but this time using a POST request http://www.w3schools.com/tags/ref_httpmethods.asp When the ‘Save’ works you’ll see the Index page again Controllers/MoviesController.cs 13 Look at // GET: Movies/Edit/5 public IActionResult Edit(int? id) { This is the action that gets executed when a GET request is made if (id == null) { return HttpNotFound(); } Movie movie = _context.Movie.Single(m => m.ID == id); if (movie == null) { return HttpNotFound(); } return View(movie); } Controllers/MoviesController.cs 14 Look at // POST: Movies/Edit/5 [HttpPost] [ValidateAntiForgeryToken] public IActionResult Edit(Movie movie) { if (ModelState.IsValid) { _context.Update(movie); _context.SaveChanges(); return RedirectToAction("Index"); } return View(movie); } This is the action that gets executed when a POST request is made Could mark the prior method with [HttpGet], but that’s not needed because that’s the default Controllers/MoviesController.cs 15 Look at // POST: Movies/Edit/5 [HttpPost] This will prevent Cross-Site Request Forgery (CSRF, aka XSS attack). [ValidateAntiForgeryToken] public IActionResult Edit(Movie movie) { if (ModelState.IsValid) { _context.Update(movie); _context.SaveChanges(); return RedirectToAction("Index"); } return View(movie); } Specifically, this attribute says to check the antiforgery token is the value that we gave to the browser (when it asked for the Edit form) CSRF / XSS Attack 16 XSS Attack: Customer logs into your web site, then visits another, malicious web site Malicious web site knows that the browser is storing login credentials & that it will send appropriate cookies back to your web site when browser next visits that site Malicious web site creates it’s own form to post to your website, and is logged in with your credentials Antiforgery Token: In addition to the cookie, ASP.Net will add a random number to each form (and it will save a copy for it’s later reference) The number is the token This is added in via <form asp-action="Edit"> When a form is submitted ASP.Net checks both the cookie (which the browser sends automatically) the token (the random number, which the malicious site cannot get) Controllers/MoviesController.cs 17 Look at // POST: Movies/Edit/5 [HttpPost] [ValidateAntiForgeryToken] public IActionResult Edit(Movie movie) { if (ModelState.IsValid) { _context.Update(movie); _context.SaveChanges(); return RedirectToAction("Index"); } return View(movie); } Checks if the information provided is valid This is done in the client for convenience, and in the server for security Controllers/MoviesController.cs 18 Look at // POST: Movies/Edit/5 [HttpPost] [ValidateAntiForgeryToken] public IActionResult Edit(Movie movie) { if (ModelState.IsValid) { _context.Update(movie); _context.SaveChanges(); return RedirectToAction("Index"); } return View(movie); } These lines save the information into the database. Controllers/MoviesController.cs 19 Look at // POST: Movies/Edit/5 [HttpPost] [ValidateAntiForgeryToken] public IActionResult Edit(Movie movie) { if (ModelState.IsValid) { _context.Update(movie); _context.SaveChanges(); return RedirectToAction("Index"); } return View(movie); } This will redirect the browser to the Index URL Controllers/MoviesController.cs 20 Look at // POST: Movies/Edit/5 [HttpPost] [ValidateAntiForgeryToken] public IActionResult Edit(Movie movie) { if (ModelState.IsValid) { _context.Update(movie); _context.SaveChanges(); return RedirectToAction("Index"); } return View(movie); } If the server was given invalid data, then direct the browser back to the Edit page 21 Older ways of generating links If you’re using MVC 5 then you don’t need the following, but it’s good to know about since it’s the way this stuff was done in the prior verion(s). 22 The Html helper class How to link from, say, the Index page to the Details page? In Views/Movies/Index.cshtml <td> @Html.ActionLink("Edit", "Edit", new { id=item.ID }) | @Html.ActionLink("Details", "Details", new { id=item.ID }) | @Html.ActionLink("Delete", "Delete", new { id=item.ID }) </td> 23 Html.ActionLink method @Html.ActionLink("Details", "Details", new { id=item.ID }) | First arg is the text to put on the page Second arg is the name of the method on this controller to link to Movies.Details Third arg is an anonymous object with info needed to build the path This actually builds the path based on the routing info in App_Data/RouteConfig.cs You can change your routing and all the links will change Details at MSDN There are other versions if you want to link to a different controller (e.g., back to the overall home page)