ASP.NET MVC 一些点

View 部分是简单的 HTML 代码, Controller 是简单的 .NET 类ASP.NET MVC的请求流程如下:
  • 触发 Controller
  • 依据行为 Controller 创建 Model 对象, Model 反过来通过调用数据接口层来向 Model对象填充数据
  • 填充完的 Model 对象将数据传输给 View 层, 然后展示出来
  • 控制器类的命名一定要含有 Controller 关键字, 含有 Controller 的是一个类名称, 不含的则是控制器名称Action 则是控制器里的一个 public 的方法, 非 public 方法不能被 Web 调用, 如果需要实现 public 的非 Action 方法则需要给方法加上 [NonAction] 注解, 注意该方法的返回类型, 如果是类的话则会返回ToString()方法的返回值IIS 访问时使用的 URL 是 ${ControllerName}/${ActionName}, 注意 ${ControllerName} 不含关键字Controller在 Action 上右击则可使用 VS 创建 View, View 总是与特定的 Controller 相关联被放到一个特殊的文件夹中(Views/${ControllerName}), View 只有放在正确的文件夹下才能被 Controller 访问, 而 Views/Shared 文件夹下的视图是所有控制器可以共用的View 的作用是创建 ViewResult 对象, 无参调用 View 函数将自动通过 ActionName 来查找视图
  • ViewResult 内部创建 ViewPageActivator 对象
  • ViewResult 选择正确的 ViewEngine,并将 ViewPageActivator 对象作为参数传输给 ViewEngine 构造函数
  • ViewEngine 创建 View 类的对象
  • ViewResult 调用 View 类的 RenderView 方法
  • ActionResult 是一个抽象类, ViewResultBaseActionResult 的子类, 而 ViewResultViewResultBase 的子类ViewResult 呈现了一个完整的 HTML 响应, 而 ContentResult 呈现的是一个纯文本响应, 就像返回一个纯 String 类型意义, 所不同的是, ContentResult 是一个 ActionResult 的子类型, 包装 String 结果ViewData 是一个字典, 它存储了 Controller 传输给 View 的数据(以 Object 类型, 所以取出时需要强制类型转换), Controller 将向 ViewData 字典添加条目, 然后 View 从这个字典里读取, 一个例子如下
  • Model 中定义数据类型:
  • // Models/Employee.cs namespace WebDemo.Models { public class Employee { public string FirstName { set; get; } public string LastName { set; get; } public int Salary { set; get; } } }
  • Controller 中添加数据:
  • // Controllers/TestController.cs using System.Web.Mvc; using WebDemo.Models; namespace WebDemo.Controllers { public class TestController : Controller { public ActionResult GetView() { Employee employee = new Employee(); employee.FirstName = "Sukesh"; employee.LastName = "Marla"; employee.Salary = 20000; ViewData["Employee"] = employee; return View("MyView"); } } }
  • View 中取出并呈现数据(两种方法):
  • <!-- Views/Test/MyView.cshtml --> @{ Layout = null; } <!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width" /> <title>MyView</title> </head> <body> @{ WebDemo.Models.Employee employee = (WebDemo.Models.Employee)ViewData["Employee"]; } <b>Employee Details:</b> <br/> Employee Name: @(employee.FirstName + " " + employee.LastName) <br/> Employee Salary: @employee.Salary.ToString("C"); @{ Response.Write(employee.FirstName + " " + employee.LastName + "rn" + employee.Salary); } </body> </html>之后访问 http://localhost:${portNum}/Test/GetView 进行访问, 值得注意的是, 输出中 Response.Write 的数据在最开始View 层代码中 @ 后有 {} 则可用于 CSharp 代码, 否则只用于展示变量或者表达式的值ViewBag 类似于 ViewData 的语法糖, 添加了动态特征, 两者可以混合使用, 使用方法是:
  • Controller 代码中添加数据
  • ViewBag.Employee = employee;
  • View 中进行解析
  • WebDemo.Models.Employee employee = (WebDemo.Models.Employee)ViewBag.Employee;ViewDataViewBag 传输类型都是 Object, 强制类型转换会有性能问题, Key 值不正确会导致运行时出错, 前后端分离不优雅, Views 可以使用强类型一定程度解决上面三个问题使用强类型 Views 的方法如下:
  • Model 层与上方的一致, 使用 Employee
  • Controller 中添加数据, 注意这里不再使用 ViewData 或 ViewBag 而是通过 View 进行传递
  • // Controllers/TestController.cs using System.Web.Mvc; using WebDemo.Models; namespace WebDemo.Controllers { public class TestController : Controller { public ActionResult GetView() { Employee employee = new Employee(); employee.FirstName = "Sukesh"; employee.LastName = "Marla"; employee.Salary = 20000; return View("MyView", employee); } } }
  • 指定 View 成为某个类型的强类型视图, 并使用相应数据, 注意首行的 @model ${className} 用于指定强类型视图, 一个 View 只能指定一个 model, 需要使用 Controller 中数据的时候直接使用 @Model.${attributeName}
  • <!-- Views/Test/MyView.cshtml --> @model WebDemo.Models.Employee @{ Layout = null; } <!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width" /> <title>MyView</title> </head> <body> <b>Employee Details:</b> <br /> Employee Name: @Model.FirstName @Model.LastName @if (Model.Salary > 15000) { <span style="background-color:yellow"> Employee Salary: @Model.Salary.ToString("C") </span> } else { <span style="background-color:green"> Employee Salary: @Model.Salary.ToString("C") </span> } </body> </html>ViewModel 是 MVC 应用中没有声明出的层, 适用于 Model 和 View 之间并且为 View 作为一个数据容器, Model 特指业务数据, 它基于业务和数据结构创建, ViewModel 特指 View 数据, 它基于视图 View 创建, View 将会是一个以 ViewModel 为强类型的视图, 但是实际上就是将 Model 多封装了一层(这样就可以使用多 Model), 在原始的业务数据之上加上了其他的所需数据并将需要在 View 层中使用的逻辑也移动到 ViewModel 层中, 数据与显示的解耦和与冗余, 增加了设计的弹性, 一个例子:
  • Model 层仍然不变, 使用上方的 Employee
  • 新建一个 ViewModels 文件夹并新建一个 ViewModel 类
  • // ViewModels/EmployeeViewModel.cs namespace WebDemo.ViewModels { public class EmployeeViewModel { // 处理 Model 中的数据 public string EmployeeName { get; set; } public string Salary { get; set; } // 处理 View 中的逻辑 public string SalaryColor { get; set; } // 添加无关数据 public string UserName { get; set; } } }
  • Controller 层中实际上是对 Model 多了一层封装
  • // Controllers/TestController.cs using System.Web.Mvc; using WebDemo.Models; using WebDemo.ViewModels; namespace WebDemo.Controllers { public class TestController : Controller { public ActionResult GetView() { // Model 层 Employee employee = new Employee(); employee.FirstName = "Sukesh"; employee.LastName = "Marla"; employee.Salary = 20000; // ViewModel层 EmployeeViewModel employeeViewModel = new EmployeeViewModel(); employeeViewModel.EmployeeName = employee.FirstName + " " + employee.LastName; employeeViewModel.Salary = employee.Salary.ToString("C"); if (15000 > employee.Salary) { employeeViewModel.SalaryColor = "green"; } else { employeeViewModel.SalaryColor = "yellow"; } employeeViewModel.UserName = "Admin"; return View("MyView", employeeViewModel); } } }
  • View 层中还是使用原有的方法, 只不过使用了其他数据源
  • <!-- Views/Test/MyView.cshtml --> @using WebDemo.ViewModels @model EmployeeViewModel @{ Layout = null; } <!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width" /> <title>MyView</title> </head> <body> Hello @Model.UserName <hr /> <div> <b>Employee Details</b> Employee Name: @Model.EmployeeName <br /> <span style="background-color:@Model.SalaryColor"> Employee Salary: @Model.Salary </span> </div> </body> </html>

    相关内容推荐