BIT 286: Web Applications Lecture 04: Thursday, January 15, 2015 ASP.Net MVC - Models 2 First Steps With Model https://docs.asp.net/en/latest/tutorials/ first-mvc-app/adding-model.html If you copy and paste the above you’ll get a 404 because of the newline after tutorials/ delete the space (or the %20, once you’re looking at the 404) and try again. Setting up the POCO / POJO, managed DB access Custom connection (to LocalDB, but could be to elsewhere) Scaffolding: Free CRUD! Examining the index page 3 EF sets up your DB with “Code First” “The Entity Framework (often referred to as EF) supports a development paradigm called Code First. Code First allows you to create model objects by writing simple classes. (These are also known as POCO classes, from "plain-old CLR objects.") You can then have the database created on the fly from your classes, which enables a very clean and rapid development workflow.” –Getting Started With MVC Database first is still an option 4 C# Class definition Create a plain old CLR object (a normal class) in the Models folder public class Movie { private int numDoors = 4; public int GetNumDoors() { return numDoors; } public void SetNumDoors(int nD) { numDoors = nD; } public int ID { get; set; } public string Title { get; set { if( value == “”) throw new Exception(“blah”); else Title = value; } public DateTime ReleaseDate { get; set; } public string Genre { get; set; } public decimal Price { get; set; } } These are C# Properties “We'll use the Movie class to represent movies in a database. Each instance of a Movie object will correspond to a row within a database table, and each property of the Movie class will map to a column in the table.” 5 Scaffolding CRUD CRUD = Create Read (examine individually, or list a bunch of them) Update Delete In the Controllers folder, Add Controller MVC 6 Controller with views, using Entity Framework Model Class: Movie Data context class: ApplicationDBContext “Visual Studio creates the following files and folders: A MoviesController.cs file in the Controllers folder. A Views\Movies folder. Create.cshtml, Delete.cshtml, Details.cshtml, Edit.cshtml, and Index.cshtml in the new Views\Movies folder.” 6 Creating the Database With luck, the directions behind the above link will work just fine They didn’t work for me. The problems were 1. The dnu/dnvm/dnx software wasn’t installed AND/OR 2. The dnu/dnvm/dnx software wasn’t added to the path For an explanation about what dnu/dnvm/dnx are: http://www.codeproject.com/Articles/1005145/DNVM-DNX-and-DNUUnderstanding-the-ASP-NET-Runtime Creating the Database: 7 Installing dnvm, etc Run this to install dnvm (DotNet Version Manager): @powershell -NoProfile -ExecutionPolicy unrestricted Command "&{$Branch='dev';iex ((new-object net.webclient).DownloadString('https://raw.githubusercont ent.com/aspnet/Home/dev/dnvminstall.ps1'))}“ This will copy the files into C:\Users\<your name>\.dnx\bin Then cd to C:\Users\<your name>\.dnx\bin so that you can use the dnvm program there. Creating the Database: 8 Installing dnvm, etc Then run dnvm setup If that doesn’t work try dnvm.cmd setup – it might not work without the .cmd extension This seems to add the dnvm.cmd program to your path If not, add it manually This page has a good explanation – look for the “Via Control Panel” section Add this to your PATH: C:\Users\<your name>\.dnx\bin; Don’t forget the ; - it’s what separates this entry from the next one Skip the dnu restore, the do the remainder: dnvm.cmd use 1.0.0-rc1-update1 -p dnx ef migrations add Initial dnx ef database update 9 Take it for a spin http://localhost:58381/Movies/ Index lists all the objects, in a nifty table You can ‘Create New’ to add objects This won’t add unless you get the date format exactly right (and there’s no feedback when you get it wrong ) 1/1/2016 should work For each object you can: View details (a specific page with the same info, but bigger layout) Edit the object Delete the object Ways to use this: Consulting: generate pages to demonstrate basic stuff to the client Start here, then go back and modify the HTML / etc so that it actually looks nice 10 Examining the Details page The ViewData thing was convenient… … but also error-prone (there’s no way for the compiler to check that any given field will actually exist when executing the View) A “Strongly typed” approach would be better At compile-time we use an object from a specific class Now compiler can check (in the View) if a given method/property actually exists public ActionResult Details(int? id) 11 { if (id == null) Examining the Details page { return HttpNotFound(); } Movie movie = _context.Movie.Single(m => m.ID == id); if (movie == null) { return HttpNotFound(); } } return View(movie); This is like SELECT * FROM <MoviesTable> WHERE <id matches> Note that we’re now passing this specific object to the View. 12 Examining the Details’ VIEW page @model WebApplication2.Models.Movie @{ViewData["Title"] = "Details";} This where we tell the <h2>Details</h2> view which C# type <div> to expect <h4>Movie</h4> This will print out the <hr /> field’s name. <dl class="dl-horizontal"> (In this case, ‘Genre’ <dt> @Html.DisplayNameFor(model => model.Genre) </dt> <dd> This will print out the field’s value. (For example ‘Comedy’) @Html.DisplayFor(model => model.Genre) 13 Examining • the Details’ VIEW page These are lambda expressions. Essentially they’re implied, local, “micro” functions. <dl class="dl-horizontal"> <dt> @Html.DisplayNameFor(model => model.Genre) </dt> <dd> @Html.DisplayFor(model => model.Genre) model => model.Genre 14 Lambda Functions (Brief Overview) This is actually a very concise function definition. You can think of this as saying something like: public string MyNewLambdaFnx(Movie model) { return model.Genre; } UNLIKE a normal method, you can pass a lambda function as a parameter (i.e., you can treat it kinda like data) UNLIKE a normal method, these are ‘anonymous’ there’s no actual name for the function More info at https://msdn.microsoft.com/enus/library/bb397687.aspx 15 Examining the Index page public class MoviesController : Controller { private ApplicationDbContext _context; public MoviesController(ApplicationDbContext context) This object connects { _context = context; } to the database // GET: Movies public IActionResult Index() { return View(_context.Movie.ToList()); } This is like ‘SELECT *” In the controller file: 16 Examining the Index page public IActionResult Index() { return View(_context.Movie.ToList()); } In the view file: @model IEnumerable<WebApplication2.Models.Movie> // Stuff left out… @foreach (var item in Model) { <tr><td> @Html.DisplayFor(modelItem => item.Genre) </td><td> @Html.DisplayFor(modelItem => item.Title) </td>