十年河东,十年河西,莫欺少年穷
学无止境,精益求精
上一节中,学习了NetCore 的web应用程序,因为Cshtml页面自带.Cs文件,所以类似于微软早期的webForm应用。
本节一起学习NetCore 的MVC模式,如下,新建一个项目:
首先在Home控制器中添加如下控制器:
public string Welcome(string name, int ID = 1) { return HtmlEncoder.Default.Encode($"Hello {name}, ID: {ID}"); }
运行项目,如下:
返回一串字符串,注意这里的 HtmlEncoder.Default.Encode() 方法,用于字符串编码,能防止JavaScript攻击,即防止XSS攻击,如果在Url中存在汉字,将会被编码。
首先准备数据库数据,如下:
1、新建一个数据库,命名为:MovieDB
2、创建一张表,命名为:Movie
脚本如下:
create table Movie ( ID int identity(1,1) primary key, Title nvarchar(200), ReleaseDate datetime, Genre varchar(200), Price decimal(18,2) )
数据库创建完毕,我们插入一条数据:
insert into [MovieDB].[dbo].[Movie] values('战狼2',getdate(),'影视媒体',18)
数据库准备完毕,
...
现在准备C#的Model 、数据库访问上下文 、及数据库链接字符串
1、在项目 Models 文件夹中添加Movie类:
public class Movie { public int Id { get; set; } public string Title { get; set; } [DataType(DataType.Date)] public DateTime ReleaseDate { get; set; } public string Genre { get; set; } public decimal Price { get; set; } }
2、添加数据访问上下文类:
using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Microsoft.EntityFrameworkCore; namespace MvcMovie.Data { public class MvcMovieContext : DbContext { public MvcMovieContext(DbContextOptions<MvcMovieContext> options) : base(options) { } public DbSet<MvcMovie.Models.Movie> Movie { get; set; } } }
3、在 appsettings.json 中添加链接字符串,如下:
{ "Logging": { "LogLevel": { "Default": "Warning" } }, "AllowedHosts": "*", "ConnectionStrings": { "MvcMovieContext": "Data Source=DESKTOP-VD79APR\SQLEXPRESS;Initial Catalog=MovieDB;Integrated Security=True" } }
4、在 StartUp类中注册上下文服务,如下:
public void ConfigureServices(IServiceCollection services) { services.Configure<CookiePolicyOptions>(options => { // This lambda determines whether user consent for non-essential cookies is needed for a given request. options.CheckConsentNeeded = context => true; options.MinimumSameSitePolicy = SameSiteMode.None; }); services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1); services.AddDbContext<MvcMovieContext>(options => options.UseSqlServer(Configuration.GetConnectionString("MvcMovieContext"))); }
至此:C#配置数据库部分就搞定了。
但是,可恶的微软提供的VS2017 采用的NetCore框架的版本是2.1.1,在这个框架下,无法添加控制器和视图...
所以我的本篇博客似乎只能到此为止了...呜呜,查了相关资料,也没能找到相关的解决方法。
添加控制器时,会报错,如下:
添加视图时。也会报错:
后来,没有放弃得我,关闭VS后,重新打开,就可以了。ののののののののののののののののののののののののののののののの
奇葩的VS就是这么神奇。
OK,添加控制器和视图的问题解决了,现在我们就添加相关控制器:MovieController 并 采用模板的形式添加视图,如下截图:
右键项目,选择:添加/新搭建基架的项目...如下:
并选择我们之前创建的上下文类及Model类,如下:
至此,我们项目针对数据表Movie的增删改查视图就构造完成了。运行项目如下:
CS 代码如下:
using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Rendering; using Microsoft.EntityFrameworkCore; using MvcMovie.Data; using MvcMovie.Models; namespace MvcMovie { public class MoviesController : Controller { private readonly MvcMovieContext _context; public MoviesController(MvcMovieContext context) { _context = context; } // GET: Movies public async Task<IActionResult> Index() { return View(await _context.Movie.ToListAsync()); } // GET: Movies/Details/5 public async Task<IActionResult> Details(int? id) { if (id == null) { return NotFound(); } var movie = await _context.Movie .FirstOrDefaultAsync(m => m.Id == id); if (movie == null) { return NotFound(); } return View(movie); } // GET: Movies/Create public IActionResult Create() { return View(); } // POST: Movies/Create // To protect from overposting attacks, please enable the specific properties you want to bind to, for // more details see http://go.microsoft.com/fwlink/?LinkId=317598. [HttpPost] [ValidateAntiForgeryToken] public async Task<IActionResult> Create([Bind("Id,Title,ReleaseDate,Genre,Price")] Movie movie) { if (ModelState.IsValid) { _context.Add(movie); await _context.SaveChangesAsync(); return RedirectToAction(nameof(Index)); } return View(movie); } // GET: Movies/Edit/5 public async Task<IActionResult> Edit(int? id) { if (id == null) { return NotFound(); } var movie = await _context.Movie.FindAsync(id); if (movie == null) { return NotFound(); } return View(movie); } // POST: Movies/Edit/5 // To protect from overposting attacks, please enable the specific properties you want to bind to, for // more details see http://go.microsoft.com/fwlink/?LinkId=317598. [HttpPost] [ValidateAntiForgeryToken] public async Task<IActionResult> Edit(int id, [Bind("Id,Title,ReleaseDate,Genre,Price")] Movie movie) { if (id != movie.Id) { return NotFound(); } if (ModelState.IsValid) { try { _context.Update(movie); await _context.SaveChangesAsync(); } catch (DbUpdateConcurrencyException) { if (!MovieExists(movie.Id)) { return NotFound(); } else { throw; } } return RedirectToAction(nameof(Index)); } return View(movie); } // GET: Movies/Delete/5 public async Task<IActionResult> Delete(int? id) { if (id == null) { return NotFound(); } var movie = await _context.Movie .FirstOrDefaultAsync(m => m.Id == id); if (movie == null) { return NotFound(); } return View(movie); } // POST: Movies/Delete/5 [HttpPost, ActionName("Delete")] [ValidateAntiForgeryToken] public async Task<IActionResult> DeleteConfirmed(int id) { var movie = await _context.Movie.FindAsync(id); _context.Movie.Remove(movie); await _context.SaveChangesAsync(); return RedirectToAction(nameof(Index)); } private bool MovieExists(int id) { return _context.Movie.Any(e => e.Id == id); } } }
具体的代码及相关知识,会在此系列博客中详解,今天只是尝试着搭建一个NETCore MVC 项目。
至此,项目搭建完毕,谢谢。
@天才卧龙的博客