9. 表单处理与提交
9.1 创建表单视图
在视图文件夹下创建一个用于创建产品的视图,如 Create.cshtml
:
html
@model YourNamespace.Product
@{
ViewBag.Title = "创建产品";
}
<h2>创建产品</h2>
@using (Html.BeginForm())
{
@Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>产品信息</h4>
<hr />
@Html.ValidationSummary(true, "", new { @class = "text-danger" })
<div class="form-group">
@Html.LabelFor(model => model.Name, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.Name, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.Name, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.Price, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.Price, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.Price, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="创建" class="btn btn-default" />
</div>
</div>
</div>
}
<div>
@Html.ActionLink("返回列表", "Index")
</div>
这个视图使用 Razor 语法创建了一个表单,用于输入产品的名称和价格,并提供了提交按钮。
9.2 处理表单提交
在控制器中添加处理表单提交的方法:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "Name,Price")] Product product)
{
if (ModelState.IsValid)
{
db.Products.Add(product);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(product);
}
这个方法使用 [HttpPost]
特性来处理 POST 请求,使用 [ValidateAntiForgeryToken]
来防止跨站请求伪造。如果模型验证通过,将产品添加到数据库并保存更改,然后重定向到产品列表页面;否则,返回创建视图并显示错误信息。
10. 控制器中的动作方法
10.1 动作方法的返回类型
- ViewResult :返回一个视图。例如
return View();
或return View(model);
。 - RedirectToRouteResult :重定向到另一个路由。例如
return RedirectToAction("Index", "Product");
。 - JsonResult :返回 JSON 数据。例如
return Json(data, JsonRequestBehavior.AllowGet);
。 - ContentResult :返回纯文本内容。例如
return Content("Hello, World!");
。
10.2 动作方法的参数绑定
动作方法可以接收不同类型的参数,如简单类型(int
、string
等)、复杂类型(模型类)和路由数据。例如:
csharp
public ActionResult Details(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Product product = db.Products.Find(id);
if (product == null)
{
return HttpNotFound();
}
return View(product);
}
这个方法接收一个可选的 int
类型的 id
参数,用于查找并显示特定产品的详细信息。
11. 视图引擎与 Razor 语法
11.1 视图引擎
ASP.NET MVC 默认使用 Razor 视图引擎。视图引擎负责将视图文件转换为 HTML 页面。可以通过配置文件或代码来切换视图引擎。
11.2 Razor 语法
- 表达式 :使用
@
符号输出表达式的值。例如@DateTime.Now
输出当前时间。 - 代码块 :使用
@{ ... }
包含代码块。例如:
html
@{
var message = "Hello, Razor!";
}
<p>@message</p>
- 条件语句和循环语句 :可以在视图中使用
if
、for
、foreach
等语句。例如:
html
@if (Model.Count > 0)
{
<ul>
@foreach (var item in Model)
{
<li>@item.Name</li>
}
</ul>
}
else
{
<p>没有数据。</p>
}
12. 过滤器
12.1 过滤器的类型
- 授权过滤器 :用于验证用户是否有权限访问某个动作方法。例如
[Authorize]
特性。 - 动作过滤器:在动作方法执行前后执行代码。可以自定义动作过滤器类。
- 结果过滤器:在动作结果执行前后执行代码。
- 异常过滤器:在发生异常时执行代码,用于处理错误。
12.2 自定义过滤器
以下是一个自定义动作过滤器的示例:
csharp
public class CustomActionFilterAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
// 在动作方法执行前执行的代码
filterContext.HttpContext.Response.Write("动作方法即将执行...<br />");
base.OnActionExecuting(filterContext);
}
public override void OnActionExecuted(ActionExecutedContext filterContext)
{
// 在动作方法执行后执行的代码
filterContext.HttpContext.Response.Write("动作方法已执行。<br />");
base.OnActionExecuted(filterContext);
}
}
可以在控制器或动作方法上使用这个过滤器:
csharp
[CustomActionFilter]
public ActionResult Index()
{
return View();
}
13. 依赖注入与服务定位
13.1 依赖注入的概念
依赖注入(DI)是一种设计模式,用于解耦对象之间的依赖关系。在 ASP.NET MVC 中,可以使用依赖注入来管理控制器的依赖项。
13.2 使用依赖注入
可以使用第三方依赖注入容器,如 Autofac 或 Microsoft.Extensions.DependencyInjection。以下是使用 Microsoft.Extensions.DependencyInjection 的示例:
csharp
// 在 Startup.cs 中配置依赖注入
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<ProductContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
services.AddControllersWithViews();
}
然后在控制器中使用构造函数注入:
csharp
public class ProductController : Controller
{
private readonly ProductContext _db;
public ProductController(ProductContext db)
{
_db = db;
}
// 动作方法...
}
14. 测试 MVC 应用程序
14.1 单元测试
可以使用单元测试框架,如 NUnit 或 MSTest,对控制器和模型进行单元测试。例如,测试控制器的动作方法:
[Test]
public void Index_ReturnsAViewResult_WithAListOfProducts()
{
// Arrange
var mockDb = new Mock<ProductContext>();
var products = new List<Product>
{
new Product { Id = 1, Name = "产品1", Price = 10.0m },
new Product { Id = 2, Name = "产品2", Price = 20.0m }
};
mockDb.Setup(m => m.Products).Returns(products.AsQueryable());
var controller = new ProductController(mockDb.Object);
// Act
var result = controller.Index() as ViewResult;
// Assert
Assert.IsNotNull(result);
var model = result.Model as List<Product>;
Assert.IsNotNull(model);
Assert.AreEqual(2, model.Count);
}
14.2 集成测试
集成测试用于测试多个组件之间的交互,如控制器、视图和数据库。可以使用 Selenium 等工具进行端到端测试。
15. 部署与发布
15.1 发布到 IIS
可以使用 Visual Studio 的发布功能将应用程序发布到 Internet Information Services (IIS)。在发布配置中选择目标服务器和发布方式,然后点击 "发布" 按钮。
15.2 发布到云服务
也可以将应用程序发布到云服务,如 Azure 或 AWS。这些云服务提供了方便的部署和管理工具。
通过以上内容,你对 ASP.NET MVC 有了更深入的了解,可以进一步开发复杂的 Web 应用程序。记得在实际开发中不断实践和探索,以掌握更多的技巧和最佳实践。