ASP.Net:(6)MVC编程入门指南
1.MVC项目创建
1.1 新建一个ASP.NET Web应用程序项目
在VS2015中,通过文件 -> 新建 -> 项目,弹出新建项目窗体,如下图。在左侧模板选中Visual C#下的Web,右侧选中ASP.NET Web应用程序,窗体底部输入项目名称和解决方案名称,选择项目存放位置,点击下一步继续。
1.2 选择MVC模板
在弹出的选择模板窗体,选中MVC,点击确定即完成项目创建。
2.MVC路由
2.1 注册路由
打开项目根目录下的全局应用程序类Global.asax,可以看到在Application_Start中完成了路由的注册:RouteConfig.RegisterRoutes(RouteTable.Routes)。
路由注册方法只被Application_Start方法调用一次,静态方法、静态变量保证每次请求都能有效。
转到RouteConfig.RegisterRoutes,可以查看其内部的已经提供了一个默认的路由。
其中:
name: "Default", //Default是这个路由的名称
url: "{controller}/{action}/{id}" //路由的规则
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
//缺省情况下,访问Home控制器下的Index这个Action,id的值从Url中获取,且是可选的,即可不传入。
没有id参数时,http://localhost:2575/ 等效于 http://localhost:2575/Home/Index
有id参数时,使用完整路由,如http://localhost:2575/Home/Index/2
2.2 注册多个路由
2.2.1 添加路由注册
在RouteConfig.RegisterRoutes中添加routes.MapRoute代码即可,如下添加了名为List和Item的两个路由:
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Default",
...
);
routes.MapRoute(
name: "List",
url: "{controller}/{action}/{section}/{category}",
defaults: new { controller = "Article", action = "List", section = UrlParameter.Optional, category = UrlParameter.Optional}
);
routes.MapRoute(
name: "Item",
url: "{controller}/{action}/{section}/{id}/html",
defaults: new { controller = "Article", action = "Item", section = UrlParameter.Optional, id = UrlParameter.Optional}
);
}
2.2.2 测试路由访问
对Article控制器下List的实现:
// GET: Article/List/02/07
public ActionResult List(string section,string category)
{
ViewBag.Section = section;
ViewBag.Category = category;
return View();
}
视图代码:
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>List</title>
</head>
<body>
<h3>
文章列表数据
</h3>
<div>栏目:@ViewBag.Section</div>
<div>类别:@ViewBag.Category</div>
</body>
</html>
对Article控制器下Item的访问测试如下,代码略:
2.3 路由规则
注意:多种路由规则优先匹配前面的。
(1)伪静态的路由规则
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}.html",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
(2)2层路由规则
routes.MapRoute(
name: "Default",
url: "{controller}/{action}-{id}.html",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
(3)带命名空间的路由
routes.MapRoute(
name:"AdminControllers", // 路由名称
url:"Admin/{controller}/{action}/{id}", // 带有参数的 URL
defaults:new { controller = "Home", action = "Index", id = UrlParameter.Optional }, // 参数默认值
namespaces:new string[] { "Admin.Controllers" }//命名空间
);
(4)带约束规则的路由:
routes.MapRoute(
"RuleControllers",
"{controller}/{action}-{Year}-{Month}-{Day}}",
new { controller = "Home", action = "Index", Year = "2010", Month = "04", Day = "21" },
new { Year = @"^\d{4}", Month = @"\d{2}" } //4位数 2位数
);
第4行位约束规则,约束了参数Year为4位数,Month为2位数。
(5)捕获所有路由
routes.MapRoute(
"All", // 路由名称
"{*Vauler}", // 带有参数的 URL
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // 参数默认值
);
3.布局页
布局页的作用,相当于Asp.Net WebForm中的母板页。MVC中使用布局页的方法如下:
在Article控制器下写一个与Item实现完全一样的Action
public ActionResult LayoutItem(string section, int id)
{
ViewBag.Section = section;
ViewBag.Message = id.ToString();
return View();
}
创建视图时,选择使用布局文件:
生成的视图文件中,Layout这一项指定了布局页,且视图文件中不再包含html,head,body这些标签。
@{
ViewBag.Title = "LayoutItem";
Layout = "~/Views/Shared/_kl_layout.cshtml";
}
<div>栏目:@ViewBag.Section</div>
<div>
第<label>@ViewBag.Message</label>篇文章
</div>
页面效果如下:
4.区域
4.1 添加区域
项目的右键菜单中添加-区域,在弹出的窗体输入区域名称,点击“添加”按钮即可。
4.2 路由处理控制器重名
创建一个Article控制器,控制器中定义名为List的Action,实现与之前的Article控制器一样。
AdminAreaRegistration下RegisterArea方法中添加路由规则
context.MapRoute(
name: "Admin_List",
url: " Admin/{controller}/{action}/{section}/{category}",
defaults: new { controller = "Article", action = "List", section = UrlParameter.Optional, category = UrlParameter.Optional }
);
访问原来Article下的List时,报如下错误:
解决方案:在路由规则中添加命名空间,如下
context.MapRoute(
name: "Admin_List",
url: " Admin/{controller}/{action}/{section}/{category}",
defaults: new { controller = "Article", action = "List", section = UrlParameter.Optional, category = UrlParameter.Optional }
namespaces: new string[] { "Admin.Controllers" }//命名空间
);
5.控制器
5.1 控制器
5.1.2 控制器的跳转
RedirectToAction("Action name","Controller name");
return RedirectToAction("Index","Home");//跳转到首页。
第一个参数是action 的名字,第二个参数是控制器controller的名字,方法返回的是个ActionResult.也就是返回视图。
5.2 ActionResult及其子类对照表
ActionResult及其子类 |
说明 |
ViewResult |
表示HTML的页面内容 |
EmptyResult |
表示空白的页面内容 |
RedirectResult |
表示定位到另外一个URL |
JsonResult |
表示可以运用到AJAX程序中JSON结果 |
JavaScriptResult |
表示一个JavaScript对象 |
ContentResult |
表示一个文本内容 |
FileContentResult |
表示一个可以下载的、二进制内容的文件 |
FilePathResult |
表示一个可以下载的、指定路径的文件 |
FileStreamResult |
表示一个可以下载的、流式的文件 |
Controller中的方法 |
返回对象 |
View |
ViewResult |
Redirect |
RedirectResult |
RedirectToAction |
RedirectToActionResult |
RedirectToRoute |
RedirectToRouteResult |
Json |
JsonResult |
JavaScriptResult |
JavaScriptResult |
Content |
ContentResult |
File |
FileContentResult、FilePathResult、FileStreamResult |
5.3 为Action创建视图
在控制器的Action上点击右键,在右键菜单选择“添加视图”,即可弹出创建视图窗体。
如果是后台管理界面,可以选择根据创建、删除、编辑等选择相应的模板;同时可为该视图选择布局页:
6.视图
6.1 MVC传值
6.1.1 MVC视图引擎
Mvc3引用了一个新的视图引擎Razor,一个项目里面可同时支持aspx和Razor。
Razor引擎与aspx引擎语法格式对比(右侧是Razor引擎语法):写C#代码更简化。
6.1.2 ViewData传值
在Controller中定义如下:
ViewData[“Message”] = “Hello word!”;
在View中读取Controller中定义的ViewData数据,代码如下:
<% = Html.Encode(ViewData[“Message”]) %>
在Controller定义如下:
public ActionResult Index()
{
Article art = new Article();
art .Title = "标题";
art .content = "文章内容";
ViewData["hello"] = "hello!";
return View(art );
}
在View中读取,代码如下:
<% var user = this.ViewData.Model; %>
<%=user.Name %>
<%=user.Age %>
<% = Html.Encode(ViewData[“hello”]) %>
6.2 使用强类型数据
6.2.1 类型定义
namespace MvcApp.Models
{
public class UserInfo
{
public string Name { get; set; }
public int Id { get; set; }
public string Address { get; set; }
public string Phone { get; set; }
}
}
6.2.2 往前端传递强类型数据
控制器:
public ActionResult ShowUserInfo()
{
UserInfo userInfo = new UserInfo();
userInfo.Id = 2;
userInfo.Name = "<br/> ded";
userInfo.Phone = "dsfdsfs";
userInfo.Address = "公交站";
ViewData.Model = userInfo;
return View();
//或以上两行改为 return View(userInfo);
}
前台页面绑定:
<%@ Page Language="C#" Inherits="System.Web.Mvc.ViewPage<MvcApp.Models.UserInfo>" %>
<body>
<div>
<%: Model.Id %>
<span>
<%: Model.Name %>
</span>
</div>
<div>
@Model.Phone
</div>
</body>
6.2.3 前端向后台提交数据
(1)页面中的元素:
<div>
<form id="frmSubUser" method="POST" action="/UserInfo/Create">
姓名:<input type="text" name="Name"/><br/>
编号:<input type="text" name="Id"/><br/>
地址:<input type="text" name="Address"/><br/>
电话:<input type="text" name="Phone"/><br/>
<input type="submit" value="提交"/>
</form>
</div>
(2)控制器中的处理方法:
public ActionResult ProcessCreate(UserInfo user,string Id)
{
if(String.isNullOrEmpty(Id))
{
AddUser(user);
}
else
{
UpdateUser(user);
}
return Content("ok");
}
如果元素名称与参数名或参数的属性名相同,post过来的数据会自动组装到对应的参数或属性
6.2.4 MVC4版本写法
@using KL.CMS.Model
@model KL.CMS.Model.Dat_article
<h2 >@Model.Title</h2> <!--使用@Model输出文本-->
<div >@Html.DisplayFor(model => model.CreateTime)</div><!--使用@Html和@model输出文本-->
<div id="divcontent" class="col-md-10">@Html.Raw(Model.Content)</div> <!--输出原生html,而不是文本-->
6.3 HtmlHelper
6.3.0 HtmlHelper控件清单
Html.ActionLink
Html.RouteLink
Html.TextBox
Html.Hidden
Html.TextArea
Html.CheckBox
Html.ListBox
Html.DropDownList
Html.BeginForm
Html.EndForm
Html.Partial 在视图内加载部分视图,如:@Html.Partial("_LoginPartial")
6.3.1 超链接
如果路由规则会变化,使用一个url.Action()方法来得到与路由规则匹配的url地址:
也可以使用HtmlHelper类得到超链接:
6.3.2 Form表单及单值表单元素
6.3.3 多值表单元素RadioButton
@Html.RadioButton("Gender","1")
@Html.RadioButton("Gender","2")
@Html.RadioButton("Gender","3") <br/>
@Html.RadioButton("Sex","1")
@Html.RadioButton("Sex", "2")<br/>
6.3.4 多值表单元素DropDownList
(1)控制器
public class HomeController : Controller
{
public ActionResult Index()
{
ViewData["Message"] = "欢迎使用 ASP.NET MVC!";
ViewData["ddl"] = new List<SelectListItem>
{
new SelectListItem(){Selected = false,Text = "北京",Value = "2"},
new SelectListItem(){Selected = false,Text = "天津",Value = "3"},
new SelectListItem(){Selected = true,Text = "西红柿",Value = "4"},
};
return View();
}
}
(2)页面body中
@Html.DropDownList("ddl")<br/>
浏览页面即可显示控件及内容
6.4 Html编码处理
6.4.1 输出Html编码的字符串
即将字符串进行Html编码,让浏览器对其只做文本显示,而不作为Html解析和处理。
<% : %>语法相对于<%= %>,对后台的数据具有Html编码作用
<% : getString()%> 相当于以下这行
<%= Html.Encode(getString())%>
6.4.2 输出未经Html编码的字符串
即输出原生html,而不是文本。
在Razor Beta 2以前的版本可以:@(new HtmlString(mystring))
以后的版本可以:@Html.Raw(mystring)
6.5 表单验证
6.5.1 基本使用步骤
与Asp.Net中使用方式基本相同,无侵入方式的。
(1)引入jquery.js和jquery.validate.js;
(2)写好表单frmUser及表单元素;
(3)在$(function(){});函数中定义校验规则和错误提醒消息。
效果如下:
6.5.2 修改提醒消息的样式
修改类样式.error,将颜色改为红色,如下:
7.过滤器
7.1 过滤器介绍
有时候想在调用Action方法之前或者之后处理一些逻辑,为了支持这个,ASP.NET MVC允许你创建Filter。
Action过滤器是自定义的Attributes,用来标记添加Action方法之前或者Action方法之后的行为到控制器类中的Action方法中。这些逻辑可以是:
日志,异常处理
身份验证和授权
输出缓存
网络爬虫的过滤
防盗链
本地化
7.2 Action过滤器
public class FilterNameAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
//执行Action时
}
public override void OnActionExecuted(ActionExecutedContext filterContext)
{
//执行Action后
}
public override void OnResultExecuting(ResultExecutingContext filterContext)
{
//执行结果时
}
public override void OnResultExecuted(ResultExecutedContext filterContext)
{
//执行结果时后
}
}
[FilterName]
public ActionResult Index()
{
return View();
}
8.MVC调试:监视请求
8.1 MVC中设置启用跟踪
在页面Page指令中设置:Trace=”true”
8.2 浏览器中查看跟踪结果
F12开启开发人员工具监视
查看请求报文:
查看响应报文:
查看请求响应耗时:
9.MVC部署:连接问题
9.1 登录失败
报错信息:用户 'IIS APPPOOL\ASP.NET v4.0' 登录失败
因为程序连接SQLServer的连接字符串是用了windows集成登陆,可以改成用数据库帐号密码登陆。连接字符串的写法是:server=localhost;uid=sa;pwd=xxxx;database=master;
9.2 EF连接名已存在
修改连接字符串后,报如下错误。网上查到的说法可能是有重名的连接。
清缓存、重启、反复检查只有一个连接字符串,但始终报下面的错误:
The entry "TreasstockEntities" has already been added
加上一句:<remove name="Security"/>或者<clear/> 也没有任何效果。
没有办法了,既然提示连接名已经添加了,干脆重新生成一个名为“TreasstockEntity”的EF上下文,所有用到“TreasstockEntities”类的地方都改为“TreasstockEntity”。重新发布到IIS,刷新,数据成功显示,问题解决!
9.3 'ViewBag' does not exist
CS0103: The name 'ViewBag' does not exist in the current context
是因为View下的web.config文件被删除了,创建一个新的mvc项目,从中拷贝一个web.config过来,修改namespace为当前项目即可。