C#高级编程42章 MVC
42.1 ASP.NET MVC
路由机制 网络介绍链接
按照传统,在很多Web框架中(如经典的ASP、JSP、PHP、ASP.NET等之类的框架),URL代表的是磁盘上的物理文件。例如,当看到请求http://example.com/albums/list.aspx时,我们可以确定该站点目录结构中含有一个albums文件夹,并且在该文件夹下还有一个list.aspx文件。
URL和文件系统之间这种一一对应的关系并不适用于大部分基于MVC的Web框架,如ASP.NET MVC.一般来说,这些框架采用不同的方法将URL映射到某个类上的方法调用,而不是映射到磁盘上的物理文件。
另外,对于MVC应用程序,URL 请求到达的第一个组件是控制器而不是视图,而控制器是没有物理路径的
控制器方法不能重载
路由是从上到下的优先级的!所有
routes.MapRoute("showBlogRoute",
"blog/post/{id}",
new { controller =“CMS”,action = “Show”,id=“”});//如果参数2是POST,则匹配这一条显示这个控制器 routes.MapRoute("blogRoute",
“blog/{action}/{id}",
new { controller = "CMS", action = “Index", id = “”});//除名为POST的参数都显示这个方法 routes.MapRoute(“DefaultRoute”, // 路由名称
"{controller}/{action}/{id}", // 带有参数的 URL
new { controller = "Home", action = "Index", id =“”} // 参数默认值
);
如上代码反过来!则不会匹配到"blog/post/{id}",这一条,直接匹配最后一条
Constraints属性是一个包含针对URL参数的验证规则的字典,就是说,它是用来限定每个参数的规则或Http请求的类型的
使用正则表达式来定义约束,比如下面的例子,如果希望以正确的格式(只允许数字值)指定年月日(正则式)
routes.MapRoute("simple",
"archive/{year}/{month}/{day}",
new{controller="blog",action="search",year="",month="",day=""},
Constraints: new{
year=@"\d{2}|\d{4}",//只能是两位或四位数字,这里的year对应到url里的year
month=@"\d{1,2}",//只能使用一位或两位数字
day=@"\d{1,2}"//只能使用一位或两位数字
});
42.3创建控制器
42.3.2参数
一个参数
public ActionResult test(string name)
{
ViewBag.Message = "测试信息:" + name; //当打开http://localhost/Home/test?name=88832564时 name的值就等于88832564
return View();//<h3>@ViewBag.Message</h3>显示于ViewBag.Message的值
}
多个参数
public string test(int x ,int y)//取路由的参数值(id必须对应路由)
{
return "测试信息:" +(x * y);//url应该为:home/test?x=5&y=8 中间用:“&”
}
以路由参数取值时可用
public ActionResult test(string id)//取路由的参数值(id必须对应路由)
{
ViewBag.Message = "测试信息:" + id; // 这里可以使用home/test?id=regfgfdg或/home/test/regfgfdg
return View();//<h3>@ViewBag.Message</h3>显示于ViewBag.Message的值
}
42.3.3返回数据
public ActionResult test()//取路由的参数值(id必须对应路由)
{
//return Content("hello world","text/plain");//返回无格式正文字符串
//return JavaScript("<script>function foo {alert('foo');}</script>");//返回JavaScript脚本
//return Redirect("http://www.126.com");//跳转网站 重定向
//return RedirectToRoute(new { controller = "Home", action = "About" });//重定向路由
return File("~/Content/Images/timg.jpg", "image/jpg"); //返回文件对象
}
public ActionResult JsonDemo() //反回JSON数据
{
var m = new Menu
{
Id = ,
Text = "Grilled sausage with sauerkraut und potatoes",
Price = 12.90,
Category = "Main"
};
return Json(m, JsonRequestBehavior.AllowGet);
} //以下是menu类
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
public class Menu
{
public int Id { get; set; }
[Required, StringLength()]
public string Text { get; set; }
[DisplayName("Price"), DisplayFormat(DataFormatString = "{0:C}")]
public double Price { get; set; }
[DataType(DataType.Date)]
public DateTime Date { get; set; }
[StringLength()]
public string Category { get; set; }
}
42.4.1 向视图传递数据
在控制器里用ViewBag.data设置在视图里用@ViewBag.data取得,可以理解决ViewBag是一个类或数组,视图通过其进行设置
42.4.2 Razor语法
相关的语法 链接 以下是视图里的相关写法 在ASPX语法中使用<%:ViewBag.MyData %>
@{ //这里可以插入代码
@ViewBag.Message; //这里输出相关字符串
}
42.4.3强类型视图
public ActionResult test()//
{
var menus = new List<Menu>
{
new Menu { Id=, Text="Schweinsbraten mit Knödel und Sauerkraut",Price=6.9, Category="Main" },
new Menu { Id=, Text="Erdäpfelgulasch mit Tofu und Gebäck",Price=6.9, Category="Vegetarian" },
new Menu { Id=, Text="Tiroler Bauerngröst'l mit Spiegelei und Krautsalat", Price=6.9, Category="Main" }
};
return View(menus);//传递menus类给视图
}
using声明类结构,在视内用model关键之际定义模型,此模型的类型为IEnumerable<Menu>
@using MyWeb.Models
@model IEnumerable<Menu> <div>
<ul>
@foreach (var item in Model)
{
<li>@item.Text</li>
}
</ul>
</div>
42.4.4布局
如果视图不显示布局则使用用
@{
Layout = null;
}
1、默认布局
_ViewStart.cshtml为页面包含全部视图的默认配置 Layout属性设定为共享布局页
布局页:@ReanderBody()为主体 @ViewBag.Title为标提
2、使用分页
布局页写入:@RenderSection("PageNavigation", required: false)
视图页:在代码域中写入HTML分页代码
@section PageNavigation
{
<div>Navigation defined from the view</div>
}
42.4.5部分视图
部分视图示例要使用的结构类存放于Models
public class EventsAndMenus
{
private IEnumerable<Event> events = null;
public IEnumerable<Event> Events
{
get
{
return events ?? (events = new List<Event>()
{
new Event { Id=, Text="Formula 1 G.P. Abu Dhabi, Yas Marina",Day=new DateTime(, , ) },
new Event { Id=, Text="Formula 1 G.P. USA, Austin",Day = new DateTime(, , ) },
new Event { Id=, Text="Formula 1 G.P. Brasil, Sao Paulo",Day = new DateTime(, , ) }
}
);
}
}
private List<Menu> menus = null;
public IEnumerable<Menu> Menus
{
get
{
return menus ?? (menus = new List<Menu>()
{
new Menu { Id=, Text="Baby Back Barbecue Ribs", Price=16.9,
Category="Main" },
new Menu { Id=, Text="Chicken and Brown Rice Piaf", Price=12.9,
Category="Main" },
new Menu { Id=, Text="Chicken Miso Soup with Shiitake Mushrooms",
Price=6.9, Category="Soup" }
});
}
}
}
1、使用服务器端代码中的部分视图
下面的方法是把结构类数据通过控制器发给视图,视图通把结构类数据发给部分视图然后显示出来
// 控制器
public ActionResult test()//
{
return View(new EventsAndMenus());
} //视图,把结构体Model.Events传给viewtes部分视图
@model MyWeb.Models.EventsAndMenus @{
ViewBag.Title = "UseAPartialView21";
} <h2>UseAPartialView1</h2>
<div>this is the main view</div>
<div>
@Html.Partial("viewtest", Model.Events)
</div> //部分视图中:viewtest.cshtml
@using MyWeb.Models
@model IEnumerable<Event>
<h2>
@ViewBag.EventsTitle
</h2>
<table>
@foreach (var item in Model)
{
<tr>
<td>@item.Day.ToShortDateString()</td>
<td>@item.Text</td>
</tr>
}
</table>
2、从控制器中返回部分视图
以下是通过视图调用控制器方法的返回Html代码然后显示在视图里
//视图页:test1.cshtml,调用Viewtest方法的结果返回Html
@Html.Action("viewtest") //控制器:
public ActionResult viewtest()
{
ViewBag.EventsTitle = "Live Events";
return PartialView(new EventsAndMenus().Events);
} //部分视图:viewtest.cshtml
@using MyWeb.Models
@model IEnumerable<Event>
<h2>
@ViewBag.EventsTitle
</h2>
<table>
@foreach (var item in Model)
{
<tr>
<td>@item.Day.ToShortDateString()</td>
<td>@item.Text</td>
</tr>
}
</table>
3、在JQuery中调用部分视图
<script>
$(function () {
$("#getEvents").click(function () {
$("#events").load("/ViewsDemo/ShowEvents");
});
});
</script>
<button id="getEvents">Get Events</button>
<div id="events"></div>
42.5 从客户端提交数据
45.5.1模型绑定:方法是从视图提交表单的处理方法!直接模型绑定到Menu类中,然后返回视图
视图页:CreateMenu.cshtml
@{
ViewBag.Title = "Create Menu";
}
<h2>Create Menu</h2>
<form action="/SubmitData/CreateMenu" method="post">
<fieldset>
<legend>Menu1</legend>
<div>Id:</div>
<input name="id" />
<div>Text:</div>
<input name="text" />
<div>Price:</div>
<input name="price" />
<div>Category:</div>
<input name="category" />
<div></div>
<button type="submit">Submit</button>
</fieldset>
</form> 控制器:
[HttpPost]//这里限制方法为HttpPost请求
public ActionResult CreateMenu(Menu m)
{
//var m = new Menu { Id = id, Text = text, Price = price };
ViewBag.Info = string.Format(
"menu created: {0}, Price: {1}, category: {2}", m.Text, m.Price,
m.Category);
return View("Index");
} 视图页:index.cshtml
<h2>Index</h2>
上面代码可以改为:(以下方法如果有一些不应该更新的属性就不应该使用UpdateModel方法,否则用户可以恶意修改请求更新这些属性)
[HttpPost]//这里限制方法为HttpPost请求
public ActionResult CreateMenu2()
{
var m = new Menu();
UpdateModel<Menu>(m);//使用来自控制器的当前值提供程序的值更新指定的模型实例
ViewBag.Info = string.Format(
"menu created: {0}, Price: {1}, category: {2}", m.Text, m.Price,
m.Category);
return View("Index");
}
视图中改为:<form action="/SubmitData/CreateMenu2" method="post">
42.5.2注释与验证
在模型绑定中通过
if (ModelState.IsValid)//获取包含模型状态和模型绑定验证状态的模型状态字典对象。
来判定模型状态 模型状态通过[StringLength(10)]来验证
当模型为工具生成时,则在别外新增一个MenuMetadata属性与模型相同的有验证的!!
public class MenuMetadata
{
public int Id { get; set; }
[Required, StringLength()]
public string Text { get; set; }
[DisplayName("Price"), DisplayFormat(DataFormatString = "{0:C}")]
public double Price { get; set; }
[DataType(DataType.Date)]
public DateTime Date { get; set; }
[StringLength()]
public string Category { get; set; }
}
//在用工具生的模型的类前面添加
[MetadataType(typeof(ManuMatadata))]
public partial class Menu
{
}
42.6 HTML Helper
帮助文链接 相关说明请查网上 下面为常用的一些代码
- Html.Actionlink(显示名称,方法)链接到操作方法
- Html.Action(方法名)返回方法的结果的HTML代码
- Html.Partial(部分视图页,数据)把数据传递到部分视图页显示并返回
- Html.DisplayName(显示字符串)
- Html.Display('模型的名称') 显示模型中相关名称的数据
- Html.TextBox("Html控件id","值",new{required="required",maxlength=15,@class="CssDemo"}) 定义TextBox控件
- Html.EditorFor(m=>m)返回表达式中每个属性对应的Html元素
- Html.EditorForModel()返回模型中返有属性对应的Html元素
- @using Html.BeginForm("方法名", "控制器名", FormMethod.Post) {这里为表单,<input type="submit" name="BtnSubmit" value="Login" />} 把表单发送给控制器
- Html.RenderAction(方法) ,这里理解只返回方法的结果的意思
- Html.RenderPartial("部分视图",模型) 可以理解这里是返回视图,
42.6.4创建列表 (下拉列表)
public static class SelectListItemsExtensions //自定义扩展方法
{
public static IEnumerable<SelectListItem> ToSelectListItems(this IDictionary<int, string> dict, int selectedId)
{
return dict.Select(item =>
new SelectListItem
{
Selected = item.Key == selectedId,
Text = item.Value,
Value = item.Key.ToString()
}
);
}
}
public ActionResult test()//控制器方法
{
var cars = new Dictionary<int, string>();
cars.Add(, "Red Bull Racing");
cars.Add(, "Mclaren");
cars.Add(, "sgvd");
return View(cars.ToSelectListItems());
} //视图显示
@model IEnumerable<SelectListItem>
@Html.DropDownList("carslist", Model)
42.6.5强类型化的helper
从控制器传到视图时 相关的链接
@model MyWeb.Models.Menu
@Html.TextBoxFor(m=>m.Text)
24.6.7自定义helper
视图页:通过DispayDay(Model.Date)把模型传致上面的方法中
@model MyWed.Models.Menu
@helper DispayDay(DateTime day)
{
if (day < DateTime.Parse("2018-1-16 2:28:22"))
{
<span>历史日期</span>
}
@String.Format("{0:d}", day);
}
@Html.DisplayFor(m => m.Text)
@DispayDay(Model.Date)
24.6.8 模板
视图中通过DisplayForModel()来显示模板或DisplayFor(m => m.Date)
在视图下面新建DisplayTemplates文件夹,或在共享文件Shared下面新建DisplayTemplates方件夹,在DisplayTemplates方件夹新建类型模板,如Date类型:在目录下新建Date.cshtml,内容如下:
<div class="markRed">
@string.Format("{0:D}", Model)
</div>
Content里面Site.css更改样式:
.markRed{
color:#ff0000;
}
而模型里面
[DataType(DataType.Date)]
注:因EF的问题,转到学习"7天玩转MVC"
C#高级编程42章 MVC的更多相关文章
- C# 6 与 .NET Core 1.0 高级编程 - 38 章 实体框架核心(上)
译文,个人原创,转载请注明出处(C# 6 与 .NET Core 1.0 高级编程 - 38 章 实体框架核心(上)),不对的地方欢迎指出与交流. 章节出自<Professional C# 6 ...
- C# 6 与 .NET Core 1.0 高级编程 - 38 章 实体框架核心(下)
译文,个人原创,转载请注明出处(C# 6 与 .NET Core 1.0 高级编程 - 38 章 实体框架核心(下)),不对的地方欢迎指出与交流. 章节出自<Professional C# 6 ...
- C# 6 与 .NET Core 1.0 高级编程 - 39 章 Windows 服务(下)
译文,个人原创,转载请注明出处(C# 6 与 .NET Core 1.0 高级编程 - 39 章 Windows 服务(下)),不对的地方欢迎指出与交流. 章节出自<Professional C ...
- C#高级编程9-第12章 动态语言扩展
C#高级编程9-第12章 动态语言扩展 dynamic t = new ExpandoObject(); t.Abc = "abc"; t.Value = ; Console.Wr ...
- C# 6 与 .NET Core 1.0 高级编程 - 37 章 ADO.NET
译文,个人原创,转载请注明出处,有不对的地方欢迎指出与交流. 英文原文:Professional C# 6 and .NET Core 1.0 - 37 ADO.NET --------------- ...
- C# 6 与 .NET Core 1.0 高级编程 - 39 章 Windows 服务(上)
译文,个人原创,转载请注明出处(C# 6 与 .NET Core 1.0 高级编程 - 39 章 Windows 服务(上)),不对的地方欢迎指出与交流. 章节出自<Professional C ...
- C#高级编程9-第8章 委托、lamdba表达式和事件
委托.lamdba表达式和事件 1.引用方法 函数指针是一个指向内存位置的指针,不是类型安全的.无法判断实际指向.参数和返回类型也无从知晓..NET委托是类型安全的.定义了返回类型和参数类型,不仅包含 ...
- C#高级编程9-第13章 异步编程
异步编程 1)异步编程的重要性 在C#5.0中提供了关键字:async和await 使用异步编程后台运行方法调用,程序的运行过程中就不会一直处于等待中.便于用户继续操作. 异步编程有3种模式:异步模式 ...
- C#高级编程9-第1章.NET体系结构
C#与NET的关系 C#编写的所有代码必须使用.NET FrameWork运行 C#是一种语言,但它本身不是.NET的一部分 C#一些特性,.NET不支持,.NET一些特性,C#不支持 公共语言运行库 ...
随机推荐
- NOIp 数学知识点总结
推荐阅读 NOIp 基础数论知识点总结: https://www.cnblogs.com/greyqz/p/number.html 排列组合 常用公式 排列:\[\displaystyle A_n^m ...
- HTTP请求时候总是设置的两个参数ConnectionTimeOut和SocketTimeOut
在HTTP请求时候总是设置两个参数,就是连接超时和Socket超时 public static final String SO_TIMEOUT = "http.socket.timeout& ...
- “美登杯”上海市高校大学生程序设计 E. 小花梨的数组 (线段树)
https://acm.ecnu.edu.cn/contest/173/problem/E/ 分析: 考虑这样一种情况,如果对一个点连续地做几次乘操作,那么之后紧跟着的除操作只需要将乘操作的次数减少即 ...
- C#调取接口时报错:服务器提交了协议冲突. Section=ResponseStatusLine
private Dictionary<string, Object> GetLocation(string imei) { #region===代码=== string serviceAd ...
- Eclipse + pydev插件
在Eclipse中安装pydev插件 启动Eclipse, 点击Help->Install New Software... 在弹出的对话框中,点Add 按钮. Name中填:Pydev, ...
- ping局域网主机得到外网IP或另一网段IP
症状::两个笔记本连接到同一个路由器上, 一个ip是 192.168.1.100,主机名是Lenovo-A, 另一个是192.168.1.109,主机名是Lenovo-B 在Lenovo-A 上pin ...
- Dedecms织梦后台登陆验证码不显示几种解决方法
Dedecms织梦后台登陆验证码不显示几种解决方法,服务器所造成的验证码不显示问题看这里: 方法一:查看服务器的php版本是否与程序版本兼容(织梦程序PHP版本查看方法:打开www.96net.com ...
- A AFei Loves Magic
链接:https://ac.nowcoder.com/acm/contest/338/A来源:牛客网 题目描述 AFei is a trainee magician who likes to stud ...
- Leetcode Lect3 时间复杂度/空间复杂度
时间复杂度 复杂度 可能对应的算法 备注 O(1) 位运算 常数级复杂度,一般面试中不会有 O(logn) 二分法,倍增法,快速幂算法,辗转相除法 O(n) 枚举法,双指针算法,单调栈算法,KMP ...
- k3 cloud中列表字段汇总类型中设置了汇总以后没有显示出汇总值
处理方法,需要bos中的分组列信息中设置求和: 选择对应字段将其从左侧添加到右侧 方法二: 直接针对[价税合计]字段的列表汇总类型进行设置,步骤如下图所示