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="2009",month="10",day="10"},
               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 = 3,
        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(25)]
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(10)]
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=1, Text="Schweinsbraten mit Knödel und Sauerkraut",Price=6.9, Category="Main" },
       new Menu { Id=2, Text="Erdäpfelgulasch mit Tofu und Gebäck",Price=6.9, Category="Vegetarian" },
       new Menu { Id=3, 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=1, Text="Formula 1 G.P. Abu Dhabi, Yas Marina",Day=new DateTime(2014, 10, 26) },
          new Event { Id=2, Text="Formula 1 G.P. USA, Austin",Day = new DateTime(2014, 11, 9) },
          new Event { Id=3, Text="Formula 1 G.P. Brasil, Sao Paulo",Day = new DateTime(2014, 11, 30) }
        }
                );
            }
        }
        private List<Menu> menus = null;
        public IEnumerable<Menu> Menus
        {
            get
            {
                return menus ?? (menus = new List<Menu>()
        {
          new Menu { Id=1, Text="Baby Back Barbecue Ribs", Price=16.9,
              Category="Main" },
          new Menu { Id=2, Text="Chicken and Brown Rice Piaf", Price=12.9,
              Category="Main" },
          new Menu { Id=3, 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(25)]
    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(10)]
    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(1, "Red Bull Racing");
cars.Add(2, "Mclaren");
cars.Add(3, "sgvd");
return View(cars.ToSelectListItems(3));
}

//视图显示
@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"

posted @ 2018-01-17 08:17  天祈笨笨  阅读(378)  评论(0编辑  收藏  举报